From 5fb12406ada5d0e8b6da18973533cf611ba21d30 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 16 May 2024 15:19:50 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .rubocop_todo/rspec/before_all.yml | 5 - .../javascripts/diffs/store/mutations.js | 5 +- app/assets/javascripts/diffs/store/utils.js | 3 +- .../javascripts/graphql_shared/constants.js | 1 + .../details_page/signature_details_modal.vue | 82 ++++++++++ .../components/details_page/tags_list_row.vue | 18 ++- .../get_manifest_details.query.graphql | 6 + .../projects/settings/repository/form.js | 22 ++- .../settings/api/access_dropdown_api.js | 4 + .../settings/components/access_dropdown.vue | 121 ++++++++------- .../protected_branch_create.js | 5 + .../projects/protected_refs_controller.rb | 6 +- .../settings/branch_rules_controller.rb | 1 - .../settings/merge_requests_controller.rb | 4 - app/finders/packages/conan/package_finder.rb | 13 +- app/helpers/protected_branches_helper.rb | 2 +- app/models/ci/pipeline.rb | 2 +- app/models/packages/conan/metadatum.rb | 11 +- app/models/packages/conan/package.rb | 47 ++++++ app/models/packages/package.rb | 32 +--- app/policies/project_policy.rb | 2 + .../packages/detail/package_presenter.rb | 2 +- .../conan/single_package_search_service.rb | 4 +- .../settings/repository/show.html.haml | 1 + app/workers/pause_control/resume_worker.rb | 1 - .../beta/approval_rules_drawer.yml | 9 -- .../ops/zoekt_pause_indexing.yml | 8 - data/whats_new/202505160001_17_0.yml | 120 ++++++++++++++ db/docs/packages_packages.yml | 1 + ...nup_bigint_conversions_for_ci_pipelines.rb | 17 ++ db/schema_migrations/20240513042657 | 1 + db/structure.sql | 12 -- doc/api/discussions.md | 4 +- doc/api/draft_notes.md | 4 +- doc/api/openapi/openapi_v2.yaml | 2 + doc/operations/error_tracking.md | 2 +- doc/operations/sentry_error_tracking.md | 2 +- doc/security/token_overview.md | 2 +- doc/user/analytics/value_streams_dashboard.md | 6 +- doc/user/group/devops_adoption/index.md | 2 + doc/user/product_analytics/index.md | 6 + doc/user/profile/index.md | 19 ++- .../project/merge_requests/approvals/rules.md | 27 +--- doc/user/search/exact_code_search.md | 9 +- lib/api/helpers/packages/conan/api_helpers.rb | 18 +-- .../pause_control/strategies/zoekt.rb | 2 +- locale/gitlab.pot | 22 ++- package.json | 2 +- qa/Gemfile | 2 +- qa/Gemfile.lock | 4 +- spec/factories/packages/conan/packages.rb | 34 ++++ spec/factories/packages/packages.rb | 32 ---- ...comments_on_whitespace_hidden_diff_spec.rb | 131 +++++++++++----- spec/features/protected_branches_spec.rb | 113 ++------------ .../signature_details_modal_spec.js | 146 ++++++++++++++++++ .../details_page/tags_list_row_spec.js | 39 +++++ .../components/access_dropdown_spec.js | 13 ++ spec/lib/bulk_imports/object_counter_spec.rb | 2 +- .../snippets_repository_pipeline_spec.rb | 2 +- .../importers/issue_importer_spec.rb | 2 +- .../importers/issue_notes_importer_spec.rb | 2 +- .../importers/issues_importer_spec.rb | 4 +- .../importers/issues_notes_importer_spec.rb | 4 +- .../importers/lfs_objects_importer_spec.rb | 4 +- .../importers/pull_request_importer_spec.rb | 2 +- .../pull_request_notes_importer_spec.rb | 2 +- .../importers/pull_requests_importer_spec.rb | 4 +- .../pull_requests_notes_importer_spec.rb | 4 +- .../bitbucket_import/user_finder_spec.rb | 2 +- .../importers/lfs_objects_importer_spec.rb | 4 +- .../importers/pull_requests_importer_spec.rb | 4 +- .../user_finder_spec.rb | 2 +- spec/lib/gitlab/git/repository_spec.rb | 2 +- .../github_import/clients/proxy_spec.rb | 2 +- .../attachments/issues_importer_spec.rb | 2 +- .../merge_requests_importer_spec.rb | 2 +- .../attachments/notes_importer_spec.rb | 2 +- .../attachments/releases_importer_spec.rb | 2 +- .../importer/events/cross_referenced_spec.rb | 2 +- .../importer/issue_event_importer_spec.rb | 3 +- .../importer/issue_importer_spec.rb | 2 +- .../importer/labels_importer_spec.rb | 3 +- .../importer/milestones_importer_spec.rb | 3 +- .../importer/pull_request_importer_spec.rb | 2 +- .../pull_requests/merged_by_importer_spec.rb | 3 +- .../pull_requests/review_importer_spec.rb | 3 +- .../review_request_importer_spec.rb | 2 +- .../github_import/issuable_finder_spec.rb | 2 +- .../gitlab/github_import/label_finder_spec.rb | 2 +- .../github_import/milestone_finder_spec.rb | 2 +- .../representation/diff_note_spec.rb | 2 +- .../diff_notes/discussion_id_spec.rb | 2 +- .../gitlab/jira_import/base_importer_spec.rb | 4 +- .../jira_import/issues_importer_spec.rb | 4 +- .../jira_import/labels_importer_spec.rb | 4 +- .../pause_control/client_spec.rb | 4 +- .../pause_control/server_spec.rb | 4 +- .../models/bulk_imports/export_status_spec.rb | 2 +- spec/models/packages/conan/metadatum_spec.rb | 12 +- spec/models/packages/conan/package_spec.rb | 102 ++++++++++++ spec/models/packages/package_spec.rb | 88 ----------- .../packages/conan/package_presenter_spec.rb | 2 +- .../packages/detail/package_presenter_spec.rb | 2 +- .../conan/create_package_service_spec.rb | 18 ++- spec/support/helpers/test_env.rb | 1 + .../policies/project_policy_shared_context.rb | 2 + .../protected_branches_shared_examples.rb | 100 ++++++++++++ .../api/conan_packages_shared_examples.rb | 2 +- .../rescheduling_methods_spec.rb | 4 +- .../stage/import_issues_worker_spec.rb | 4 +- yarn.lock | 8 +- 111 files changed, 1102 insertions(+), 565 deletions(-) delete mode 100644 .rubocop_todo/rspec/before_all.yml create mode 100644 app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/signature_details_modal.vue create mode 100644 app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_manifest_details.query.graphql create mode 100644 app/models/packages/conan/package.rb delete mode 100644 config/feature_flags/beta/approval_rules_drawer.yml delete mode 100644 config/feature_flags/ops/zoekt_pause_indexing.yml create mode 100644 data/whats_new/202505160001_17_0.yml create mode 100644 db/post_migrate/20240513042657_cleanup_bigint_conversions_for_ci_pipelines.rb create mode 100644 db/schema_migrations/20240513042657 create mode 100644 spec/factories/packages/conan/packages.rb create mode 100644 spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/signature_details_modal_spec.js create mode 100644 spec/models/packages/conan/package_spec.rb create mode 100644 spec/support/shared_examples/features/project/protected_branches_shared_examples.rb diff --git a/.rubocop_todo/rspec/before_all.yml b/.rubocop_todo/rspec/before_all.yml deleted file mode 100644 index f1b7ac64bdd..00000000000 --- a/.rubocop_todo/rspec/before_all.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -# Cop supports --autocorrect. -RSpec/BeforeAll: - Exclude: - - 'ee/spec/support/shared_examples/finders/security/findings_finder_shared_examples.rb' diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js index 2cc2e13648f..441dc7389a3 100644 --- a/app/assets/javascripts/diffs/store/mutations.js +++ b/app/assets/javascripts/diffs/store/mutations.js @@ -168,7 +168,10 @@ export default { const files = prepareDiffData({ diff: data }); const [newFileData] = files.filter((f) => f.file_hash === file.file_hash); const selectedFile = state.diffFiles.find((f) => f.file_hash === file.file_hash); - Object.assign(selectedFile, { ...newFileData }); + Object.assign(selectedFile, { + ...newFileData, + whitespaceOnlyChange: selectedFile.whitespaceOnlyChange, + }); }, [types.SET_LINE_DISCUSSIONS_FOR_FILE](state, { discussion, diffPositionByLineCode, hash }) { diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js index ad8cacf8504..0ca4cf96615 100644 --- a/app/assets/javascripts/diffs/store/utils.js +++ b/app/assets/javascripts/diffs/store/utils.js @@ -156,7 +156,7 @@ export function getFormData(params) { width: params.width, height: params.height, line_range: lineRange, - ignore_whitespace_change: !showWhitespace, + ignore_whitespace_change: diffFile.whitespaceOnlyChange ? false : !showWhitespace, }); const postData = { @@ -390,6 +390,7 @@ function finalizeDiffFile(file) { isLoadingFullFile: false, discussions: [], renderingLines: false, + whitespaceOnlyChange: file.viewer?.whitespace_only, }); return file; diff --git a/app/assets/javascripts/graphql_shared/constants.js b/app/assets/javascripts/graphql_shared/constants.js index aac92ff8ab9..62204e340cc 100644 --- a/app/assets/javascripts/graphql_shared/constants.js +++ b/app/assets/javascripts/graphql_shared/constants.js @@ -7,6 +7,7 @@ export const TYPENAME_CI_PIPELINE = 'Ci::Pipeline'; export const TYPENAME_CI_RUNNER = 'Ci::Runner'; export const TYPENAME_CI_VARIABLE = 'Ci::Variable'; export const TYPENAME_COMMIT_STATUS = 'CommitStatus'; +export const TYPENAME_CONTAINER_REPOSITORY = 'ContainerRepository'; export const TYPENAME_CRM_CONTACT = 'CustomerRelations::Contact'; export const TYPENAME_CRM_ORGANIZATION = 'CustomerRelations::Organization'; export const TYPENAME_DESIGN_VERSION = 'DesignManagement::Version'; diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/signature_details_modal.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/signature_details_modal.vue new file mode 100644 index 00000000000..c5be25e8c4b --- /dev/null +++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/signature_details_modal.vue @@ -0,0 +1,82 @@ + + + diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue index eaae04c132a..3f61d7f22e7 100644 --- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue +++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue @@ -6,6 +6,7 @@ import { GlIcon, GlDisclosureDropdown, GlBadge, + GlLink, } from '@gitlab/ui'; import { formatDate } from '~/lib/utils/datetime_utility'; import { numberToHumanSize } from '~/lib/utils/number_utils'; @@ -27,6 +28,7 @@ import { MORE_ACTIONS_TEXT, COPY_IMAGE_PATH_TITLE, } from '../../constants/index'; +import SignatureDetailsModal from './signature_details_modal.vue'; export default { components: { @@ -35,10 +37,12 @@ export default { GlIcon, GlDisclosureDropdown, GlBadge, + GlLink, ListItem, ClipboardButton, TimeAgoTooltip, DetailsRow, + SignatureDetailsModal, }, directives: { GlTooltip: GlTooltipDirective, @@ -283,7 +287,7 @@ export default { diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_manifest_details.query.graphql b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_manifest_details.query.graphql new file mode 100644 index 00000000000..37f1410ecbd --- /dev/null +++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_manifest_details.query.graphql @@ -0,0 +1,6 @@ +query getManifestDetails($id: ContainerRepositoryID!, $reference: String!) { + containerRepository(id: $id) { + id + manifest(reference: $reference) + } +} diff --git a/app/assets/javascripts/pages/projects/settings/repository/form.js b/app/assets/javascripts/pages/projects/settings/repository/form.js index f64de693188..4735e7faf30 100644 --- a/app/assets/javascripts/pages/projects/settings/repository/form.js +++ b/app/assets/javascripts/pages/projects/settings/repository/form.js @@ -10,12 +10,18 @@ import ProtectedTagEditList from '~/protected_tags/protected_tag_edit_list'; import initSettingsPanels from '~/settings_panels'; export default () => { - new ProtectedTagCreate({ hasLicense: false }); - new ProtectedTagEditList({ hasLicense: false }); - initDeployKeys(); - initSettingsPanels(); - new ProtectedBranchCreate({ hasLicense: false }); - new ProtectedBranchEditList(); - initDatePicker(); // Used for deploy token "expires at" field - fileUpload('.js-choose-file', '.js-object-map-input'); + if (gon.limit_repository_settings?.includes('protected_branches')) { + new ProtectedBranchCreate({ hasLicense: false }); + new ProtectedBranchEditList(); + } else { + new ProtectedTagCreate({ hasLicense: false }); + new ProtectedTagEditList({ hasLicense: false }); + initDeployKeys(); + initSettingsPanels(); + new ProtectedBranchCreate({ hasLicense: false }); + new ProtectedBranchEditList(); + initDatePicker(); // Used for deploy token "expires at" field + fileUpload('.js-choose-file', '.js-object-map-input'); + new ProtectedBranchEditList(); + } }; diff --git a/app/assets/javascripts/projects/settings/api/access_dropdown_api.js b/app/assets/javascripts/projects/settings/api/access_dropdown_api.js index 89ae2a82c6d..52a84648b6d 100644 --- a/app/assets/javascripts/projects/settings/api/access_dropdown_api.js +++ b/app/assets/javascripts/projects/settings/api/access_dropdown_api.js @@ -35,6 +35,10 @@ export const getGroups = ({ withProjectAccess = false }) => { }; export const getDeployKeys = (query) => { + if (gon.limit_repository_settings) { + return { data: [] }; + } + return axios.get(buildUrl(gon.relative_url_root || '', DEPLOY_KEYS_PATH), { params: { search: query, diff --git a/app/assets/javascripts/projects/settings/components/access_dropdown.vue b/app/assets/javascripts/projects/settings/components/access_dropdown.vue index c863973cd2e..772f43bc9df 100644 --- a/app/assets/javascripts/projects/settings/components/access_dropdown.vue +++ b/app/assets/javascripts/projects/settings/components/access_dropdown.vue @@ -230,37 +230,42 @@ export default { this.initialLoading = initial; this.loading = true; + let asyncKeysUsersAndGroups; + if (this.hasLicense) { - Promise.all([ - getDeployKeys(this.query), - getUsers(this.query), - this.groups.length - ? Promise.resolve({ data: this.groups }) - : getGroups({ withProjectAccess: this.groupsWithProjectAccess }), - ]) - .then(([deployKeysResponse, usersResponse, groupsResponse]) => { - this.consolidateData(deployKeysResponse.data, usersResponse.data, groupsResponse.data); - this.setSelected({ initial }); - }) - .catch(() => - createAlert({ message: __('Failed to load groups, users and deploy keys.') }), - ) - .finally(() => { - this.initialLoading = false; - this.loading = false; - }); + if (gon.limit_repository_settings?.includes('protected_branches')) { + asyncKeysUsersAndGroups = Promise.all([ + null, + getUsers(this.query), + this.groups.length + ? this.groups + : getGroups({ withProjectAccess: this.groupsWithProjectAccess }), + ]); + } else { + asyncKeysUsersAndGroups = Promise.all([ + getDeployKeys(this.query), + getUsers(this.query), + this.groups.length + ? this.groups + : getGroups({ withProjectAccess: this.groupsWithProjectAccess }), + ]); + } } else { - getDeployKeys(this.query) - .then((deployKeysResponse) => { - this.consolidateData(deployKeysResponse.data); - this.setSelected({ initial }); - }) - .catch(() => createAlert({ message: __('Failed to load deploy keys.') })) - .finally(() => { - this.initialLoading = false; - this.loading = false; - }); + asyncKeysUsersAndGroups = Promise.all([getDeployKeys(this.query), null, null]); } + + asyncKeysUsersAndGroups + .then((data) => { + this.consolidateData(...data); + this.setSelected({ initial }); + }) + .catch(() => { + createAlert({ message: __('Failed to load data.') }); + }) + .finally(() => { + this.initialLoading = false; + this.loading = false; + }); }, consolidateData(deployKeysResponse, usersResponse = [], groupsResponse = []) { // This re-assignment is intentional as level.type property is being used for comparision, @@ -269,42 +274,48 @@ export default { this.roles = this.accessLevelsData.map((role) => ({ ...role, type: LEVEL_TYPES.ROLE })); if (this.hasLicense) { - this.groups = groupsResponse.map((group) => ({ ...group, type: LEVEL_TYPES.GROUP })); + this.groups = groupsResponse + ? groupsResponse.data.map((group) => ({ ...group, type: LEVEL_TYPES.GROUP })) + : []; // Has to be checked against server response // because the selected item can be in filter results if (this.showUsers) { - this.users = usersResponse.map(({ id, name, username, avatar_url }) => ({ - id, - name, - username, - avatar_url, - type: LEVEL_TYPES.USER, - })); + this.users = usersResponse + ? usersResponse.data.map(({ id, name, username, avatar_url }) => ({ + id, + name, + username, + avatar_url, + type: LEVEL_TYPES.USER, + })) + : []; } } - this.deployKeys = deployKeysResponse.map((response) => { - const { - id, - fingerprint, - fingerprint_sha256: fingerprintSha256, - title, - owner: { avatar_url, name, username }, - } = response; + this.deployKeys = deployKeysResponse + ? deployKeysResponse.data.map((response) => { + const { + id, + fingerprint, + fingerprint_sha256: fingerprintSha256, + title, + owner: { avatar_url, name, username }, + } = response; - const availableFingerprint = fingerprintSha256 || fingerprint; - const shortFingerprint = `(${availableFingerprint.substring(0, 14)}...)`; + const availableFingerprint = fingerprintSha256 || fingerprint; + const shortFingerprint = `(${availableFingerprint.substring(0, 14)}...)`; - return { - id, - title: title.concat(' ', shortFingerprint), - avatar_url, - fullname: name, - username, - type: LEVEL_TYPES.DEPLOY_KEY, - }; - }); + return { + id, + title: title.concat(' ', shortFingerprint), + avatar_url, + fullname: name, + username, + type: LEVEL_TYPES.DEPLOY_KEY, + }; + }) + : []; }, setSelected({ initial } = {}) { if (initial) { diff --git a/app/assets/javascripts/protected_branches/protected_branch_create.js b/app/assets/javascripts/protected_branches/protected_branch_create.js index 612f801300e..2fb53be33b2 100644 --- a/app/assets/javascripts/protected_branches/protected_branch_create.js +++ b/app/assets/javascripts/protected_branches/protected_branch_create.js @@ -147,6 +147,11 @@ export default class ProtectedBranchCreate { if (!this.hasProtectedBranchSuccessAlert()) { return; } + + if (!document.getElementById('branch-rules')) { + return; + } + this.expandAndScroll(PROTECTED_BRANCHES_ANCHOR); this.createSuccessAlert(); diff --git a/app/controllers/projects/protected_refs_controller.rb b/app/controllers/projects/protected_refs_controller.rb index e57aac1ff7f..e6adabd2662 100644 --- a/app/controllers/projects/protected_refs_controller.rb +++ b/app/controllers/projects/protected_refs_controller.rb @@ -4,7 +4,7 @@ class Projects::ProtectedRefsController < Projects::ApplicationController include RepositorySettingsRedirect # Authorize - before_action :authorize_admin_project! + before_action :authorize_admin_protected_refs! before_action :load_protected_ref, only: [:show, :update, :destroy] layout "project_settings" @@ -51,6 +51,10 @@ class Projects::ProtectedRefsController < Projects::ApplicationController protected + def authorize_admin_protected_refs! + authorize_admin_project! + end + def create_service_class service_namespace::CreateService end diff --git a/app/controllers/projects/settings/branch_rules_controller.rb b/app/controllers/projects/settings/branch_rules_controller.rb index ec8877b0ad8..ab537ea42b7 100644 --- a/app/controllers/projects/settings/branch_rules_controller.rb +++ b/app/controllers/projects/settings/branch_rules_controller.rb @@ -5,7 +5,6 @@ module Projects class BranchRulesController < Projects::ApplicationController before_action :authorize_admin_project! before_action do - push_frontend_feature_flag(:approval_rules_drawer, @project) push_frontend_feature_flag(:edit_branch_rules, @project) end diff --git a/app/controllers/projects/settings/merge_requests_controller.rb b/app/controllers/projects/settings/merge_requests_controller.rb index 8b3700df7d0..2724e2d9eec 100644 --- a/app/controllers/projects/settings/merge_requests_controller.rb +++ b/app/controllers/projects/settings/merge_requests_controller.rb @@ -11,10 +11,6 @@ module Projects feature_category :code_review_workflow - before_action do - push_frontend_feature_flag(:approval_rules_drawer, @project) - end - def update result = ::Projects::UpdateService.new(@project, current_user, project_params).execute diff --git a/app/finders/packages/conan/package_finder.rb b/app/finders/packages/conan/package_finder.rb index 161a3d0d409..3671a13a2cb 100644 --- a/app/finders/packages/conan/package_finder.rb +++ b/app/finders/packages/conan/package_finder.rb @@ -12,7 +12,7 @@ module Packages end def execute - return ::Packages::Package.none unless query + return ::Packages::Conan::Package.none unless query packages end @@ -23,7 +23,6 @@ module Packages def packages base - .conan .installable .preload_conan_metadatum .with_name_like(query) @@ -31,15 +30,7 @@ module Packages end def base - project ? packages_of_project : packages_for_current_user - end - - def packages_of_project - project.packages - end - - def packages_for_current_user - Packages::Package.for_projects(projects_visible_to_current_user) + ::Packages::Conan::Package.for_projects(project || projects_visible_to_current_user) end def projects_visible_to_current_user diff --git a/app/helpers/protected_branches_helper.rb b/app/helpers/protected_branches_helper.rb index bd2a4d1170d..113dfca7d6f 100644 --- a/app/helpers/protected_branches_helper.rb +++ b/app/helpers/protected_branches_helper.rb @@ -5,7 +5,7 @@ module ProtectedBranchesHelper if protected_branch_entity.is_a?(Group) can?(current_user, :admin_group, protected_branch_entity) else - can?(current_user, :admin_project, protected_branch_entity) + can?(current_user, :admin_protected_branch, protected_branch_entity) end end diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index f56d15098e3..57fa0651ebe 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -19,7 +19,7 @@ module Ci include FastDestroyAll::Helpers include IgnorableColumns - ignore_column :id_convert_to_bigint, remove_with: '16.3', remove_after: '2023-08-22' + ignore_column :id_convert_to_bigint, remove_with: '17.2', remove_after: '2024-06-15' MAX_OPEN_MERGE_REQUESTS_REFS = 4 diff --git a/app/models/packages/conan/metadatum.rb b/app/models/packages/conan/metadatum.rb index cc416098a8b..f489b1bd258 100644 --- a/app/models/packages/conan/metadatum.rb +++ b/app/models/packages/conan/metadatum.rb @@ -3,7 +3,7 @@ class Packages::Conan::Metadatum < ApplicationRecord NONE_VALUE = '_' - belongs_to :package, -> { where(package_type: :conan) }, inverse_of: :conan_metadatum + belongs_to :package, class_name: 'Packages::Conan::Package', inverse_of: :conan_metadatum validates :package, presence: true @@ -12,7 +12,6 @@ class Packages::Conan::Metadatum < ApplicationRecord presence: true, format: { with: Gitlab::Regex.conan_recipe_user_channel_regex } - validate :conan_package_type validate :username_channel_none_values def recipe @@ -42,15 +41,9 @@ class Packages::Conan::Metadatum < ApplicationRecord private - def conan_package_type - unless package&.conan? - errors.add(:base, _('Package type must be Conan')) - end - end - def username_channel_none_values self.class.validate_username_and_channel(package_username, package_channel) do |none_field| - errors.add("package_#{none_field}".to_sym, _("can't be solely blank")) + errors.add(:"package_#{none_field}", _("can't be solely blank")) end end end diff --git a/app/models/packages/conan/package.rb b/app/models/packages/conan/package.rb new file mode 100644 index 00000000000..a5bb83f71de --- /dev/null +++ b/app/models/packages/conan/package.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module Packages + module Conan + class Package < Packages::Package + self.allow_legacy_sti_class = true + + INSTALLABLE_STATUSES = %i[default hidden].freeze + + has_one :conan_metadatum, inverse_of: :package, class_name: 'Packages::Conan::Metadatum' + + accepts_nested_attributes_for :conan_metadatum + + delegate :recipe, :recipe_path, to: :conan_metadatum, prefix: :conan + + validates :name, :version, format: { with: Gitlab::Regex.conan_recipe_component_regex } + validate :valid_conan_package_recipe + + scope :with_conan_channel, ->(package_channel) do + joins(:conan_metadatum).where(packages_conan_metadata: { package_channel: package_channel }) + end + + scope :with_conan_username, ->(package_username) do + joins(:conan_metadatum).where(packages_conan_metadata: { package_username: package_username }) + end + + scope :preload_conan_metadatum, -> { preload(:conan_metadatum) } + + private + + def valid_conan_package_recipe + return unless self.class + .for_projects(project) + .includes(:conan_metadatum) + .not_pending_destruction + .with_name(name) + .with_version(version) + .with_conan_channel(conan_metadatum.package_channel) + .with_conan_username(conan_metadatum.package_username) + .id_not_in(id) + .exists? + + errors.add(:base, _('Package recipe already exists')) + end + end + end +end diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb index 698d7493c8b..52ec88a3f22 100644 --- a/app/models/packages/package.rb +++ b/app/models/packages/package.rb @@ -45,7 +45,6 @@ class Packages::Package < ApplicationRecord has_many :installable_nuget_package_files, -> { installable.with_nuget_format }, class_name: 'Packages::PackageFile', inverse_of: :package has_many :dependency_links, inverse_of: :package, class_name: 'Packages::DependencyLink' has_many :tags, inverse_of: :package, class_name: 'Packages::Tag' - has_one :conan_metadatum, inverse_of: :package, class_name: 'Packages::Conan::Metadatum' has_one :pypi_metadatum, inverse_of: :package, class_name: 'Packages::Pypi::Metadatum' has_one :maven_metadatum, inverse_of: :package, class_name: 'Packages::Maven::Metadatum' has_one :nuget_metadatum, inverse_of: :package, class_name: 'Packages::Nuget::Metadatum' @@ -60,11 +59,9 @@ class Packages::Package < ApplicationRecord has_one :debian_distribution, through: :debian_publication, source: :distribution, inverse_of: :packages, class_name: 'Packages::Debian::ProjectDistribution' has_many :matching_package_protection_rules, -> (package) { where(package_type: package.package_type).for_package_name(package.name) }, through: :project, source: :package_protection_rules - accepts_nested_attributes_for :conan_metadatum accepts_nested_attributes_for :debian_publication accepts_nested_attributes_for :maven_metadatum - delegate :recipe, :recipe_path, to: :conan_metadatum, prefix: :conan delegate :codename, :suite, to: :debian_distribution, prefix: :debian_distribution delegate :target_sha, to: :composer_metadatum, prefix: :composer @@ -80,11 +77,9 @@ class Packages::Package < ApplicationRecord }, unless: -> { pending_destruction? || conan? } - validate :valid_conan_package_recipe, if: :conan? validate :valid_composer_global_name, if: :composer? validate :npm_package_already_taken, if: :npm? - validates :name, format: { with: Gitlab::Regex.conan_recipe_component_regex }, if: :conan? validates :name, format: { with: Gitlab::Regex.generic_package_name_regex }, if: :generic? validates :name, format: { with: Gitlab::Regex.helm_package_regex }, if: :helm? validates :name, format: { with: Gitlab::Regex.npm_package_name_regex, message: Gitlab::Regex.npm_package_name_regex_message }, if: :npm? @@ -93,7 +88,6 @@ class Packages::Package < ApplicationRecord validates :name, format: { with: Gitlab::Regex.debian_package_name_regex }, if: :debian_package? validates :name, inclusion: { in: [Packages::Debian::INCOMING_PACKAGE_NAME] }, if: :debian_incoming? validates :version, format: { with: Gitlab::Regex.nuget_version_regex }, if: :nuget? - validates :version, format: { with: Gitlab::Regex.conan_recipe_component_regex }, if: :conan? validates :version, format: { with: Gitlab::Regex.maven_version_regex }, if: -> { version? && maven? } validates :version, format: { with: Gitlab::Regex.pypi_version_regex }, if: :pypi? validates :version, format: { with: Gitlab::Regex.helm_version_regex }, if: :helm? @@ -154,13 +148,6 @@ class Packages::Package < ApplicationRecord scope :including_dependency_links, -> { includes(dependency_links: :dependency) } scope :including_dependency_links_with_nuget_metadatum, -> { includes(dependency_links: [:dependency, :nuget_metadatum]) } - scope :with_conan_channel, ->(package_channel) do - joins(:conan_metadatum).where(packages_conan_metadata: { package_channel: package_channel }) - end - scope :with_conan_username, ->(package_username) do - joins(:conan_metadatum).where(packages_conan_metadata: { package_username: package_username }) - end - scope :with_debian_codename, ->(codename) do joins(:debian_distribution).where(Packages::Debian::ProjectDistribution.table_name => { codename: codename }) end @@ -178,7 +165,6 @@ class Packages::Package < ApplicationRecord scope :preload_npm_metadatum, -> { preload(:npm_metadatum) } scope :preload_nuget_metadatum, -> { preload(:nuget_metadatum) } scope :preload_pypi_metadatum, -> { preload(:pypi_metadatum) } - scope :preload_conan_metadatum, -> { preload(:conan_metadatum) } scope :with_npm_scope, ->(scope) do npm.where("position('/' in packages_packages.name) > 0 AND split_part(packages_packages.name, '/', 1) = :package_scope", package_scope: "@#{sanitize_sql_like(scope)}") @@ -232,7 +218,8 @@ class Packages::Package < ApplicationRecord def self.inheritance_column_to_class_map = { ml_model: 'Packages::MlModel::Package', golang: 'Packages::Go::Package', - rubygems: 'Packages::Rubygems::Package' + rubygems: 'Packages::Rubygems::Package', + conan: 'Packages::Conan::Package' }.freeze def self.only_maven_packages_with_path(path, use_cte: false) @@ -401,21 +388,6 @@ class Packages::Package < ApplicationRecord composer? && !Gitlab::Regex.composer_dev_version_regex.match(version.to_s) end - def valid_conan_package_recipe - recipe_exists = project.packages - .conan - .includes(:conan_metadatum) - .not_pending_destruction - .with_name(name) - .with_version(version) - .with_conan_channel(conan_metadatum.package_channel) - .with_conan_username(conan_metadatum.package_username) - .id_not_in(id) - .exists? - - errors.add(:base, _('Package recipe already exists')) if recipe_exists - end - def valid_composer_global_name # .default_scoped is required here due to a bug in rails that leaks # the scope and adds `self` to the query incorrectly diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index ca897d5375b..ee6862f84d7 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -607,6 +607,8 @@ class ProjectPolicy < BasePolicy enable :admin_push_rules enable :manage_deploy_tokens enable :manage_merge_request_settings + enable :create_protected_branch + enable :admin_protected_branch end rule { can?(:admin_build) }.enable :manage_trigger diff --git a/app/presenters/packages/detail/package_presenter.rb b/app/presenters/packages/detail/package_presenter.rb index 37d144d9e98..23fec001db3 100644 --- a/app/presenters/packages/detail/package_presenter.rb +++ b/app/presenters/packages/detail/package_presenter.rb @@ -28,7 +28,7 @@ module Packages package_detail[:maven_metadatum] = @package.maven_metadatum if @package.maven_metadatum package_detail[:nuget_metadatum] = @package.nuget_metadatum if @package.nuget_metadatum package_detail[:composer_metadatum] = @package.composer_metadatum if @package.composer_metadatum - package_detail[:conan_metadatum] = @package.conan_metadatum if @package.conan_metadatum + package_detail[:conan_metadatum] = @package.conan_metadatum if @package.conan? && @package.conan_metadatum package_detail[:dependency_links] = @package.dependency_links.map { |link| build_dependency_links(link) } package_detail[:pipeline] = build_pipeline_info(@package.pipeline) if @package.pipeline package_detail[:pipelines] = build_pipeline_infos(@package.pipelines) if @package.pipelines.present? diff --git a/app/services/packages/conan/single_package_search_service.rb b/app/services/packages/conan/single_package_search_service.rb index e133b35c2cf..c998d15f74b 100644 --- a/app/services/packages/conan/single_package_search_service.rb +++ b/app/services/packages/conan/single_package_search_service.rb @@ -25,8 +25,8 @@ module Packages end def package - project - .packages + ::Packages::Conan::Package + .for_projects(project) .with_name(name) .with_version(version) .order_created diff --git a/app/views/projects/settings/repository/show.html.haml b/app/views/projects/settings/repository/show.html.haml index dede437d2b3..cf950de75db 100644 --- a/app/views/projects/settings/repository/show.html.haml +++ b/app/views/projects/settings/repository/show.html.haml @@ -17,6 +17,7 @@ -# The shared parts of the views can be found in the `shared` directory. -# Those are used throughout the actual views. These `shared` views are then -# reused in EE. +- if can?(current_user, :admin_protected_branch, @project) = render "projects/settings/repository/protected_branches", protected_branch_entity: @project - if current_user.can?(:manage_deploy_tokens, @project) diff --git a/app/workers/pause_control/resume_worker.rb b/app/workers/pause_control/resume_worker.rb index 98725c0b6f2..b647c7651b0 100644 --- a/app/workers/pause_control/resume_worker.rb +++ b/app/workers/pause_control/resume_worker.rb @@ -19,7 +19,6 @@ module PauseControl pause_strategies_workers.each do |strategy, workers| strategy_klass = Gitlab::SidekiqMiddleware::PauseControl.for(strategy) - next if strategy_klass.should_pause? workers.each do |worker| diff --git a/config/feature_flags/beta/approval_rules_drawer.yml b/config/feature_flags/beta/approval_rules_drawer.yml deleted file mode 100644 index dead46d69dc..00000000000 --- a/config/feature_flags/beta/approval_rules_drawer.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: approval_rules_drawer -feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/439397 -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/146502 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/444628 -milestone: '16.10' -group: group::source code -type: beta -default_enabled: true diff --git a/config/feature_flags/ops/zoekt_pause_indexing.yml b/config/feature_flags/ops/zoekt_pause_indexing.yml deleted file mode 100644 index 1bd74536348..00000000000 --- a/config/feature_flags/ops/zoekt_pause_indexing.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: zoekt_pause_indexing -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/126027 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/417597 -milestone: '16.3' -type: ops -group: group::global search -default_enabled: false diff --git a/data/whats_new/202505160001_17_0.yml b/data/whats_new/202505160001_17_0.yml new file mode 100644 index 00000000000..3da29c584bd --- /dev/null +++ b/data/whats_new/202505160001_17_0.yml @@ -0,0 +1,120 @@ +- name: CI/CD Catalog with components and inputs now generally available + description: | + The CI/CD Catalog is now generally available. As part of this release, we're also making [CI/CD components](https://docs.gitlab.com/ee/ci/components/) and [inputs](https://docs.gitlab.com/ee/ci/yaml/inputs.html) generally available. + + With the CI/CD Catalog, you gain access to a vast array of components created by the community and industry experts. + Whether you're seeking solutions for continuous integration, deployment pipelines, or automation tasks, you'll find a diverse selection of components tailored to suit your requirements. + You can read more about the Catalog and its features in the following [blog post](https://about.gitlab.com/blog/2024/05/08/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch/). + + You're invited to contribute CI/CD components to the Catalog and help expand this new and growing part of GitLab.com! + stage: verify + self-managed: true + gitlab-com: true + available_in: [Free, Premium, Ultimate] + documentation_link: https://docs.gitlab.com/ee/ci/components/#cicd-catalog + image_url: https://img.youtube.com/vi/QDn77nwIb-o/hqdefault.jpg + published_at: 2024-05-16 + release: 17.0 + +- name: AI Impact analytics in the Value Streams Dashboard + description: | + AI Impact is a dashboard available in the Value Streams Dashboard that helps organizations understand the [impact of GitLab Duo on their productivity](https://about.gitlab.com/blog/2024/02/20/measuring-ai-effectiveness-beyond-developer-productivity-metrics/). + This new month-over-month metric view compares the AI Usage trends with SDLC metrics like lead time, cycle time, DORA, and vulnerabilities. Software leaders can use the AI Impact dashboard to measure how much time is saved in their end-to-end workstream, while staying focused on business outcomes rather than developer activity. + + In this first release, the AI usage is measured as the monthly [Code Suggestions](https://docs.gitlab.com/ee/user/project/repository/code_suggestions/) usage rate, and is calculated as the number of monthly unique Code Suggestions users divided by total monthly unique [contributors](https://docs.gitlab.com/ee/user/group/contribution_analytics/). + + The AI Impact dashboard is available to users on the Ultimate tier for a limited time. Afterwards, a GitLab Duo Enterprise license will be required to use the dashboard. + stage: plan + self-managed: true + gitlab-com: true + available_in: [Ultimate] + documentation_link: https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html#ai-impact-analytics + image_url: https://about.gitlab.com/images/17_0/17.0_vsd_ai2.png + published_at: 2024-05-16 + release: 17.0 + +- name: Introducing hosted runners on Linux Arm + description: | + We are excited to introduce hosted runners on Linux Arm for GitLab.com. + The now available `medium` and `large` Arm machine types, equipped with 4 and 8 vCPUs respectively, and fully integrated with GitLab CI/CD, will allow you to build and test your application faster and more cost-efficient than ever before. + + We are determined to provide the industry's fastest CI/CD build speed and look forward to seeing teams achieve even shorter feedback cycles and ultimately deliver software faster. + stage: verify + self-managed: false + gitlab-com: true + available_in: [Premium, Ultimate] + documentation_link: https://docs.gitlab.com/ee/ci/runners/hosted_runners/linux.html + image_url: https://about.gitlab.com/images/17_0/larger-runners.png + published_at: 2024-05-16 + release: 17.0 + +- name: Introducing deployment detail pages + description: | + You can now link directly to a deployment in GitLab. Previously, if you were collaborating on a deployment, you had to look up the deployment from the deployment list. Because of the number of deployments listed, finding the correct deployment was difficult and prone to error. + + From 17.0, GitLab offers a deployment details view that you can link to directly. In this first version, the deployment details page offers an overview of the deployment job and the possibility to approve, reject, or comment on a deployment in a continuous delivery setting. We are looking into further avenues to enhance the deployment details page, including by linking to it from the related pipeline job. We would love to hear your feedback in [issue 450700](https://gitlab.com/gitlab-org/gitlab/-/issues/450700). + stage: verify + self-managed: true + gitlab-com: true + available_in: [Premium, Ultimate] + documentation_link: https://docs.gitlab.com/ee/ci/environments/deployment_approvals.html#approve-or-reject-a-deployment + image_url: https://about.gitlab.com/images/17_0/deployment-detail-page.png + published_at: 2024-05-16 + release: 17.0 + +- name: GitLab Duo Chat now uses Anthropic Claude 3 Sonnet + description: | + GitLab Duo Chat just got a lot better. It now uses Anthropic Claude 3 Sonnet as the base model, replacing Claude 2.1 for answering most questions. + + At GitLab, we apply a test-driven approach when choosing the best model for a set of tasks and authoring well-performing prompts. With recent adjustments to the chat prompts, we have achieved significant improvements in the correctness, comprehensiveness, and readability of chat answers based on Claude 3 Sonnet compared to the previous chat version built on Claude 2.1. Hence, we have now switched to this new model version. + stage: ai-powered + self-managed: true + gitlab-com: true + available_in: [Premium, Ultimate] + documentation_link: https://docs.gitlab.com/ee/user/ai_features.html#gitlab-duo-chat + image_url: https://about.gitlab.com/images/17_0/gitlabduo.png + published_at: 2024-05-16 + release: 17.0 + +- name: Enhanced context control with the `rules:exists` CI/CD keyword + description: | + The `rules:exists` CI/CD keyword has default behaviors that vary based on where the keyword is defined, which can make it harder to use with more complex pipelines. When defined in a job, `rules:exists` searches for specified files in the project running the pipeline. However, when defined in an `include` section, `rules:exists` searches for specified files in the project hosting the configuration file containing the `include` section. If configuration is split over multiple files and projects, it can be hard to know which exact project will be searched for defined files. + + In this release, we have introduced `project` and `ref` subkeys to `rules:exists`, providing you a way to explicitly control the search context for this keyword. These new subkeys help you ensure accurate rule evaluation by precisely specifying the search context, mitigating inconsistencies, and enhancing clarity in your pipeline rule definitions. + stage: verify + self-managed: true + gitlab-com: true + available_in: [Free, Premium, Ultimate] + documentation_link: https://docs.gitlab.com/ee/ci/yaml/#rulesexistsproject + image_url: https://about.gitlab.com/images/17_0/exists.png + published_at: 2024-05-16 + release: 17.0 + +- name: Add a group to the CI/CD job token allowlist + description: | + Introduced in GitLab 15.9, the CI/CD job token allowlist prevents unauthorized access from other projects to your project. Previously, you could allow access at the project level from other specific projects only, with a maximum limit of 200 total projects. + + In GitLab 17.0, you can now add groups to a project's CI/CD job token allowlist. The maximum limit of 200 now applies to both projects and groups, meaning a project allowlist can now have up to 200 projects and groups authorized for access. This improvement makes it easier to add large numbers of projects associated with a group. + stage: verify + self-managed: true + gitlab-com: true + available_in: [Free, Premium, Ultimate] + documentation_link: https://docs.gitlab.com/ee/ci/jobs/ci_job_token.html#control-job-token-access-to-your-project + image_url: https://about.gitlab.com/images/17_0/verify-add-a-group-to-the-job-token-allowlist.png + published_at: 2024-05-16 + release: 17.0 + + +- name: New usage overview panel in the Value Streams Dashboard + description: | + We enhanced the Value Streams Dashboard with an Overview panel. This new visualization addresses the need for executive-level insights into software delivery performance, and gives a clear picture of GitLab usage in the context of software development life cycle (SDLC). + + The Overview panel displays metrics for the group level, such as number of (sub)groups, projects, users, issues, merge requests, and pipelines. + stage: plan + self-managed: true + gitlab-com: true + available_in: [Ultimate] + documentation_link: https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html#overview-panel + image_url: https://about.gitlab.com/images/17_0/vsd_overview_17.png + published_at: 2024-05-16 + release: 17.0 diff --git a/db/docs/packages_packages.yml b/db/docs/packages_packages.yml index b0e5b7ca91f..129151b72ec 100644 --- a/db/docs/packages_packages.yml +++ b/db/docs/packages_packages.yml @@ -1,6 +1,7 @@ --- table_name: packages_packages classes: +- Packages::Conan::Package - Packages::Go::Package - Packages::MlModel::Package - Packages::Package diff --git a/db/post_migrate/20240513042657_cleanup_bigint_conversions_for_ci_pipelines.rb b/db/post_migrate/20240513042657_cleanup_bigint_conversions_for_ci_pipelines.rb new file mode 100644 index 00000000000..3ae9efa83ec --- /dev/null +++ b/db/post_migrate/20240513042657_cleanup_bigint_conversions_for_ci_pipelines.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class CleanupBigintConversionsForCiPipelines < Gitlab::Database::Migration[2.2] + milestone '17.1' + enable_lock_retries! + + TABLE = :ci_pipelines + COLUMNS = %i[id] + + def up + cleanup_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + restore_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end +end diff --git a/db/schema_migrations/20240513042657 b/db/schema_migrations/20240513042657 new file mode 100644 index 00000000000..50f395220f9 --- /dev/null +++ b/db/schema_migrations/20240513042657 @@ -0,0 +1 @@ +3b6c9657b2bd7ec2a772339716fa1c293c4352a709fdc71043d2265ade855d2a \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 4f93f614335..aa51c6319a2 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -852,15 +852,6 @@ RETURN NEW; END $$; -CREATE FUNCTION trigger_b2d852e1e2cb() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW."id_convert_to_bigint" := NEW."id"; - RETURN NEW; -END; -$$; - CREATE FUNCTION trigger_b4520c29ea74() RETURNS trigger LANGUAGE plpgsql AS $$ @@ -6845,7 +6836,6 @@ CREATE SEQUENCE ci_pipeline_variables_id_seq ALTER SEQUENCE ci_pipeline_variables_id_seq OWNED BY p_ci_pipeline_variables.id; CREATE TABLE ci_pipelines ( - id_convert_to_bigint integer DEFAULT 0 NOT NULL, ref character varying, sha character varying, before_sha character varying, @@ -29927,8 +29917,6 @@ CREATE TRIGGER trigger_56d49f4ed623 BEFORE INSERT OR UPDATE ON workspace_variabl CREATE TRIGGER trigger_94514aeadc50 BEFORE INSERT OR UPDATE ON deployment_approvals FOR EACH ROW EXECUTE FUNCTION trigger_94514aeadc50(); -CREATE TRIGGER trigger_b2d852e1e2cb BEFORE INSERT OR UPDATE ON ci_pipelines FOR EACH ROW EXECUTE FUNCTION trigger_b2d852e1e2cb(); - CREATE TRIGGER trigger_b4520c29ea74 BEFORE INSERT OR UPDATE ON approval_merge_request_rule_sources FOR EACH ROW EXECUTE FUNCTION trigger_b4520c29ea74(); CREATE TRIGGER trigger_catalog_resource_sync_event_on_project_update AFTER UPDATE ON projects FOR EACH ROW WHEN ((((old.name)::text IS DISTINCT FROM (new.name)::text) OR (old.description IS DISTINCT FROM new.description) OR (old.visibility_level IS DISTINCT FROM new.visibility_level))) EXECUTE FUNCTION insert_catalog_resource_sync_event(); diff --git a/doc/api/discussions.md b/doc/api/discussions.md index b01962b89fb..c7cfced36e9 100644 --- a/doc/api/discussions.md +++ b/doc/api/discussions.md @@ -894,7 +894,7 @@ Parameters for all comments: | `position[start_sha]` | string | yes (if `position*` is supplied) | SHA referencing commit in target branch. | | `position[new_path]` | string | yes (if the position type is `text`) | File path after change. | | `position[old_path]` | string | yes (if the position type is `text`) | File path before change. | -| `position[position_type]` | string | yes (if position* is supplied) | Type of the position reference. Allowed values: `text` or `image`. | +| `position[position_type]` | string | yes (if position* is supplied) | Type of the position reference. Allowed values: `text`, `image`, or `file`. `file` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/423046) in GitLab 16.4. | | `commit_id` | string | no | SHA referencing commit to start this thread on. | | `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z`. Requires administrator or project/group owner rights. | | `position` | hash | no | Position when creating a diff note. | @@ -1303,7 +1303,7 @@ Parameters: | `position[base_sha]` | string | yes (if `position*` is supplied) | SHA of the parent commit. | | `position[head_sha]` | string | yes (if `position*` is supplied) | The SHA of this commit. Same as `commit_id`. | | `position[start_sha]` | string | yes (if `position*` is supplied) | SHA of the parent commit. | -| `position[position_type]` | string | yes (if `position*` is supplied) | Type of the position reference. Allowed values: `text` or `image`. | +| `position[position_type]` | string | yes (if `position*` is supplied) | Type of the position reference. Allowed values: `text`, `image`, or `file`. `file` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/423046) in GitLab 16.4. | | `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z`. Requires administrator or project/group owner rights. | | `position` | hash | no | Position when creating a diff note. | diff --git a/doc/api/draft_notes.md b/doc/api/draft_notes.md index abe50186252..d6165c635da 100644 --- a/doc/api/draft_notes.md +++ b/doc/api/draft_notes.md @@ -126,7 +126,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/draft_notes | `position[start_sha]` | string | yes | SHA referencing commit in target branch. | | `position[new_path]` | string | yes (if the position type is `text`) | File path after change. | | `position[old_path]` | string | yes (if the position type is `text`) | File path before change. | -| `position[position_type]` | string | yes | Type of the position reference. Allowed values: `text` or `image`. | +| `position[position_type]` | string | yes | Type of the position reference. Allowed values: `text`, `image`, or `file`. `file` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/423046) in GitLab 16.4. | | `position` | hash | no | Position when creating a diff note. | | `position[new_line]` | integer | no | For `text` diff notes, the line number after change. | | `position[old_line]` | integer | no | For `text` diff notes, the line number before change. | @@ -160,7 +160,7 @@ PUT /projects/:id/merge_requests/:merge_request_iid/draft_notes/:draft_note_id | `position[start_sha]` | string | yes | SHA referencing commit in target branch. | | `position[new_path]` | string | yes (if the position type is `text`) | File path after change. | | `position[old_path]` | string | yes (if the position type is `text`) | File path before change. | -| `position[position_type]` | string | yes | Type of the position reference. Allowed values: `text` or `image`. | +| `position[position_type]` | string | yes | Type of the position reference. Allowed values: `text`, `image` or `file`. `file` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/423046) in GitLab 16.4. | | `position` | hash | no | Position when creating a diff note. | | `position[new_line]` | integer | no | For `text` diff notes, the line number after change. | | `position[old_line]` | integer | no | For `text` diff notes, the line number before change. | diff --git a/doc/api/openapi/openapi_v2.yaml b/doc/api/openapi/openapi_v2.yaml index 4b08987e882..e443c937272 100644 --- a/doc/api/openapi/openapi_v2.yaml +++ b/doc/api/openapi/openapi_v2.yaml @@ -27712,6 +27712,7 @@ paths: enum: - text - image + - file required: true - in: formData name: position[new_path] @@ -27906,6 +27907,7 @@ paths: enum: - text - image + - file required: true - in: formData name: position[new_path] diff --git a/doc/operations/error_tracking.md b/doc/operations/error_tracking.md index aa94ddf432f..8312dc4021c 100644 --- a/doc/operations/error_tracking.md +++ b/doc/operations/error_tracking.md @@ -23,7 +23,7 @@ For error tracking to work, you need: - To use the GitLab backend, see [GitLab Integrated error tracking](integrated_error_tracking.md). Integrated error tracking is available only on GitLab.com. - To use Sentry as the backend, see [Sentry based](sentry_error_tracking.md). - Sentry based error tracking is available only for self-managed instances. + Sentry based error tracking is available for GitLab.com, GitLab Dedicated and Self-managed instances. Here is a summary of the capabilities for each version: diff --git a/doc/operations/sentry_error_tracking.md b/doc/operations/sentry_error_tracking.md index 1e697307f14..b0afa3f5436 100644 --- a/doc/operations/sentry_error_tracking.md +++ b/doc/operations/sentry_error_tracking.md @@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w DETAILS: **Tier:** Free, Premium, Ultimate -**Offering:** Self-managed, GitLab Dedicated +**Offering:** GitLab.com, Self-managed, GitLab Dedicated [Sentry](https://sentry.io/) is an open source error tracking system. GitLab enables administrators to connect Sentry to GitLab, so users can view a list of Sentry errors in GitLab. diff --git a/doc/security/token_overview.md b/doc/security/token_overview.md index df7cd999386..9238d4a600c 100644 --- a/doc/security/token_overview.md +++ b/doc/security/token_overview.md @@ -59,7 +59,7 @@ You can use the [project access tokens API](../api/project_access_tokens.md) to programmatically take action, such as [rotating a project access token](../api/project_access_tokens.md#rotate-a-project-access-token). -Project owners and maintainers receive an email when project access tokens are 7 days or less from expiration. +Project maintainers receive an email when project access tokens are 7 days or less from expiration. ## Group access tokens diff --git a/doc/user/analytics/value_streams_dashboard.md b/doc/user/analytics/value_streams_dashboard.md index 71b10ca035d..662634e3e3d 100644 --- a/doc/user/analytics/value_streams_dashboard.md +++ b/doc/user/analytics/value_streams_dashboard.md @@ -154,11 +154,15 @@ If multiple topics are provided, all topics must match for the project to be inc ### AI Impact analytics +DETAILS: +**Offering:** GitLab.com, Self-managed + > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/443696) in GitLab 16.11 [with a flag](../../administration/feature_flags.md) named `ai_impact_analytics_dashboard`. Disabled by default. FLAG: On self-managed GitLab, by default this feature is not available. To make it available, an administrator can [enable the feature flag](../../administration/feature_flags.md) named `ai_impact_analytics_dashboard`. -On GitLab.com and GitLab Dedicated, this feature is available. +On GitLab.com this feature is available. +On GitLab Dedicated this feature is not available. AI Impact analytics displays SDLC metrics for a group or project in the month-to-date and the past six months. You can use this table to observe how changes in the AI usage metric correlate with changes in other metrics. diff --git a/doc/user/group/devops_adoption/index.md b/doc/user/group/devops_adoption/index.md index 30e55c3cf83..07ca44d3069 100644 --- a/doc/user/group/devops_adoption/index.md +++ b/doc/user/group/devops_adoption/index.md @@ -10,6 +10,8 @@ DETAILS: **Tier:** Ultimate **Offering:** GitLab.com, Self-managed, GitLab Dedicated +> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/367093) to the [Registration Features Program](../../../administration/settings/usage_statistics.md#registration-features-program) in GitLab 16.6. + DevOps Adoption shows you how groups in your organization adopt and use the most essential features of GitLab. You can use Group DevOps Adoption to: diff --git a/doc/user/product_analytics/index.md b/doc/user/product_analytics/index.md index 62bd7b36a7e..737c4e88e19 100644 --- a/doc/user/product_analytics/index.md +++ b/doc/user/product_analytics/index.md @@ -24,6 +24,12 @@ DETAILS: FLAG: The availability of this feature is controlled by feature flags. For more information, see the history. +The product analytics feature empowers you to track user behavior and gain insights into how your +applications are used and how users interact with your product. +By using the data collected with product analytics in GitLab, you can better understand your users, +identify friction points in funnels, make data-driven product decisions, and ultimately build better +products that drive user engagement and business growth. + For more information about the vision and development of product analytics, see the [group direction page](https://about.gitlab.com/direction/monitor/product-analytics/). To leave feedback about product analytics bugs or functionality: diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md index 9bcea50d6e9..cb3457deff2 100644 --- a/doc/user/profile/index.md +++ b/doc/user/profile/index.md @@ -356,13 +356,24 @@ You can disable following and being followed by other users. NOTE: When this feature is being disabled, all current followed/following connections are deleted. -## Advanced code search with zoekt +## Exact code search -### Disable searching code with Zoekt +### Enable exact code search -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/388519) as a beta feature [with a flag](../feature_flags.md) named `search_code_with_zoekt`. Enabled by default. +DETAILS: +**Tier:** Premium, Ultimate +**Offering:** GitLab.com, Self-managed +**Status:** Beta -You can disable searching with Zoekt and use Elasticsearch instead. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105049) as a [Beta](../../policy/experiment-beta-support.md#beta) in GitLab 15.9 [with flags](../../administration/feature_flags.md) named `index_code_with_zoekt` and `search_code_with_zoekt`. Disabled by default. +> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/388519) in GitLab 16.6. +> - Feature flags `index_code_with_zoekt` and `search_code_with_zoekt` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/148378) in GitLab 17.1. + +WARNING: +This feature is in [Beta](../../policy/experiment-beta-support.md#beta) and subject to change without notice. +For more information, see [epic 9404](https://gitlab.com/groups/gitlab-org/-/epics/9404). + +To enable exact code search in GitLab: 1. On the left sidebar, select your avatar. 1. Select **Edit profile**. diff --git a/doc/user/project/merge_requests/approvals/rules.md b/doc/user/project/merge_requests/approvals/rules.md index 33518b71fd6..11c4026790f 100644 --- a/doc/user/project/merge_requests/approvals/rules.md +++ b/doc/user/project/merge_requests/approvals/rules.md @@ -49,7 +49,7 @@ To add a merge request approval rule: 1. Select **Settings > Merge requests**. 1. In the **Merge request approvals** section, in the **Approval rules** section, select **Add approval rule**. -1. Complete the fields: +1. On the right sidebar, complete the fields: - In **Approvals required**, a value of `0` makes [the rule optional](#configure-optional-approval-rules), and any number greater than `0` creates a required rule. @@ -57,7 +57,7 @@ To add a merge request approval rule: - From **Add approvers**, select users or groups that are [eligible to approve](#eligible-approvers). GitLab suggests approvers based on previous authors of the files changed by the merge request. -1. Select **Add approval rule**. You can add [multiple approval rules](#multiple-approval-rules). +1. Select **Save changes**. You can add [multiple approval rules](#multiple-approval-rules). Your configuration for approval rule overrides determines if the new rule is applied to existing merge requests: @@ -83,14 +83,14 @@ To edit a merge request approval rule: 1. On the left sidebar, select **Search or go to** and find your project. 1. Select **Settings > Merge requests**. 1. In the **Merge request approvals** section, in the **Approval rules** section, next to the rule you want to edit, select **Edit**. -1. Edit the fields: +1. On the right sidebar, edit the fields: - In **Approvals required**, a value of `0` makes [the rule optional](#configure-optional-approval-rules), and any number greater than `0` creates a required rule. Maximum number of required approvals is `100`. - To remove users or groups, identify the group or user to remove, and select **Remove** (**{remove}**). -1. Select **Update approval rule**. +1. Select **Save changes**. ## Delete an approval rule @@ -213,8 +213,8 @@ To enable approval permissions for these users without granting them push access 1. In the **Merge request approvals** section, in the **Approval rules** section: - For a new rule, select **Add approval rule** and target the protected branch. - For an existing rule, select **Edit** and target the protected branch. -1. In **Add approvers**, select the group you created. -1. Select **Add approval rule** or **Update approval rule**. +1. On the right sidebar, in **Add approvers**, select the group you created. +1. Select **Save changes**. ## Edit or override merge request approval rules @@ -302,21 +302,6 @@ on the merge request to indicate which steps are needed to proceed. These policies are both created and edited in the [security policy editor](../../../application_security/policies/index.md#policy-editor). -## Edit approval rules in a drawer - -DETAILS: -**Status:** Beta - -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/439397) in GitLab 16.11 [with a flag](../../../../administration/feature_flags.md) named `approval_rules_drawer`. Enabled by default. This feature is in [beta](../../../../policy/experiment-beta-support.md). - -FLAG: -On self-managed GitLab, by default this feature is available. -To hide the feature, an administrator can [disable the feature flag](../../../../administration/feature_flags.md) named `approval_rules_drawer`. -On GitLab.com and GitLab Dedicated, this feature is available. - -When this feature is enabled, the dialog to [add](#add-an-approval-rule) or -[edit an approval](#edit-an-approval-rule) rule opens in a drawer on the right. - ## Troubleshooting ### Approval rule name can't be blank diff --git a/doc/user/search/exact_code_search.md b/doc/user/search/exact_code_search.md index 75ff372fe09..d4ba3b9b495 100644 --- a/doc/user/search/exact_code_search.md +++ b/doc/user/search/exact_code_search.md @@ -11,12 +11,9 @@ DETAILS: **Offering:** GitLab.com, Self-managed **Status:** Beta -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105049) in GitLab 15.9 [with flags](../../administration/feature_flags.md) named `index_code_with_zoekt` and `search_code_with_zoekt`. Disabled by default. - -FLAG: -The availability of this feature is controlled by a feature flag. -For more information, see the history. -This feature is available for testing, but not ready for production use. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105049) as a [Beta](../../policy/experiment-beta-support.md#beta) in GitLab 15.9 [with flags](../../administration/feature_flags.md) named `index_code_with_zoekt` and `search_code_with_zoekt`. Disabled by default. +> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/388519) in GitLab 16.6. +> - Feature flags `index_code_with_zoekt` and `search_code_with_zoekt` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/148378) in GitLab 17.1. WARNING: This feature is in [beta](../../policy/experiment-beta-support.md#beta) and subject to change without notice. diff --git a/lib/api/helpers/packages/conan/api_helpers.rb b/lib/api/helpers/packages/conan/api_helpers.rb index 7f695dfde64..1cae747dd99 100644 --- a/lib/api/helpers/packages/conan/api_helpers.rb +++ b/lib/api/helpers/packages/conan/api_helpers.rb @@ -136,15 +136,15 @@ module API strong_memoize_attr :project def package - project.packages - .conan - .with_name(params[:package_name]) - .with_version(params[:package_version]) - .with_conan_username(params[:package_username]) - .with_conan_channel(params[:package_channel]) - .order_created - .not_pending_destruction - .last + ::Packages::Conan::Package + .for_projects(project) + .with_name(params[:package_name]) + .with_version(params[:package_version]) + .with_conan_username(params[:package_username]) + .with_conan_channel(params[:package_channel]) + .order_created + .not_pending_destruction + .last end strong_memoize_attr :package diff --git a/lib/gitlab/sidekiq_middleware/pause_control/strategies/zoekt.rb b/lib/gitlab/sidekiq_middleware/pause_control/strategies/zoekt.rb index 23cba5553e2..6942e5151a1 100644 --- a/lib/gitlab/sidekiq_middleware/pause_control/strategies/zoekt.rb +++ b/lib/gitlab/sidekiq_middleware/pause_control/strategies/zoekt.rb @@ -7,7 +7,7 @@ module Gitlab class Zoekt < Base override :should_pause? def should_pause? - ::Feature.enabled?(:zoekt_pause_indexing, type: :ops) + Gitlab::CurrentSettings.zoekt_indexing_paused? end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 221a5594cb7..3881b5a4dea 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -13690,6 +13690,9 @@ msgstr "" msgid "Configure settings for Advanced Search with Elasticsearch." msgstr "" +msgid "Configure settings for exact code search." +msgstr "" + msgid "Configure specific limits for Files API requests that supersede the general user and IP rate limits." msgstr "" @@ -13979,6 +13982,9 @@ msgstr "" msgid "ContainerRegistry|Copy push command" msgstr "" +msgid "ContainerRegistry|Could not load signature details." +msgstr "" + msgid "ContainerRegistry|Created %{time}" msgstr "" @@ -14137,6 +14143,9 @@ msgstr "" msgid "ContainerRegistry|Show full path" msgstr "" +msgid "ContainerRegistry|Signature details" +msgstr "" + msgid "ContainerRegistry|Signature digest: %{digest}" msgstr "" @@ -21124,6 +21133,9 @@ msgstr "" msgid "Evidence collection" msgstr "" +msgid "Exact code search" +msgstr "" + msgid "Exactly one of %{attributes} is required" msgstr "" @@ -21610,7 +21622,7 @@ msgstr "" msgid "Failed to load branches. Please try again." msgstr "" -msgid "Failed to load deploy keys." +msgid "Failed to load data." msgstr "" msgid "Failed to load error details from Sentry." @@ -21622,9 +21634,6 @@ msgstr "" msgid "Failed to load group activity metrics. Please try again." msgstr "" -msgid "Failed to load groups, users and deploy keys." -msgstr "" - msgid "Failed to load groups." msgstr "" @@ -39169,7 +39178,7 @@ msgstr "" msgid "ProductAnalytics|3. Initiate the tracking" msgstr "" -msgid "ProductAnalytics|A deployed instance of the analytics-stack project." +msgid "ProductAnalytics|A deployed instance of the %{linkStart}helm-charts%{linkEnd} project." msgstr "" msgid "ProductAnalytics|Add another dimension" @@ -55553,9 +55562,6 @@ msgstr "" msgid "Update appearance settings" msgstr "" -msgid "Update approval rule" -msgstr "" - msgid "Update approvers" msgstr "" diff --git a/package.json b/package.json index d35faaf8a33..b91eedadbac 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "@gitlab/favicon-overlay": "2.0.0", "@gitlab/fonts": "^1.3.0", "@gitlab/svgs": "3.99.0", - "@gitlab/ui": "80.8.1", + "@gitlab/ui": "80.10.0", "@gitlab/web-ide": "^0.0.1-dev-20240508140740", "@mattiasbuelens/web-streams-adapter": "^0.1.0", "@rails/actioncable": "7.0.8-1", diff --git a/qa/Gemfile b/qa/Gemfile index 8be581d4a58..bec54566048 100644 --- a/qa/Gemfile +++ b/qa/Gemfile @@ -11,7 +11,7 @@ gem 'capybara', '~> 3.40.0' gem 'capybara-screenshot', '~> 1.0.26' gem 'rake', '~> 13', '>= 13.2.1' gem 'rspec', '~> 3.13' -gem 'selenium-webdriver', '= 4.20.1' +gem 'selenium-webdriver', '= 4.21.0' gem 'airborne', '~> 0.3.7', require: false # airborne is messing with rspec sandboxed mode so not requiring by default gem 'rest-client', '~> 2.1.0' gem 'rspec_junit_formatter', '~> 0.6.0' diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock index 5d0cab47974..057faa470ac 100644 --- a/qa/Gemfile.lock +++ b/qa/Gemfile.lock @@ -314,7 +314,7 @@ GEM sawyer (0.9.2) addressable (>= 2.3.5) faraday (>= 0.17.3, < 3) - selenium-webdriver (4.20.1) + selenium-webdriver (4.21.0) base64 (~> 0.2) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) @@ -395,7 +395,7 @@ DEPENDENCIES rspec-parameterized (~> 1.0.2) rspec_junit_formatter (~> 0.6.0) ruby-debug-ide (~> 0.7.3) - selenium-webdriver (= 4.20.1) + selenium-webdriver (= 4.21.0) slack-notifier (~> 2.4) terminal-table (~> 3.0.2) warning (~> 1.3) diff --git a/spec/factories/packages/conan/packages.rb b/spec/factories/packages/conan/packages.rb new file mode 100644 index 00000000000..e5ad7d35621 --- /dev/null +++ b/spec/factories/packages/conan/packages.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :conan_package, class: 'Packages::Conan::Package', parent: :package do + package_type { :conan } + sequence(:name) { |n| "package-#{n}" } + version { '1.0.0' } + + conan_metadatum + + transient do + without_package_files { false } + end + + after :build do |package| + package.conan_metadatum.package_username = ::Packages::Conan::Metadatum.package_username_from( + full_path: package.project.full_path + ) + end + + after :create do |package, evaluator| + unless evaluator.without_package_files + %i[conan_recipe_file conan_recipe_manifest conan_package_info conan_package_manifest + conan_package].each do |file| + create :conan_package_file, file, package: package + end + end + end + + trait(:without_loaded_metadatum) do + conan_metadatum { association(:conan_metadatum, package: nil, strategy: :build) } + end + end +end diff --git a/spec/factories/packages/packages.rb b/spec/factories/packages/packages.rb index bc1af280897..a991a8b7a1b 100644 --- a/spec/factories/packages/packages.rb +++ b/spec/factories/packages/packages.rb @@ -252,38 +252,6 @@ FactoryBot.define do end end - factory :conan_package do - conan_metadatum - - transient do - without_package_files { false } - end - - after :build do |package| - package.conan_metadatum.package_username = Packages::Conan::Metadatum.package_username_from( - full_path: package.project.full_path - ) - end - - sequence(:name) { |n| "package-#{n}" } - version { '1.0.0' } - package_type { :conan } - - after :create do |package, evaluator| - unless evaluator.without_package_files - create :conan_package_file, :conan_recipe_file, package: package - create :conan_package_file, :conan_recipe_manifest, package: package - create :conan_package_file, :conan_package_info, package: package - create :conan_package_file, :conan_package_manifest, package: package - create :conan_package_file, :conan_package, package: package - end - end - - trait(:without_loaded_metadatum) do - conan_metadatum { build(:conan_metadatum, package: nil) } # rubocop:disable RSpec/FactoryBot/InlineAssociation - end - end - factory :generic_package do sequence(:name) { |n| "generic-package-#{n}" } version { '1.0.0' } diff --git a/spec/features/merge_request/user_comments_on_whitespace_hidden_diff_spec.rb b/spec/features/merge_request/user_comments_on_whitespace_hidden_diff_spec.rb index 233e6dd0f3e..3c86f99249c 100644 --- a/spec/features/merge_request/user_comments_on_whitespace_hidden_diff_spec.rb +++ b/spec/features/merge_request/user_comments_on_whitespace_hidden_diff_spec.rb @@ -6,57 +6,116 @@ RSpec.describe 'User comments on a diff with whitespace changes', :js, feature_c include MergeRequestDiffHelpers let_it_be(:project) { create(:project, :repository) } - let(:merge_request) do - create(:merge_request_with_diffs, source_project: project, target_project: project, - source_branch: 'changes-with-whitespace') - end let(:user) { create(:user) } before do project.add_maintainer(user) sign_in(user) - - visit(diffs_project_merge_request_path(project, merge_request, view: 'parallel')) end - context 'when hiding whitespace changes' do + context 'when MR contains a whitespace diff which contains line combinations that are not present in the real diff' do + let(:merge_request) do + create(:merge_request_with_diffs, source_project: project, target_project: project, + source_branch: 'changes-with-whitespace') + end + before do - find('.js-show-diff-settings').click - find_by_testid('show-whitespace').click - wait_for_requests + visit(diffs_project_merge_request_path(project, merge_request, view: 'parallel')) end - context 'when commenting on line combinations that are not present in the real diff' do + context 'when hiding whitespace changes' do before do - # Comment on line combination old: 19, new 20 - # This line combination does not exist when whitespace is shown - click_diff_line( - find_by_scrolling('div[data-path="files/ruby/popen.rb"] .left-side a[data-linenumber="19"]').find(:xpath, - '../..'), 'left') - page.within('.js-discussion-note-form') do - fill_in(:note_note, with: 'Comment on diff with whitespace') + hide_whitespace + end + + context 'when commenting on line combinations that are not present in the real diff' do + before do + # Comment on line combination old: 19, new 20 + # This line combination does not exist when whitespace is shown + click_diff_line( + find_by_scrolling('div[data-path="files/ruby/popen.rb"] .left-side a[data-linenumber="19"]').find(:xpath, + '../..'), 'left') + page.within('.js-discussion-note-form') do + fill_in(:note_note, with: 'Comment on diff with whitespace') + click_button('Add comment now') + end + + wait_for_requests + end + + it 'shows the comments in the diff' do + page.within('.notes_holder') do + expect(page).to have_content('Comment on diff with whitespace') + end + end + + it 'allows replies to comments in the diff' do + click_button('Reply to comment') + fill_in(:note_note, with: 'reply to whitespace comment') click_button('Add comment now') - end - - wait_for_requests - end - - it 'shows the comments in the diff' do - page.within('.notes_holder') do - expect(page).to have_content('Comment on diff with whitespace') - end - end - - it 'allows replies to comments in the diff' do - click_button('Reply to comment') - fill_in(:note_note, with: 'reply to whitespace comment') - click_button('Add comment now') - wait_for_requests - page.within('.notes_holder') do - expect(page).to have_content('reply to whitespace comment') + wait_for_requests + page.within('.notes_holder') do + expect(page).to have_content('reply to whitespace comment') + end end end end end + + context 'when the MR contains a diff with a file with whitespace changes only' do + let(:merge_request) do + create(:merge_request_with_diffs, source_project: project, target_project: project, target_branch: 'master', + source_branch: 'changes-with-only-whitespace') + end + + before do + visit(diffs_project_merge_request_path(project, merge_request, view: 'parallel')) + end + + context 'when hiding whitespace changes' do + before do + hide_whitespace + end + + context 'when showing changes and commenting' do + before do + click_button('Show changes') + wait_for_requests + + click_diff_line( + find_by_scrolling('div[data-path="files/ruby/popen.rb"] .left-side a[data-linenumber="1"]').find(:xpath, + '../..'), 'left') + page.within('.js-discussion-note-form') do + fill_in(:note_note, with: 'Comment on whitespace only diff') + click_button('Add comment now') + end + + wait_for_requests + end + + it 'shows the comments in the diff' do + page.within('.notes_holder') do + expect(page).to have_content('Comment on whitespace only diff') + end + end + + it 'allows replies to comments in the diff' do + click_button('Reply to comment') + fill_in(:note_note, with: 'reply to whitespace only comment') + click_button('Add comment now') + wait_for_requests + page.within('.notes_holder') do + expect(page).to have_content('reply to whitespace only comment') + end + end + end + end + end + + def hide_whitespace + find('.js-show-diff-settings').click + find_by_testid('show-whitespace').click + wait_for_requests + end end diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb index ba6e38ae82b..499e1be0661 100644 --- a/spec/features/protected_branches_spec.rb +++ b/spec/features/protected_branches_spec.rb @@ -88,112 +88,17 @@ RSpec.describe 'Protected Branches', :js, feature_category: :source_code_managem enable_admin_mode!(admin) end - describe "explicit protected branches" do - it "allows creating explicit protected branches" do - visit project_protected_branches_path(project) + it_behaves_like 'setting project protected branches' - show_add_form - set_defaults - set_protected_branch_name('some->branch') - click_on "Protect" + it "shows success alert once protected branch is created" do + visit project_protected_branches_path(project) - within(".protected-branches-list") { expect(page).to have_content('some->branch') } - expect(ProtectedBranch.count).to eq(1) - expect(ProtectedBranch.last.name).to eq('some->branch') - end - - it "shows success alert once protected branch is created" do - visit project_protected_branches_path(project) - - show_add_form - set_defaults - set_protected_branch_name('some->branch') - click_on "Protect" - wait_for_requests - expect(page).to have_content(s_('ProtectedBranch|View protected branches as branch rules')) - end - - it "displays the last commit on the matching branch if it exists" do - commit = create(:commit, project: project) - project.repository.add_branch(admin, 'some-branch', commit.id) - - visit project_protected_branches_path(project) - - show_add_form - set_defaults - set_protected_branch_name('some-branch') - click_on "Protect" - - within(".protected-branches-list") do - expect(page).not_to have_content("matching") - expect(page).not_to have_content("was deleted") - end - end - - it "displays an error message if the named branch does not exist" do - visit project_protected_branches_path(project) - - show_add_form - set_defaults - set_protected_branch_name('some-branch') - click_on "Protect" - - within(".protected-branches-list") { expect(page).to have_content('Branch does not exist') } - end - end - - describe "wildcard protected branches" do - it "allows creating protected branches with a wildcard" do - visit project_protected_branches_path(project) - - show_add_form - set_defaults - set_protected_branch_name('*-stable') - click_on "Protect" - - within(".protected-branches-list") { expect(page).to have_content('*-stable') } - expect(ProtectedBranch.count).to eq(1) - expect(ProtectedBranch.last.name).to eq('*-stable') - end - - it "displays the number of matching branches", - quarantine: 'https://gitlab.com/gitlab-org/quality/engineering-productivity/flaky-tests/-/issues/3459' do - project.repository.add_branch(admin, 'production-stable', 'master') - project.repository.add_branch(admin, 'staging-stable', 'master') - - visit project_protected_branches_path(project) - - show_add_form - set_defaults - set_protected_branch_name('*-stable') - click_on "Protect" - - within(".protected-branches-list") do - expect(page).to have_content("2 matching branches") - end - end - - it "displays all the branches matching the wildcard" do - project.repository.add_branch(admin, 'production-stable', 'master') - project.repository.add_branch(admin, 'staging-stable', 'master') - project.repository.add_branch(admin, 'development', 'master') - - visit project_protected_branches_path(project) - - show_add_form - set_protected_branch_name('*-stable') - set_defaults - click_on "Protect" - - visit project_protected_branches_path(project) - click_on "2 matching branches" - - within(".protected-branches-list") do - expect(page).to have_content("production-stable") - expect(page).to have_content("staging-stable") - expect(page).not_to have_content("development") - end - end + show_add_form + set_defaults + set_protected_branch_name('some->branch') + click_on "Protect" + wait_for_requests + expect(page).to have_content(s_('ProtectedBranch|View protected branches as branch rules')) end describe "access control" do diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/signature_details_modal_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/signature_details_modal_spec.js new file mode 100644 index 00000000000..b2520819f1a --- /dev/null +++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/signature_details_modal_spec.js @@ -0,0 +1,146 @@ +import VueApollo from 'vue-apollo'; +import Vue from 'vue'; +import { shallowMount } from '@vue/test-utils'; +import { GlLoadingIcon, GlModal, GlAlert } from '@gitlab/ui'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import SignatureDetailsModal from '~/packages_and_registries/container_registry/explorer/components/details_page/signature_details_modal.vue'; +import getManifestDetailsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_manifest_details.query.graphql'; +import waitForPromises from 'helpers/wait_for_promises'; +import { __ } from '~/locale'; +import CodeBlockHighlighted from '~/vue_shared/components/code_block_highlighted.vue'; + +Vue.use(VueApollo); + +describe('Signature details modal', () => { + let wrapper; + + const defaultManifestDetailsHandler = jest + .fn() + .mockResolvedValue({ data: { containerRepository: { id: 1, manifest: 'manifest details' } } }); + + const createWrapper = ({ + manifestDetailsHandler = defaultManifestDetailsHandler, + visible = true, + digest = 'sha256:abcdef', + } = {}) => { + wrapper = shallowMount(SignatureDetailsModal, { + propsData: { visible, digest }, + apolloProvider: createMockApollo([[getManifestDetailsQuery, manifestDetailsHandler]]), + mocks: { $route: { params: { id: 123 } } }, + }); + + return waitForPromises(); + }; + + const findModal = () => wrapper.findComponent(GlModal); + const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); + const findAlert = () => wrapper.findComponent(GlAlert); + const findCodeBlockHighlighted = () => wrapper.findComponent(CodeBlockHighlighted); + + describe('modal', () => { + it('shows modal with expected settings', () => { + createWrapper(); + + expect(findModal().attributes()).toHaveProperty('scrollable'); + expect(findModal().props()).toMatchObject({ + title: 'Signature details', + actionCancel: { text: __('Close') }, + }); + }); + + it.each([true, false])('passes %s visible prop', (visible) => { + createWrapper({ visible }); + + expect(findModal().props('visible')).toBe(visible); + }); + + it('emits close event when modal is closed', () => { + createWrapper(); + findModal().vm.$emit('hidden'); + + expect(wrapper.emitted('close')).toHaveLength(1); + }); + }); + + describe('manifest details query', () => { + it('calls query with expected variables', () => { + createWrapper(); + + expect(defaultManifestDetailsHandler).toHaveBeenCalledTimes(1); + expect(defaultManifestDetailsHandler).toHaveBeenCalledWith({ + id: 'gid://gitlab/ContainerRepository/123', + reference: 'sha256:abcdef', + }); + }); + + it('does not call query when there is no digest', () => { + createWrapper({ digest: null }); + + expect(defaultManifestDetailsHandler).not.toHaveBeenCalled(); + }); + }); + + describe('when query is loading', () => { + beforeEach(() => { + createWrapper(); + }); + + it('shows loading icon', () => { + expect(findLoadingIcon().exists()).toBe(true); + }); + + it('does not show error alert', () => { + expect(findAlert().exists()).toBe(false); + }); + + it('does not show code block', () => { + expect(findCodeBlockHighlighted().exists()).toBe(false); + }); + }); + + describe('when query encounters an error', () => { + beforeEach(() => { + return createWrapper({ manifestDetailsHandler: jest.fn().mockRejectedValue() }); + }); + + it('does not show loading icon', () => { + expect(findLoadingIcon().exists()).toBe(false); + }); + + it('shows error alert with expected props and text', () => { + expect(findAlert().props()).toMatchObject({ + variant: 'danger', + dismissible: false, + }); + }); + + it('shows error alert with expected text', () => { + expect(findAlert().text()).toBe('Could not load signature details.'); + }); + + it('does not show code block', () => { + expect(findCodeBlockHighlighted().exists()).toBe(false); + }); + }); + + describe('when query finishes loading', () => { + beforeEach(() => { + return createWrapper(); + }); + + it('does not show loading icon', () => { + expect(findLoadingIcon().exists()).toBe(false); + }); + + it('does not show error alert', () => { + expect(findAlert().exists()).toBe(false); + }); + + it('shows code block with expected props', () => { + expect(findCodeBlockHighlighted().props()).toMatchObject({ + language: 'json', + code: 'manifest details', + }); + }); + }); +}); diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js index 3a53ad25dc0..984eb976c50 100644 --- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js +++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js @@ -5,11 +5,13 @@ import { GlDisclosureDropdown, GlDisclosureDropdownItem, GlBadge, + GlLink, } from '@gitlab/ui'; import { nextTick } from 'vue'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; import TagsListRow from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue'; +import SignatureDetailsModal from '~/packages_and_registries/container_registry/explorer/components/details_page/signature_details_modal.vue'; import { REMOVE_TAG_BUTTON_TITLE, MISSING_MANIFEST_WARNING_TOOLTIP, @@ -45,6 +47,7 @@ describe('tags list row', () => { const findAdditionalActionsMenu = () => wrapper.findComponent(GlDisclosureDropdown); const findDeleteButton = () => wrapper.findComponent(GlDisclosureDropdownItem); const findSignedBadge = () => wrapper.findComponent(GlBadge); + const findSignatureDetailsModal = () => wrapper.findComponent(SignatureDetailsModal); const mountComponent = (propsData = defaultProps) => { wrapper = shallowMountExtended(TagsListRow, { @@ -437,6 +440,10 @@ describe('tags list row', () => { it('does not show the signature details row', () => { expect(findSignaturesDetails().exists()).toBe(false); }); + + it('does not show the signatures modal', () => { + expect(findSignatureDetailsModal().exists()).toBe(false); + }); }); describe('with signatures', () => { @@ -485,6 +492,38 @@ describe('tags list row', () => { `Signature digest: sha256:${index}`, ); }); + + it('shows the view details link', () => { + expect(findSignaturesDetails().at(index).findComponent(GlLink).text()).toBe( + 'View details', + ); + }); + }); + }); + + describe('signature details modal', () => { + it('does not show modal by default', () => { + expect(findSignatureDetailsModal().props('visible')).toBe(false); + expect(findSignatureDetailsModal().props('digest')).toBe(null); + }); + + describe(`when a row's view details link is clicked`, () => { + beforeEach(() => { + findSignaturesDetails().at(0).findComponent(GlLink).vm.$emit('click'); + }); + + it('shows modal', () => { + expect(findSignatureDetailsModal().props('visible')).toBe(true); + expect(findSignatureDetailsModal().props('digest')).toBe('sha256:0'); + }); + + it('hides modal when the modal is closed', async () => { + findSignatureDetailsModal().vm.$emit('close'); + await nextTick(); + + expect(findSignatureDetailsModal().props('visible')).toBe(false); + expect(findSignatureDetailsModal().props('digest')).toBe(null); + }); }); }); }); diff --git a/spec/frontend/projects/settings/components/access_dropdown_spec.js b/spec/frontend/projects/settings/components/access_dropdown_spec.js index 75b239d2d94..9bbd9a1f531 100644 --- a/spec/frontend/projects/settings/components/access_dropdown_spec.js +++ b/spec/frontend/projects/settings/components/access_dropdown_spec.js @@ -119,6 +119,19 @@ describe('Access Level Dropdown', () => { expect(getGroups).toHaveBeenCalledWith({ withProjectAccess: true }); expect(getDeployKeys).toHaveBeenCalled(); }); + + describe('with limit_repository_settings = protected_branches', () => { + it('should not make an api call for depoloyKeys', () => { + window.gon = { + limit_repository_settings: ['protected_branches'], + }; + + createComponent({ groupsWithProjectAccess: true }); + expect(getUsers).toHaveBeenCalled(); + expect(getGroups).toHaveBeenCalledWith({ withProjectAccess: true }); + expect(getDeployKeys).not.toHaveBeenCalled(); + }); + }); }); it('should make an api call for deployKeys but not for users or groups when user does not have a license', () => { diff --git a/spec/lib/bulk_imports/object_counter_spec.rb b/spec/lib/bulk_imports/object_counter_spec.rb index 77a598dc920..072c835b325 100644 --- a/spec/lib/bulk_imports/object_counter_spec.rb +++ b/spec/lib/bulk_imports/object_counter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe BulkImports::ObjectCounter, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe BulkImports::ObjectCounter, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:tracker) { build(:bulk_import_tracker, id: non_existing_record_id) } let_it_be(:cache_key) { "bulk_imports/object_counter/#{tracker.id}" } diff --git a/spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb index c6468324be3..28e2e3bdc26 100644 --- a/spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb +++ b/spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb @@ -59,7 +59,7 @@ RSpec.describe BulkImports::Projects::Pipelines::SnippetsRepositoryPipeline, fea end end - describe '#run', :clean_gitlab_redis_cache do + describe '#run', :clean_gitlab_redis_shared_state do let(:validation_response) { double(Hash, 'error?': false) } before do diff --git a/spec/lib/gitlab/bitbucket_import/importers/issue_importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importers/issue_importer_spec.rb index 7cf57bc675a..ce811b9ff76 100644 --- a/spec/lib/gitlab/bitbucket_import/importers/issue_importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importers/issue_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketImport::Importers::IssueImporter, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::BitbucketImport::Importers::IssueImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do include AfterNextHelpers let_it_be(:project) { create(:project, :repository) } diff --git a/spec/lib/gitlab/bitbucket_import/importers/issue_notes_importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importers/issue_notes_importer_spec.rb index 99371a2b0c2..3bd05088d9e 100644 --- a/spec/lib/gitlab/bitbucket_import/importers/issue_notes_importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importers/issue_notes_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketImport::Importers::IssueNotesImporter, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::BitbucketImport::Importers::IssueNotesImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:project) do create(:project, :import_started, import_source: 'namespace/repo', import_data_attributes: { diff --git a/spec/lib/gitlab/bitbucket_import/importers/issues_importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importers/issues_importer_spec.rb index 90987f6d3d4..b4c6fb085c6 100644 --- a/spec/lib/gitlab/bitbucket_import/importers/issues_importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importers/issues_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketImport::Importers::IssuesImporter, feature_category: :importers do +RSpec.describe Gitlab::BitbucketImport::Importers::IssuesImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:project) do create(:project, :import_started, import_data_attributes: { @@ -29,7 +29,7 @@ RSpec.describe Gitlab::BitbucketImport::Importers::IssuesImporter, feature_categ subject(:importer) { described_class.new(project) } - describe '#execute', :clean_gitlab_redis_cache do + describe '#execute' do context 'when the repo does not have issue tracking enabled' do before do allow(client).to receive(:repo).and_return(Bitbucket::Representation::Repo.new({ 'has_issues' => false })) diff --git a/spec/lib/gitlab/bitbucket_import/importers/issues_notes_importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importers/issues_notes_importer_spec.rb index 84dea203478..3bc6e43eff1 100644 --- a/spec/lib/gitlab/bitbucket_import/importers/issues_notes_importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importers/issues_notes_importer_spec.rb @@ -2,14 +2,14 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketImport::Importers::IssuesNotesImporter, feature_category: :importers do +RSpec.describe Gitlab::BitbucketImport::Importers::IssuesNotesImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:project) { create(:project, :import_started) } let_it_be(:issue_1) { create(:issue, project: project) } let_it_be(:issue_2) { create(:issue, project: project) } subject(:importer) { described_class.new(project) } - describe '#execute', :clean_gitlab_redis_cache do + describe '#execute' do it 'imports the notes from each issue in parallel' do expect(Gitlab::BitbucketImport::ImportIssueNotesWorker).to receive(:perform_in).twice diff --git a/spec/lib/gitlab/bitbucket_import/importers/lfs_objects_importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importers/lfs_objects_importer_spec.rb index 289a6de1e91..7e1efecb40c 100644 --- a/spec/lib/gitlab/bitbucket_import/importers/lfs_objects_importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importers/lfs_objects_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketImport::Importers::LfsObjectsImporter, feature_category: :importers do +RSpec.describe Gitlab::BitbucketImport::Importers::LfsObjectsImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:project) do create(:project, :import_started, import_data_attributes: { @@ -32,7 +32,7 @@ RSpec.describe Gitlab::BitbucketImport::Importers::LfsObjectsImporter, feature_c } end - describe '#execute', :clean_gitlab_redis_cache do + describe '#execute' do context 'when lfs is enabled' do before do allow(project).to receive(:lfs_enabled?).and_return(true) diff --git a/spec/lib/gitlab/bitbucket_import/importers/pull_request_importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importers/pull_request_importer_spec.rb index 7cef163db8d..8a1e97a848b 100644 --- a/spec/lib/gitlab/bitbucket_import/importers/pull_request_importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importers/pull_request_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketImport::Importers::PullRequestImporter, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::BitbucketImport::Importers::PullRequestImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do include AfterNextHelpers let_it_be(:project) { create(:project, :repository) } diff --git a/spec/lib/gitlab/bitbucket_import/importers/pull_request_notes_importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importers/pull_request_notes_importer_spec.rb index 1949202640d..266b66dcd2c 100644 --- a/spec/lib/gitlab/bitbucket_import/importers/pull_request_notes_importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importers/pull_request_notes_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketImport::Importers::PullRequestNotesImporter, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::BitbucketImport::Importers::PullRequestNotesImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:project) do create(:project, :repository, :import_started, import_data_attributes: { diff --git a/spec/lib/gitlab/bitbucket_import/importers/pull_requests_importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importers/pull_requests_importer_spec.rb index 4d72c47d61a..32e3c3e3d7d 100644 --- a/spec/lib/gitlab/bitbucket_import/importers/pull_requests_importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importers/pull_requests_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketImport::Importers::PullRequestsImporter, feature_category: :importers do +RSpec.describe Gitlab::BitbucketImport::Importers::PullRequestsImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:project) do create(:project, :import_started, import_data_attributes: { @@ -14,7 +14,7 @@ RSpec.describe Gitlab::BitbucketImport::Importers::PullRequestsImporter, feature subject(:importer) { described_class.new(project) } - describe '#execute', :clean_gitlab_redis_cache do + describe '#execute' do before do allow_next_instance_of(Bitbucket::Client) do |client| allow(client).to receive(:pull_requests).and_return( diff --git a/spec/lib/gitlab/bitbucket_import/importers/pull_requests_notes_importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importers/pull_requests_notes_importer_spec.rb index b4c26ff7add..399be958ab9 100644 --- a/spec/lib/gitlab/bitbucket_import/importers/pull_requests_notes_importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importers/pull_requests_notes_importer_spec.rb @@ -2,14 +2,14 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketImport::Importers::PullRequestsNotesImporter, feature_category: :importers do +RSpec.describe Gitlab::BitbucketImport::Importers::PullRequestsNotesImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:project) { create(:project, :import_started) } let_it_be(:merge_request_1) { create(:merge_request, source_project: project) } let_it_be(:merge_request_2) { create(:merge_request, source_project: project, source_branch: 'other-branch') } subject(:importer) { described_class.new(project) } - describe '#execute', :clean_gitlab_redis_cache do + describe '#execute' do it 'imports the notes from each merge request in parallel' do expect(Gitlab::BitbucketImport::ImportPullRequestNotesWorker).to receive(:perform_in).twice diff --git a/spec/lib/gitlab/bitbucket_import/user_finder_spec.rb b/spec/lib/gitlab/bitbucket_import/user_finder_spec.rb index 4ac4c2e4813..83521dc58a5 100644 --- a/spec/lib/gitlab/bitbucket_import/user_finder_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/user_finder_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketImport::UserFinder, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::BitbucketImport::UserFinder, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:user) { create(:user) } let_it_be(:identity) { create(:identity, user: user, extern_uid: 'uid', provider: :bitbucket) } let(:created_id) { 1 } diff --git a/spec/lib/gitlab/bitbucket_server_import/importers/lfs_objects_importer_spec.rb b/spec/lib/gitlab/bitbucket_server_import/importers/lfs_objects_importer_spec.rb index aa901fe0146..7b81c26ed00 100644 --- a/spec/lib/gitlab/bitbucket_server_import/importers/lfs_objects_importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_server_import/importers/lfs_objects_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketServerImport::Importers::LfsObjectsImporter, feature_category: :importers do +RSpec.describe Gitlab::BitbucketServerImport::Importers::LfsObjectsImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:project) do create(:project, :import_started, import_data_attributes: { @@ -32,7 +32,7 @@ RSpec.describe Gitlab::BitbucketServerImport::Importers::LfsObjectsImporter, fea } end - describe '#execute', :clean_gitlab_redis_cache do + describe '#execute' do context 'when lfs is enabled' do before do allow(project).to receive(:lfs_enabled?).and_return(true) diff --git a/spec/lib/gitlab/bitbucket_server_import/importers/pull_requests_importer_spec.rb b/spec/lib/gitlab/bitbucket_server_import/importers/pull_requests_importer_spec.rb index b6477f17af4..3393cef5868 100644 --- a/spec/lib/gitlab/bitbucket_server_import/importers/pull_requests_importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_server_import/importers/pull_requests_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketServerImport::Importers::PullRequestsImporter, feature_category: :importers do +RSpec.describe Gitlab::BitbucketServerImport::Importers::PullRequestsImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do include RepoHelpers let_it_be(:project) do @@ -18,7 +18,7 @@ RSpec.describe Gitlab::BitbucketServerImport::Importers::PullRequestsImporter, f subject(:importer) { described_class.new(project) } - describe '#execute', :clean_gitlab_redis_cache, :clean_gitlab_redis_shared_state do + describe '#execute' do let(:commit_sha) { 'aaaa1' } let(:page_hash_1) do diff --git a/spec/lib/gitlab/bitbucket_server_import/user_finder_spec.rb b/spec/lib/gitlab/bitbucket_server_import/user_finder_spec.rb index 70923df3064..16aff872c6d 100644 --- a/spec/lib/gitlab/bitbucket_server_import/user_finder_spec.rb +++ b/spec/lib/gitlab/bitbucket_server_import/user_finder_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketServerImport::UserFinder, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::BitbucketServerImport::UserFinder, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:user) { create(:user) } let(:created_id) { 1 } diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index badc1d2eb3c..1ac2cd9c07b 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -1528,7 +1528,7 @@ RSpec.describe Gitlab::Git::Repository, feature_category: :source_code_managemen it "returns the number of commits in the whole repository" do options = { all: true } - expect(repository.count_commits(options)).to eq(322) + expect(repository.count_commits(options)).to eq(323) end end diff --git a/spec/lib/gitlab/github_import/clients/proxy_spec.rb b/spec/lib/gitlab/github_import/clients/proxy_spec.rb index 99fd98d2ed4..b6c9d477e4a 100644 --- a/spec/lib/gitlab/github_import/clients/proxy_spec.rb +++ b/spec/lib/gitlab/github_import/clients/proxy_spec.rb @@ -44,7 +44,7 @@ RSpec.describe Gitlab::GithubImport::Clients::Proxy, :manage, feature_category: end end - describe '#count_by', :clean_gitlab_redis_cache do + describe '#count_repos_by', :clean_gitlab_redis_shared_state do let(:client_stub) { instance_double(Gitlab::GithubImport::Client) } let(:client_response) { { data: { search: { repositoryCount: 1 } } } } diff --git a/spec/lib/gitlab/github_import/importer/attachments/issues_importer_spec.rb b/spec/lib/gitlab/github_import/importer/attachments/issues_importer_spec.rb index 223b7318d69..6ee6a943484 100644 --- a/spec/lib/gitlab/github_import/importer/attachments/issues_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/attachments/issues_importer_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Attachments::IssuesImporter, feat let(:client) { instance_double(Gitlab::GithubImport::Client) } - describe '#sequential_import', :clean_gitlab_redis_cache do + describe '#sequential_import', :clean_gitlab_redis_shared_state do let_it_be(:issue) { create(:issue, project: project) } let_it_be(:issue_with_attachment) do diff --git a/spec/lib/gitlab/github_import/importer/attachments/merge_requests_importer_spec.rb b/spec/lib/gitlab/github_import/importer/attachments/merge_requests_importer_spec.rb index 5449d4def1f..4329337dc9f 100644 --- a/spec/lib/gitlab/github_import/importer/attachments/merge_requests_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/attachments/merge_requests_importer_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Attachments::MergeRequestsImporte let(:client) { instance_double(Gitlab::GithubImport::Client) } - describe '#sequential_import', :clean_gitlab_redis_cache do + describe '#sequential_import', :clean_gitlab_redis_shared_state do let_it_be(:mr) { create(:merge_request, source_project: project, target_branch: 'feature1') } let_it_be(:mr_with_attachment) do diff --git a/spec/lib/gitlab/github_import/importer/attachments/notes_importer_spec.rb b/spec/lib/gitlab/github_import/importer/attachments/notes_importer_spec.rb index 8c90536cb1e..65433b482c2 100644 --- a/spec/lib/gitlab/github_import/importer/attachments/notes_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/attachments/notes_importer_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Attachments::NotesImporter, featu let(:client) { instance_double(Gitlab::GithubImport::Client) } - describe '#sequential_import', :clean_gitlab_redis_cache do + describe '#sequential_import', :clean_gitlab_redis_shared_state do let_it_be(:note) { create(:note, project: project) } let_it_be(:note_with_attachment) do diff --git a/spec/lib/gitlab/github_import/importer/attachments/releases_importer_spec.rb b/spec/lib/gitlab/github_import/importer/attachments/releases_importer_spec.rb index 4886cb923dc..8f1b6debcd6 100644 --- a/spec/lib/gitlab/github_import/importer/attachments/releases_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/attachments/releases_importer_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Attachments::ReleasesImporter, fe let(:client) { instance_double(Gitlab::GithubImport::Client) } - describe '#sequential_import', :clean_gitlab_redis_cache do + describe '#sequential_import', :clean_gitlab_redis_shared_state do let_it_be(:release) { create(:release, project: project) } let_it_be(:release_with_attachment) do diff --git a/spec/lib/gitlab/github_import/importer/events/cross_referenced_spec.rb b/spec/lib/gitlab/github_import/importer/events/cross_referenced_spec.rb index 3d1cd61f3ea..92f86ed0450 100644 --- a/spec/lib/gitlab/github_import/importer/events/cross_referenced_spec.rb +++ b/spec/lib/gitlab/github_import/importer/events/cross_referenced_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_gitlab_redis_shared_state, feature_category: :importers do subject(:importer) { described_class.new(project, client) } let_it_be(:project) { create(:project, :repository) } diff --git a/spec/lib/gitlab/github_import/importer/issue_event_importer_spec.rb b/spec/lib/gitlab/github_import/importer/issue_event_importer_spec.rb index ffe6c237506..57e53bf46b8 100644 --- a/spec/lib/gitlab/github_import/importer/issue_event_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/issue_event_importer_spec.rb @@ -2,8 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::Importer::IssueEventImporter, :clean_gitlab_redis_cache, - feature_category: :importers do +RSpec.describe Gitlab::GithubImport::Importer::IssueEventImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let(:importer) { described_class.new(issue_event, project, client) } let(:project) { build(:project) } diff --git a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb index 14342146f75..d042b5439d2 100644 --- a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:work_item_type_id) { ::WorkItems::Type.default_issue_type.id } let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } diff --git a/spec/lib/gitlab/github_import/importer/labels_importer_spec.rb b/spec/lib/gitlab/github_import/importer/labels_importer_spec.rb index 0328a36b646..3dd966e8de3 100644 --- a/spec/lib/gitlab/github_import/importer/labels_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/labels_importer_spec.rb @@ -2,8 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::Importer::LabelsImporter, :clean_gitlab_redis_cache, -feature_category: :importers do +RSpec.describe Gitlab::GithubImport::Importer::LabelsImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let(:project) { create(:project, import_source: 'foo/bar') } let(:client) { double(:client) } let(:importer) { described_class.new(project, client) } diff --git a/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb b/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb index fa7283d210b..a2dfdd09c58 100644 --- a/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb @@ -2,8 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::Importer::MilestonesImporter, :clean_gitlab_redis_cache, - feature_category: :importers do +RSpec.describe Gitlab::GithubImport::Importer::MilestonesImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let(:project) { create(:project, import_source: 'foo/bar') } let(:client) { double(:client) } let(:importer) { described_class.new(project, client) } diff --git a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb index 52c91d91eff..819c16cf932 100644 --- a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let(:project) { create(:project, :repository) } let(:client) { double(:client) } let(:user) { create(:user) } diff --git a/spec/lib/gitlab/github_import/importer/pull_requests/merged_by_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests/merged_by_importer_spec.rb index 8cd96295bbd..eae4c9cfa05 100644 --- a/spec/lib/gitlab/github_import/importer/pull_requests/merged_by_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/pull_requests/merged_by_importer_spec.rb @@ -2,8 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::Importer::PullRequests::MergedByImporter, - :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::GithubImport::Importer::PullRequests::MergedByImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:merge_request) { create(:merged_merge_request) } let(:project) { merge_request.project } diff --git a/spec/lib/gitlab/github_import/importer/pull_requests/review_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests/review_importer_spec.rb index 1651774b5ce..ffb14f06be4 100644 --- a/spec/lib/gitlab/github_import/importer/pull_requests/review_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/pull_requests/review_importer_spec.rb @@ -2,8 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::Importer::PullRequests::ReviewImporter, - :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::GithubImport::Importer::PullRequests::ReviewImporter, :clean_gitlab_redis_shared_state, feature_category: :importers do using RSpec::Parameterized::TableSyntax let_it_be(:merge_request) { create(:merge_request) } diff --git a/spec/lib/gitlab/github_import/importer/pull_requests/review_request_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests/review_request_importer_spec.rb index 6dcbc4e32e6..b1f84213ad9 100644 --- a/spec/lib/gitlab/github_import/importer/pull_requests/review_request_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/pull_requests/review_request_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::Importer::PullRequests::ReviewRequestImporter, :clean_gitlab_redis_cache do +RSpec.describe Gitlab::GithubImport::Importer::PullRequests::ReviewRequestImporter, :clean_gitlab_redis_shared_state do subject(:importer) { described_class.new(review_request, project, client) } let(:project) { instance_double('Project') } diff --git a/spec/lib/gitlab/github_import/issuable_finder_spec.rb b/spec/lib/gitlab/github_import/issuable_finder_spec.rb index 3fe07923a50..5dc6854cca1 100644 --- a/spec/lib/gitlab/github_import/issuable_finder_spec.rb +++ b/spec/lib/gitlab/github_import/issuable_finder_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::IssuableFinder, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::GithubImport::IssuableFinder, :clean_gitlab_redis_shared_state, feature_category: :importers do let(:project) { build(:project, id: 20, import_data_attributes: import_data_attributes) } let(:single_endpoint_optional_stage) { false } let(:import_data_attributes) do diff --git a/spec/lib/gitlab/github_import/label_finder_spec.rb b/spec/lib/gitlab/github_import/label_finder_spec.rb index 4c01e2b65da..d56dbd38c8e 100644 --- a/spec/lib/gitlab/github_import/label_finder_spec.rb +++ b/spec/lib/gitlab/github_import/label_finder_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::LabelFinder, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::GithubImport::LabelFinder, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:project) { create(:project) } let_it_be(:finder) { described_class.new(project) } let_it_be(:bug) { create(:label, project: project, name: 'Bug') } diff --git a/spec/lib/gitlab/github_import/milestone_finder_spec.rb b/spec/lib/gitlab/github_import/milestone_finder_spec.rb index 91f1c3b8cb9..357bbfc2aab 100644 --- a/spec/lib/gitlab/github_import/milestone_finder_spec.rb +++ b/spec/lib/gitlab/github_import/milestone_finder_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::MilestoneFinder, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::GithubImport::MilestoneFinder, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:project) { create(:project) } let_it_be(:milestone) { create(:milestone, project: project) } diff --git a/spec/lib/gitlab/github_import/representation/diff_note_spec.rb b/spec/lib/gitlab/github_import/representation/diff_note_spec.rb index be202733a89..5859c3021c9 100644 --- a/spec/lib/gitlab/github_import/representation/diff_note_spec.rb +++ b/spec/lib/gitlab/github_import/representation/diff_note_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::Representation::DiffNote, :clean_gitlab_redis_cache do +RSpec.describe Gitlab::GithubImport::Representation::DiffNote do let(:hunk) do '@@ -1 +1 @@ -Hello diff --git a/spec/lib/gitlab/github_import/representation/diff_notes/discussion_id_spec.rb b/spec/lib/gitlab/github_import/representation/diff_notes/discussion_id_spec.rb index 64a16516e07..0035a7c23a9 100644 --- a/spec/lib/gitlab/github_import/representation/diff_notes/discussion_id_spec.rb +++ b/spec/lib/gitlab/github_import/representation/diff_notes/discussion_id_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::Representation::DiffNotes::DiscussionId, :clean_gitlab_redis_cache, +RSpec.describe Gitlab::GithubImport::Representation::DiffNotes::DiscussionId, :clean_gitlab_redis_shared_state, feature_category: :importers do describe '#discussion_id' do let(:hunk) do diff --git a/spec/lib/gitlab/jira_import/base_importer_spec.rb b/spec/lib/gitlab/jira_import/base_importer_spec.rb index 70a594b09af..d4bf23a7b1a 100644 --- a/spec/lib/gitlab/jira_import/base_importer_spec.rb +++ b/spec/lib/gitlab/jira_import/base_importer_spec.rb @@ -43,7 +43,7 @@ RSpec.describe Gitlab::JiraImport::BaseImporter do it { expect(subject.send(:imported_items_cache_key)).to eq('dumb-importer-key') } end - describe '#mark_as_imported', :clean_gitlab_redis_cache do + describe '#mark_as_imported', :clean_gitlab_redis_shared_state do it 'stores id in redis cache' do expect(Gitlab::Cache::Import::Caching).to receive(:set_add).once.and_call_original @@ -53,7 +53,7 @@ RSpec.describe Gitlab::JiraImport::BaseImporter do end end - describe '#already_imported?', :clean_gitlab_redis_cache do + describe '#already_imported?', :clean_gitlab_redis_shared_state do it 'returns false if value is not in cache' do expect(Gitlab::Cache::Import::Caching).to receive(:set_includes?).once.and_call_original diff --git a/spec/lib/gitlab/jira_import/issues_importer_spec.rb b/spec/lib/gitlab/jira_import/issues_importer_spec.rb index 36135c56dd9..81526fda3cd 100644 --- a/spec/lib/gitlab/jira_import/issues_importer_spec.rb +++ b/spec/lib/gitlab/jira_import/issues_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::JiraImport::IssuesImporter do +RSpec.describe Gitlab::JiraImport::IssuesImporter, :clean_gitlab_redis_shared_state do include JiraIntegrationHelpers let_it_be(:user) { create(:user) } @@ -23,7 +23,7 @@ RSpec.describe Gitlab::JiraImport::IssuesImporter do it { expect(subject.imported_items_cache_key).to eq("jira-importer/already-imported/#{project.id}/issues") } end - describe '#execute', :clean_gitlab_redis_cache do + describe '#execute' do context 'when no returned issues' do it 'does not schedule any import jobs' do expect(subject).to receive(:fetch_issues).with(0).and_return([]) diff --git a/spec/lib/gitlab/jira_import/labels_importer_spec.rb b/spec/lib/gitlab/jira_import/labels_importer_spec.rb index 7579e2c65f4..174afcc2dc4 100644 --- a/spec/lib/gitlab/jira_import/labels_importer_spec.rb +++ b/spec/lib/gitlab/jira_import/labels_importer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::JiraImport::LabelsImporter do +RSpec.describe Gitlab::JiraImport::LabelsImporter, :clean_gitlab_redis_shared_state do include JiraIntegrationHelpers let_it_be(:user) { create(:user) } @@ -18,7 +18,7 @@ RSpec.describe Gitlab::JiraImport::LabelsImporter do stub_const('Gitlab::JiraImport::LabelsImporter::MAX_LABELS', 2) end - describe '#execute', :clean_gitlab_redis_cache do + describe '#execute' do before do stub_jira_integration_test end diff --git a/spec/lib/gitlab/sidekiq_middleware/pause_control/client_spec.rb b/spec/lib/gitlab/sidekiq_middleware/pause_control/client_spec.rb index 0a837f6f932..0d7ed09be7a 100644 --- a/spec/lib/gitlab/sidekiq_middleware/pause_control/client_spec.rb +++ b/spec/lib/gitlab/sidekiq_middleware/pause_control/client_spec.rb @@ -24,7 +24,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::PauseControl::Client, :clean_gitlab_re describe '#call' do context 'when strategy is enabled' do before do - stub_feature_flags(zoekt_pause_indexing: true) + allow(Gitlab::CurrentSettings).to receive(:zoekt_indexing_paused?).and_return(true) end it 'does not schedule the job' do @@ -38,7 +38,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::PauseControl::Client, :clean_gitlab_re context 'when strategy is disabled' do before do - stub_feature_flags(zoekt_pause_indexing: false) + allow(Gitlab::CurrentSettings).to receive(:zoekt_indexing_paused?).and_return(false) end it 'schedules the job' do diff --git a/spec/lib/gitlab/sidekiq_middleware/pause_control/server_spec.rb b/spec/lib/gitlab/sidekiq_middleware/pause_control/server_spec.rb index c577f9697b2..d44b162f335 100644 --- a/spec/lib/gitlab/sidekiq_middleware/pause_control/server_spec.rb +++ b/spec/lib/gitlab/sidekiq_middleware/pause_control/server_spec.rb @@ -35,7 +35,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::PauseControl::Server, :clean_gitlab_re describe '#call' do context 'when strategy is enabled' do before do - stub_feature_flags(zoekt_pause_indexing: true) + allow(Gitlab::CurrentSettings).to receive(:zoekt_indexing_paused?).and_return(true) end it 'puts the job to another queue without execution' do @@ -55,7 +55,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::PauseControl::Server, :clean_gitlab_re context 'when strategy is disabled' do before do - stub_feature_flags(zoekt_pause_indexing: false) + allow(Gitlab::CurrentSettings).to receive(:zoekt_indexing_paused?).and_return(false) end it 'executes the job' do diff --git a/spec/models/bulk_imports/export_status_spec.rb b/spec/models/bulk_imports/export_status_spec.rb index 4c0039e97e6..5a3f37b8de1 100644 --- a/spec/models/bulk_imports/export_status_spec.rb +++ b/spec/models/bulk_imports/export_status_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe BulkImports::ExportStatus, :clean_gitlab_redis_cache, :clean_gitlab_redis_shared_state, feature_category: :importers do +RSpec.describe BulkImports::ExportStatus, :clean_gitlab_redis_shared_state, feature_category: :importers do let_it_be(:relation) { 'labels' } let_it_be(:import) { create(:bulk_import) } let_it_be(:config) { create(:bulk_import_configuration, bulk_import: import) } diff --git a/spec/models/packages/conan/metadatum_spec.rb b/spec/models/packages/conan/metadatum_spec.rb index 92c8b126639..f0a3ef318ff 100644 --- a/spec/models/packages/conan/metadatum_spec.rb +++ b/spec/models/packages/conan/metadatum_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Packages::Conan::Metadatum, type: :model do +RSpec.describe Packages::Conan::Metadatum, type: :model, feature_category: :package_registry do using RSpec::Parameterized::TableSyntax describe 'relationships' do @@ -70,16 +70,6 @@ RSpec.describe Packages::Conan::Metadatum, type: :model do it { is_expected.to eq(valid) } end end - - describe '#conan_package_type' do - it 'will not allow a package with a different package_type' do - package = build('package') - conan_metadatum = build('conan_metadatum', package: package) - - expect(conan_metadatum).not_to be_valid - expect(conan_metadatum.errors.to_a).to include('Package type must be Conan') - end - end end describe '#recipe' do diff --git a/spec/models/packages/conan/package_spec.rb b/spec/models/packages/conan/package_spec.rb new file mode 100644 index 00000000000..4e97b4e69b4 --- /dev/null +++ b/spec/models/packages/conan/package_spec.rb @@ -0,0 +1,102 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Packages::Conan::Package, type: :model, feature_category: :package_registry do + describe 'relationships' do + it { is_expected.to have_one(:conan_metadatum).inverse_of(:package) } + end + + describe 'validations' do + subject { build_stubbed(:conan_package) } + + describe '#name' do + let(:fifty_one_characters) { 'f_b' * 17 } + + it { is_expected.to allow_value('foo+bar').for(:name) } + it { is_expected.to allow_value('foo_bar').for(:name) } + it { is_expected.to allow_value('foo.bar').for(:name) } + it { is_expected.to allow_value('9foo+bar').for(:name) } + it { is_expected.not_to allow_value(fifty_one_characters).for(:name) } + it { is_expected.not_to allow_value('+foobar').for(:name) } + it { is_expected.not_to allow_value('.foobar').for(:name) } + it { is_expected.not_to allow_value('%foo%bar').for(:name) } + end + + describe '#version' do + let(:fifty_one_characters) { '1.2' * 17 } + + it { is_expected.to allow_value('1.2').for(:version) } + it { is_expected.to allow_value('1.2.3-beta').for(:version) } + it { is_expected.to allow_value('1.2.3-pre1+build2').for(:version) } + it { is_expected.not_to allow_value('1').for(:version) } + it { is_expected.not_to allow_value(fifty_one_characters).for(:version) } + it { is_expected.not_to allow_value('1./2.3').for(:version) } + it { is_expected.not_to allow_value('.1.2.3').for(:version) } + it { is_expected.not_to allow_value('+1.2.3').for(:version) } + it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) } + end + + context 'for recipe uniqueness' do + let_it_be(:package) { create(:conan_package) } + let_it_be(:new_package) do + build(:conan_package, project: package.project, name: package.name, version: package.version) + end + + it 'does not allow a conan package with same recipe' do + expect(new_package).not_to be_valid + expect(new_package.errors.to_a).to include('Package recipe already exists') + end + + it 'allows a conan package with same project, name, version and package_type but different channel' do + new_package.conan_metadatum.package_channel = 'beta' + expect(new_package).to be_valid + end + + it 'allows a conan package with same project, name, version and package_type, but different package username' do + new_package.conan_metadatum.package_username = 'asdf99' + expect(new_package).to be_valid + end + + context 'with pending destruction package' do + let_it_be(:package) { create(:conan_package, :pending_destruction) } + + it 'allows a conan package with same recipe' do + expect(new_package).to be_valid + end + end + end + end + + describe 'scopes' do + let_it_be(:package) { create(:conan_package) } + + describe '.with_conan_channel' do + subject { described_class.with_conan_channel('stable') } + + it 'includes only packages with specified version' do + is_expected.to include(package) + end + end + + describe '.with_conan_username' do + subject do + described_class.with_conan_username( + Packages::Conan::Metadatum.package_username_from(full_path: package.project.full_path) + ) + end + + it 'includes only packages with specified version' do + is_expected.to match_array([package]) + end + end + + describe '.preload_conan_metadatum' do + subject(:packages) { described_class.preload_conan_metadatum } + + it 'loads conan metadatum' do + expect(packages.first.association(:conan_metadatum)).to be_loaded + end + end + end +end diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb index c022958642d..86337e3de2b 100644 --- a/spec/models/packages/package_spec.rb +++ b/spec/models/packages/package_spec.rb @@ -17,7 +17,6 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis it { is_expected.to have_many(:tags).inverse_of(:package) } it { is_expected.to have_many(:build_infos).inverse_of(:package) } it { is_expected.to have_many(:installable_nuget_package_files).inverse_of(:package) } - it { is_expected.to have_one(:conan_metadatum).inverse_of(:package) } it { is_expected.to have_one(:maven_metadatum).inverse_of(:package) } it { is_expected.to have_one(:debian_publication).inverse_of(:package).class_name('Packages::Debian::Publication') } it { is_expected.to have_one(:debian_distribution).through(:debian_publication).source(:distribution).inverse_of(:packages).class_name('Packages::Debian::ProjectDistribution') } @@ -157,20 +156,6 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis it { is_expected.to allow_value("my.app-11.07.2018").for(:name) } it { is_expected.not_to allow_value("my(dom$$$ain)com.my-app").for(:name) } - context 'conan package' do - subject { build_stubbed(:conan_package) } - - let(:fifty_one_characters) { 'f_b' * 17 } - - it { is_expected.to allow_value('foo+bar').for(:name) } - it { is_expected.to allow_value('foo_bar').for(:name) } - it { is_expected.to allow_value('foo.bar').for(:name) } - it { is_expected.not_to allow_value(fifty_one_characters).for(:name) } - it { is_expected.not_to allow_value('+foobar').for(:name) } - it { is_expected.not_to allow_value('.foobar').for(:name) } - it { is_expected.not_to allow_value('%foo%bar').for(:name) } - end - context 'debian package' do subject { build(:debian_package) } @@ -269,22 +254,6 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis end end - context 'conan package' do - subject { build_stubbed(:conan_package) } - - let(:fifty_one_characters) { '1.2' * 17 } - - it { is_expected.to allow_value('1.2').for(:version) } - it { is_expected.to allow_value('1.2.3-beta').for(:version) } - it { is_expected.to allow_value('1.2.3-pre1+build2').for(:version) } - it { is_expected.not_to allow_value('1').for(:version) } - it { is_expected.not_to allow_value(fifty_one_characters).for(:version) } - it { is_expected.not_to allow_value('1./2.3').for(:version) } - it { is_expected.not_to allow_value('.1.2.3').for(:version) } - it { is_expected.not_to allow_value('+1.2.3').for(:version) } - it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) } - end - context 'composer package' do it_behaves_like 'validating version to be SemVer compliant for', :composer_package @@ -639,31 +608,6 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis end end - context "recipe uniqueness for conan packages" do - let_it_be(:package) { create(:conan_package) } - - it "will allow a conan package with same project, name, version and package_type" do - new_package = build(:conan_package, project: package.project, name: package.name, version: package.version) - new_package.conan_metadatum.package_channel = 'beta' - expect(new_package).to be_valid - end - - it "will not allow a conan package with same recipe (name, version, metadatum.package_channel, metadatum.package_username, and package_type)" do - new_package = build(:conan_package, project: package.project, name: package.name, version: package.version) - expect(new_package).not_to be_valid - expect(new_package.errors.to_a).to include("Package recipe already exists") - end - - context 'with pending destruction package' do - let_it_be(:package) { create(:conan_package, :pending_destruction) } - - it 'will allow a conan package with same recipe (name, version, metadatum.package_channel, metadatum.package_username, and package_type)' do - new_package = build(:conan_package, project: package.project, name: package.name, version: package.version) - expect(new_package).to be_valid - end - end - end - describe '#valid_composer_global_name' do let_it_be(:package) { create(:composer_package) } @@ -840,38 +784,6 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis end end - context 'conan scopes' do - let!(:package) { create(:conan_package) } - - describe '.with_conan_channel' do - subject { described_class.with_conan_channel('stable') } - - it 'includes only packages with specified version' do - is_expected.to include(package) - end - end - - describe '.with_conan_username' do - subject do - described_class.with_conan_username( - Packages::Conan::Metadatum.package_username_from(full_path: package.project.full_path) - ) - end - - it 'includes only packages with specified version' do - is_expected.to match_array([package]) - end - end - - describe '.preload_conan_metadatum' do - subject { described_class.preload_conan_metadatum } - - it 'loads conan metadatum' do - expect(subject.first.association(:conan_metadatum)).to be_loaded - end - end - end - describe '.with_npm_scope' do let_it_be(:package1) { create(:npm_package, name: '@test/foobar') } let_it_be(:package2) { create(:npm_package, name: '@test2/foobar') } diff --git a/spec/presenters/packages/conan/package_presenter_spec.rb b/spec/presenters/packages/conan/package_presenter_spec.rb index 9b74d2e637e..0fe810ef59c 100644 --- a/spec/presenters/packages/conan/package_presenter_spec.rb +++ b/spec/presenters/packages/conan/package_presenter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe ::Packages::Conan::PackagePresenter do +RSpec.describe ::Packages::Conan::PackagePresenter, feature_category: :package_registry do let_it_be(:user) { create(:user) } let_it_be(:package) { create(:conan_package) } let_it_be(:project) { package.project } diff --git a/spec/presenters/packages/detail/package_presenter_spec.rb b/spec/presenters/packages/detail/package_presenter_spec.rb index 6dea887eb28..ef95d6f28ba 100644 --- a/spec/presenters/packages/detail/package_presenter_spec.rb +++ b/spec/presenters/packages/detail/package_presenter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe ::Packages::Detail::PackagePresenter do +RSpec.describe ::Packages::Detail::PackagePresenter, feature_category: :package_registry do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, creator: user) } let_it_be(:package) { create(:npm_package, :with_build, project: project) } diff --git a/spec/services/packages/conan/create_package_service_spec.rb b/spec/services/packages/conan/create_package_service_spec.rb index db06463b7fa..7d36751f0e1 100644 --- a/spec/services/packages/conan/create_package_service_spec.rb +++ b/spec/services/packages/conan/create_package_service_spec.rb @@ -45,7 +45,23 @@ RSpec.describe Packages::Conan::CreatePackageService, feature_category: :package end it 'fails' do - expect { package }.to raise_exception(ActiveRecord::RecordInvalid) + expect { package }.to raise_error(ActiveRecord::RecordInvalid, /Conan metadatum package username is invalid/) + end + end + + context 'with existing recipe' do + let_it_be(:existing_package) { create(:conan_package, project: project) } + let(:params) do + { + package_name: existing_package.name, + package_version: existing_package.version, + package_username: existing_package.conan_metadatum.package_username, + package_channel: existing_package.conan_metadatum.package_channel + } + end + + it 'does not create a conan package with same recipe' do + expect { package }.to raise_error(ActiveRecord::RecordInvalid, /Package recipe already exists/) end end end diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb index 1007f5fc958..c9ea22a2f78 100644 --- a/spec/support/helpers/test_env.rb +++ b/spec/support/helpers/test_env.rb @@ -112,6 +112,7 @@ module TestEnv 'Ääh-test-utf-8' => '7975be0', 'ssh-signed-commit' => '7b5160f', 'changes-with-whitespace' => 'f2d141fadb33ceaafc95667c1a0a308ad5edc5f9', + 'changes-with-only-whitespace' => '80cffbb2ad86202171dd3c05b38b5b4523b447d3', 'lock-detection' => '1ada92f78a19f27cb442a0a205f1c451a3a15432' }.freeze diff --git a/spec/support/shared_contexts/policies/project_policy_shared_context.rb b/spec/support/shared_contexts/policies/project_policy_shared_context.rb index 218c7f89e34..d727a4d1ddf 100644 --- a/spec/support/shared_contexts/policies/project_policy_shared_context.rb +++ b/spec/support/shared_contexts/policies/project_policy_shared_context.rb @@ -71,6 +71,8 @@ RSpec.shared_context 'ProjectPolicy context' do admin_wiki create_deploy_token destroy_deploy_token manage_deploy_tokens push_to_delete_protected_branch read_deploy_token update_snippet destroy_upload admin_member_access_request rename_project manage_merge_request_settings + destroy_upload admin_member_access_request rename_project + create_protected_branch admin_protected_branch ] end diff --git a/spec/support/shared_examples/features/project/protected_branches_shared_examples.rb b/spec/support/shared_examples/features/project/protected_branches_shared_examples.rb new file mode 100644 index 00000000000..583c085ecab --- /dev/null +++ b/spec/support/shared_examples/features/project/protected_branches_shared_examples.rb @@ -0,0 +1,100 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'setting project protected branches' do + describe "explicit protected branches" do + it "allows creating explicit protected branches" do + visit project_protected_branches_path(project) + + show_add_form + set_defaults + set_protected_branch_name('some->branch') + click_on "Protect" + + within(".protected-branches-list") { expect(page).to have_content('some->branch') } + expect(ProtectedBranch.count).to eq(1) + expect(ProtectedBranch.last.name).to eq('some->branch') + end + + it "displays the last commit on the matching branch if it exists" do + commit = create(:commit, project: project) + project.repository.add_branch(admin, 'some-branch', commit.id) + + visit project_protected_branches_path(project) + + show_add_form + set_defaults + set_protected_branch_name('some-branch') + click_on "Protect" + + within(".protected-branches-list") do + expect(page).not_to have_content("matching") + expect(page).not_to have_content("was deleted") + end + end + + it "displays an error message if the named branch does not exist" do + visit project_protected_branches_path(project) + + show_add_form + set_defaults + set_protected_branch_name('some-branch') + click_on "Protect" + + within(".protected-branches-list") { expect(page).to have_content('Branch does not exist') } + end + end + + describe "wildcard protected branches" do + it "allows creating protected branches with a wildcard" do + visit project_protected_branches_path(project) + + show_add_form + set_defaults + set_protected_branch_name('*-stable') + click_on "Protect" + + within(".protected-branches-list") { expect(page).to have_content('*-stable') } + expect(ProtectedBranch.count).to eq(1) + expect(ProtectedBranch.last.name).to eq('*-stable') + end + + it "displays the number of matching branches", + quarantine: 'https://gitlab.com/gitlab-org/quality/engineering-productivity/flaky-tests/-/issues/3459' do + project.repository.add_branch(admin, 'production-stable', 'master') + project.repository.add_branch(admin, 'staging-stable', 'master') + + visit project_protected_branches_path(project) + + show_add_form + set_defaults + set_protected_branch_name('*-stable') + click_on "Protect" + + within(".protected-branches-list") do + expect(page).to have_content("2 matching branches") + end + end + + it "displays all the branches matching the wildcard" do + project.repository.add_branch(admin, 'production-stable', 'master') + project.repository.add_branch(admin, 'staging-stable', 'master') + project.repository.add_branch(admin, 'development', 'master') + + visit project_protected_branches_path(project) + + show_add_form + set_protected_branch_name('*-stable') + set_defaults + click_on "Protect" + + visit project_protected_branches_path(project) + click_on "2 matching branches" + + within(".protected-branches-list") do + expect(page).to have_content("production-stable") + expect(page).to have_content("staging-stable") + expect(page).not_to have_content("development") + end + end + end +end diff --git a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb index c76bc7c3107..116e9874001 100644 --- a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb @@ -217,7 +217,7 @@ end RSpec.shared_examples 'handling validation error for package' do context 'with validation error' do before do - allow_next_instance_of(Packages::Package) do |instance| + allow_next_instance_of(::Packages::Conan::Package) do |instance| instance.errors.add(:base, 'validation error') allow(instance).to receive(:valid?).and_return(false) diff --git a/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb b/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb index 9c641c7254f..d82f0d6bff2 100644 --- a/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb +++ b/spec/workers/concerns/gitlab/github_import/rescheduling_methods_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::GithubImport::ReschedulingMethods, feature_category: :importers do +RSpec.describe Gitlab::GithubImport::ReschedulingMethods, :clean_gitlab_redis_shared_state, feature_category: :importers do let(:worker) do Class.new do def self.name @@ -32,7 +32,7 @@ RSpec.describe Gitlab::GithubImport::ReschedulingMethods, feature_category: :imp end end - context 'with an existing project', :clean_gitlab_redis_cache do + context 'with an existing project' do let(:project) { create(:project, import_url: 'https://t0ken@github.com/repo/repo.git') } before do diff --git a/spec/workers/gitlab/jira_import/stage/import_issues_worker_spec.rb b/spec/workers/gitlab/jira_import/stage/import_issues_worker_spec.rb index c8ab8cf7097..10b37e39045 100644 --- a/spec/workers/gitlab/jira_import/stage/import_issues_worker_spec.rb +++ b/spec/workers/gitlab/jira_import/stage/import_issues_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::JiraImport::Stage::ImportIssuesWorker, feature_category: :importers do +RSpec.describe Gitlab::JiraImport::Stage::ImportIssuesWorker, :clean_gitlab_redis_cache, feature_category: :importers do include JiraIntegrationHelpers let_it_be(:user) { create(:user) } @@ -24,7 +24,7 @@ RSpec.describe Gitlab::JiraImport::Stage::ImportIssuesWorker, feature_category: it_behaves_like 'does not advance to next stage' end - context 'when import started', :clean_gitlab_redis_cache do + context 'when import started' do let(:job_waiter) { Gitlab::JobWaiter.new(2, 'some-job-key') } before_all do diff --git a/yarn.lock b/yarn.lock index 62ac7397e21..3fd32010349 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1331,10 +1331,10 @@ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.99.0.tgz#85d2752787c3a87d40d5468a797e67c1e736a9fc" integrity sha512-N1y2W8ti0Pw7N8UYUdcl7DQuIZfOcL0R85EzJlSgXLt+I0NdmX4s3CCqBV1g62ZDxLgfDqBfiLKLCcYz8JkJ8w== -"@gitlab/ui@80.8.1": - version "80.8.1" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-80.8.1.tgz#8f66aefb63dd704fc3136d792d2d24c0ab7af5f1" - integrity sha512-YMA5+dOumj0pftZlhWT17Za8KwU+zQf7BtLs1Ii0cUlK1eHvmFhD6wZ2e74lXBDfUcBC0HmobF5Cb5BuKo5U4g== +"@gitlab/ui@80.10.0": + version "80.10.0" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-80.10.0.tgz#3c748d3127197e1d576aee7546497286e169bdf9" + integrity sha512-SL/obWt6uMVEW1qYSBNaI8U1sekInuckDQbdRH5eo6sjICdlOljm0rTvYaH8hux188sIFhuLD7Ovl84UhF6PFg== dependencies: "@floating-ui/dom" "1.4.3" bootstrap-vue "2.23.1"