diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2024-01-16 21:09:25 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2024-01-16 21:09:25 +0300 |
commit | e18006fc6313b1d04128416cdb5f1533adcdb53e (patch) | |
tree | ad418c4afbfcc8f83bcf5b4a9c897a2139e79e13 | |
parent | cb8835f38a3e4c188e9a73adf45936e2a95f40ae (diff) |
Add latest changes from gitlab-org/gitlab@master
83 files changed, 565 insertions, 565 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7998dbd8b96..d2f1fc8c2ff 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -56,7 +56,7 @@ default: workflow: name: '$PIPELINE_NAME' rules: - - if: '$CI_PROJECT_PATH == "gitlab-org/gitaly" && $CI_PIPELINE_SOURCE == "parent_pipeline" && $GITALY_TEST' + - if: '$CI_PIPELINE_SOURCE == "pipeline" && $GITALY_TEST' variables: <<: *default-ruby-variables PIPELINE_NAME: 'Gitaly Rails Test Pipeline' diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index ab603ecb9f2..539d1a0bdf1 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -1151,6 +1151,7 @@ when: never # If any of the files that are DIRECTLY related to generating or managing the GLFM specification change, # run `glfm-verify` to get quick feedback on any needed updates, even if the MR is not yet approved + - <<: *if-default-refs - changes: *glfm-patterns # Otherwise do not run `glfm-verify` if the MR is not approved - <<: *if-merge-request-not-approved @@ -1158,6 +1159,7 @@ # If we passed all the previous rules, run `glfm-verify` if there are any changes that could impact `glfm-verify`. # This could potentially be a wide range of files, so we reuse `setup-test-env-patterns`, which includes # almost all app files except docs files. + - <<: *if-default-refs - changes: *setup-test-env-patterns # If we are forcing all rspec to run, run this job too. - <<: *if-merge-request-labels-run-all-rspec @@ -1233,6 +1235,7 @@ .frontend:rules:compile-test-assets: rules: - if: '$ENABLE_COMPILE_TEST_ASSETS == "true"' + - if: '$ENABLE_RSPEC == "true"' - <<: *if-merge-request-labels-run-all-rspec - <<: *if-merge-request changes: *backend-patterns diff --git a/app/assets/javascripts/issues/show/components/description.vue b/app/assets/javascripts/issues/show/components/description.vue index 369aa694739..a0bc76537fa 100644 --- a/app/assets/javascripts/issues/show/components/description.vue +++ b/app/assets/javascripts/issues/show/components/description.vue @@ -20,7 +20,7 @@ import { sprintfWorkItem, I18N_WORK_ITEM_ERROR_CREATING, I18N_WORK_ITEM_ERROR_DELETING, - TASK_TYPE_NAME, + WORK_ITEM_TYPE_VALUE_TASK, } from '~/work_items/constants'; import { renderGFM } from '~/behaviors/markdown/render_gfm'; import eventHub from '../event_hub'; @@ -129,7 +129,7 @@ export default { }, computed: { taskWorkItemTypeId() { - return this.workItemTypes.find((type) => type.name === TASK_TYPE_NAME)?.id; + return this.workItemTypes.find((type) => type.name === WORK_ITEM_TYPE_VALUE_TASK)?.id; }, issueGid() { return this.issueId ? convertToGraphQLId(TYPENAME_WORK_ITEM, this.issueId) : null; diff --git a/app/assets/javascripts/work_items/components/notes/work_item_comment_form.vue b/app/assets/javascripts/work_items/components/notes/work_item_comment_form.vue index 9ede327b2f1..480549452ad 100644 --- a/app/assets/javascripts/work_items/components/notes/work_item_comment_form.vue +++ b/app/assets/javascripts/work_items/components/notes/work_item_comment_form.vue @@ -4,7 +4,11 @@ import { helpPagePath } from '~/helpers/help_page_helper'; import { s__, __ } from '~/locale'; import Tracking from '~/tracking'; import { capitalizeFirstCharacter } from '~/lib/utils/text_utility'; -import { STATE_OPEN, TRACKING_CATEGORY_SHOW, TASK_TYPE_NAME } from '~/work_items/constants'; +import { + STATE_OPEN, + TRACKING_CATEGORY_SHOW, + WORK_ITEM_TYPE_VALUE_TASK, +} from '~/work_items/constants'; import { getDraft, clearDraft, updateDraft } from '~/lib/utils/autosave'; import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal'; import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue'; @@ -127,10 +131,12 @@ export default { return this.isNoteInternal ? this.$options.i18n.addInternalNote : this.commentButtonText; }, workItemDocPath() { - return this.workItemType === TASK_TYPE_NAME ? 'user/tasks.html' : 'user/okrs.html'; + return this.workItemType === WORK_ITEM_TYPE_VALUE_TASK ? 'user/tasks.html' : 'user/okrs.html'; }, workItemDocAnchor() { - return this.workItemType === TASK_TYPE_NAME ? 'confidential-tasks' : 'confidential-okrs'; + return this.workItemType === WORK_ITEM_TYPE_VALUE_TASK + ? 'confidential-tasks' + : 'confidential-okrs'; }, getWorkItemData() { return { diff --git a/app/assets/javascripts/work_items/components/notes/work_item_comment_locked.vue b/app/assets/javascripts/work_items/components/notes/work_item_comment_locked.vue index c1b6903cf17..31330204b7e 100644 --- a/app/assets/javascripts/work_items/components/notes/work_item_comment_locked.vue +++ b/app/assets/javascripts/work_items/components/notes/work_item_comment_locked.vue @@ -2,7 +2,7 @@ import { GlLink, GlIcon } from '@gitlab/ui'; import { __, sprintf } from '~/locale'; import { helpPagePath } from '~/helpers/help_page_helper'; -import { TASK_TYPE_NAME } from '~/work_items/constants'; +import { WORK_ITEM_TYPE_VALUE_TASK } from '~/work_items/constants'; export default { components: { @@ -13,7 +13,7 @@ export default { workItemType: { required: false, type: String, - default: TASK_TYPE_NAME, + default: WORK_ITEM_TYPE_VALUE_TASK, }, isProjectArchived: { required: false, diff --git a/app/assets/javascripts/work_items/components/shared/work_item_link_child_contents.vue b/app/assets/javascripts/work_items/components/shared/work_item_link_child_contents.vue index 78afb9a04ef..7ea2b7ff86a 100644 --- a/app/assets/javascripts/work_items/components/shared/work_item_link_child_contents.vue +++ b/app/assets/javascripts/work_items/components/shared/work_item_link_child_contents.vue @@ -6,7 +6,6 @@ import RichTimestampTooltip from '~/vue_shared/components/rich_timestamp_tooltip import WorkItemLinkChildMetadata from 'ee_else_ce/work_items/components/shared/work_item_link_child_metadata.vue'; import { STATE_OPEN, - TASK_TYPE_NAME, WIDGET_TYPE_PROGRESS, WIDGET_TYPE_HIERARCHY, WIDGET_TYPE_HEALTH_STATUS, @@ -14,6 +13,7 @@ import { WIDGET_TYPE_ASSIGNEES, WIDGET_TYPE_LABELS, WORK_ITEM_NAME_TO_ICON_MAP, + WORK_ITEM_TYPE_VALUE_TASK, } from '../../constants'; export default { @@ -79,7 +79,7 @@ export default { return this.childItem.state === STATE_OPEN; }, iconName() { - if (this.childItemType === TASK_TYPE_NAME && !this.showTaskIcon) { + if (this.childItemType === WORK_ITEM_TYPE_VALUE_TASK && !this.showTaskIcon) { return this.isChildItemOpen ? 'issue-open-m' : 'issue-close'; } return WORK_ITEM_NAME_TO_ICON_MAP[this.childItemType]; @@ -88,7 +88,7 @@ export default { return this.childItem.workItemType.name; }, iconClass() { - if (this.childItemType === TASK_TYPE_NAME && !this.showTaskIcon) { + if (this.childItemType === WORK_ITEM_TYPE_VALUE_TASK && !this.showTaskIcon) { return this.isChildItemOpen ? 'gl-text-green-500' : 'gl-text-blue-500'; } return ''; diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_link_child.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_link_child.vue index f43718c4cb8..1de737765e2 100644 --- a/app/assets/javascripts/work_items/components/work_item_links/work_item_link_child.vue +++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_link_child.vue @@ -8,10 +8,10 @@ import { createAlert } from '~/alert'; import updateWorkItemMutation from '../../graphql/update_work_item.mutation.graphql'; import { STATE_OPEN, - TASK_TYPE_NAME, - WORK_ITEM_TYPE_VALUE_OBJECTIVE, WIDGET_TYPE_HIERARCHY, WORK_ITEM_NAME_TO_ICON_MAP, + WORK_ITEM_TYPE_VALUE_OBJECTIVE, + WORK_ITEM_TYPE_VALUE_TASK, } from '../../constants'; import getWorkItemTreeQuery from '../../graphql/work_item_tree.query.graphql'; import WorkItemLinkChildContents from '../shared/work_item_link_child_contents.vue'; @@ -76,13 +76,13 @@ export default { return this.childItem.workItemType.name; }, iconName() { - if (this.childItemType === TASK_TYPE_NAME) { + if (this.childItemType === WORK_ITEM_TYPE_VALUE_TASK) { return this.isItemOpen ? 'issue-open-m' : 'issue-close'; } return WORK_ITEM_NAME_TO_ICON_MAP[this.childItemType]; }, iconClass() { - if (this.childItemType === TASK_TYPE_NAME) { + if (this.childItemType === WORK_ITEM_TYPE_VALUE_TASK) { return this.isItemOpen ? 'gl-text-green-500' : 'gl-text-blue-500'; } return ''; diff --git a/app/assets/javascripts/work_items/constants.js b/app/assets/javascripts/work_items/constants.js index 62fdc8a21c2..fcf73e5f822 100644 --- a/app/assets/javascripts/work_items/constants.js +++ b/app/assets/javascripts/work_items/constants.js @@ -10,8 +10,6 @@ export const STATE_EVENT_CLOSE = 'CLOSE'; export const TRACKING_CATEGORY_SHOW = 'workItems:show'; -export const TASK_TYPE_NAME = 'Task'; - export const WIDGET_TYPE_ASSIGNEES = 'ASSIGNEES'; export const WIDGET_TYPE_DESCRIPTION = 'DESCRIPTION'; export const WIDGET_TYPE_AWARD_EMOJI = 'AWARD_EMOJI'; @@ -46,9 +44,6 @@ export const WORK_ITEM_TYPE_VALUE_REQUIREMENTS = 'Requirements'; export const WORK_ITEM_TYPE_VALUE_KEY_RESULT = 'Key Result'; export const WORK_ITEM_TYPE_VALUE_OBJECTIVE = 'Objective'; -export const NAMESPACE_GROUP = 'group'; -export const NAMESPACE_PROJECT = 'project'; - export const WORK_ITEM_TITLE_MAX_LENGTH = 255; export const i18n = { diff --git a/app/graphql/mutations/notes/create/discussion.rb b/app/graphql/mutations/notes/create/discussion.rb new file mode 100644 index 00000000000..c90f5565284 --- /dev/null +++ b/app/graphql/mutations/notes/create/discussion.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Mutations + module Notes + module Create + class Discussion < Base + graphql_name 'CreateDiscussion' + + private + + def create_note_params(noteable, args) + super(noteable, args).merge({ type: 'DiscussionNote' }) + end + end + end + end +end diff --git a/app/graphql/mutations/work_items/create.rb b/app/graphql/mutations/work_items/create.rb index 754b453ce5d..7ce508e5ef1 100644 --- a/app/graphql/mutations/work_items/create.rb +++ b/app/graphql/mutations/work_items/create.rb @@ -60,7 +60,6 @@ module Mutations def resolve(project_path: nil, namespace_path: nil, **attributes) container_path = project_path || namespace_path container = authorized_find!(container_path) - check_env_feature_available!(container) check_feature_available!(container) params = global_id_compatibility_params(attributes).merge(author_id: current_user.id) @@ -84,15 +83,6 @@ module Mutations private - # This is just a temporary measure while we migrate and backfill epic internal_ids - # More info in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139367 - def check_env_feature_available!(container) - return unless container.is_a?(::Group) && Rails.env.production? - - message = 'Group level work items are disabled. Only project paths allowed in `namespacePath`.' - raise Gitlab::Graphql::Errors::ArgumentError, message - end - def check_feature_available!(container) return unless container.is_a?(::Group) && Feature.disabled?(:namespace_level_work_items, container) diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb index 0a725c2e0a7..51ab6880b1a 100644 --- a/app/graphql/types/mutation_type.rb +++ b/app/graphql/types/mutation_type.rb @@ -102,6 +102,7 @@ module Types mount_mutation Mutations::Notes::Create::Note, calls_gitaly: true mount_mutation Mutations::Notes::Create::DiffNote, calls_gitaly: true mount_mutation Mutations::Notes::Create::ImageDiffNote, calls_gitaly: true + mount_mutation Mutations::Notes::Create::Discussion, calls_gitaly: true mount_mutation Mutations::Notes::Update::Note mount_mutation Mutations::Notes::Update::ImageDiffNote mount_mutation Mutations::Notes::RepositionImageDiffNote diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb index d0a9197db0a..61fe9e133ea 100644 --- a/app/helpers/auth_helper.rb +++ b/app/helpers/auth_helper.rb @@ -52,8 +52,7 @@ module AuthHelper saml: 'saml-login-button', openid_connect: 'oidc-login-button', github: 'github-login-button', - gitlab: 'gitlab-oauth-login-button', - facebook: 'facebook-login-button' + gitlab: 'gitlab-oauth-login-button' }[provider.to_sym] end diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index 96ae7be5fdc..7db833edff5 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -184,7 +184,7 @@ module GroupsHelper } end - def enabled_git_access_protocol_options_for_group(_) + def enabled_git_access_protocol_options_for_group case ::Gitlab::CurrentSettings.enabled_git_access_protocol when nil, "" [[_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]] diff --git a/app/helpers/work_items_helper.rb b/app/helpers/work_items_helper.rb index d2e3d41377a..b7e9699dc12 100644 --- a/app/helpers/work_items_helper.rb +++ b/app/helpers/work_items_helper.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module WorkItemsHelper - def work_items_index_data(resource_parent) + def work_items_show_data(resource_parent) { full_path: resource_parent.full_path, issues_list_path: diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 35d4722b711..490029ce0b5 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -240,7 +240,7 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord if: :auto_devops_enabled? validates :enabled_git_access_protocol, - inclusion: { in: ->(_) { enabled_git_access_protocol_values }, allow_blank: true } + inclusion: { in: %w[ssh http], allow_blank: true } validates :domain_denylist, presence: { message: 'Domain denylist cannot be empty if denylist is enabled.' }, @@ -898,10 +898,6 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord HUMANIZED_ATTRIBUTES[attribute.to_sym] || super end - def self.enabled_git_access_protocol_values - %w[ssh http] - end - def parsed_grafana_url @parsed_grafana_url ||= Gitlab::Utils.parse_url(grafana_url) end diff --git a/app/models/namespace_setting.rb b/app/models/namespace_setting.rb index e61e5a7f37e..95400beaf50 100644 --- a/app/models/namespace_setting.rb +++ b/app/models/namespace_setting.rb @@ -15,7 +15,7 @@ class NamespaceSetting < ApplicationRecord belongs_to :namespace, inverse_of: :namespace_settings enum jobs_to_be_done: { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5 }, _suffix: true - enum enabled_git_access_protocol: { all: 0, ssh: 1, http: 2, ssh_certificates: 3 }, _suffix: true + enum enabled_git_access_protocol: { all: 0, ssh: 1, http: 2 }, _suffix: true attribute :default_branch_protection_defaults, default: -> { {} } diff --git a/app/services/google_cloud_platform/artifact_registry/list_docker_images_service.rb b/app/services/google_cloud_platform/artifact_registry/list_docker_images_service.rb index c9afa8609f9..1e227a2fcb6 100644 --- a/app/services/google_cloud_platform/artifact_registry/list_docker_images_service.rb +++ b/app/services/google_cloud_platform/artifact_registry/list_docker_images_service.rb @@ -16,7 +16,7 @@ module GoogleCloudPlatform end def client - ::Integrations::GoogleCloudPlatform::ArtifactRegistry::Client.new( + ::GoogleCloudPlatform::ArtifactRegistry::Client.new( project: project, user: current_user, gcp_project_id: gcp_project_id, diff --git a/app/services/import/github_service.rb b/app/services/import/github_service.rb index ffd26e2aaca..92a91740304 100644 --- a/app/services/import/github_service.rb +++ b/app/services/import/github_service.rb @@ -5,6 +5,7 @@ module Import include ActiveSupport::NumberHelper include Gitlab::Utils::StrongMemoize + MINIMUM_IMPORT_SCOPE = %w[repo].freeze COLLAB_IMPORT_SCOPES = %w[admin:org read:org].freeze attr_accessor :client @@ -14,7 +15,7 @@ module Import context_error = validate_context return context_error if context_error - scope_error = validate_collaborators_import_scope + scope_error = validate_scopes return scope_error if scope_error project = create_project(access_params, provider) @@ -103,18 +104,22 @@ module Import private - def validate_collaborators_import_scope - collaborators_import = params.dig(:optional_stages, :collaborators_import) - # A value for `collaborators_import` may not be included in POST params - # and the default value is `true` - return unless collaborators_import == true || collaborators_import.nil? - + def validate_scopes # We need to call `#repo` to ensure the `#last_response` from the client has the headers we need. repo scopes = client.octokit.last_response.headers["x-oauth-scopes"] scopes = scopes.split(',').map(&:strip) - return if (scopes & COLLAB_IMPORT_SCOPES).any? + unless scopes.intersect?(MINIMUM_IMPORT_SCOPE + COLLAB_IMPORT_SCOPES) + return log_and_return_error('Invalid Scope', _('Your GitHub access token does not have the correct scope to import.'), :unprocessable_entity) + end + + collaborators_import = params.dig(:optional_stages, :collaborators_import) + # A value for `collaborators_import` may not be included in POST params + # and the default value is `true` + return unless collaborators_import == true || collaborators_import.nil? + + return if scopes.intersect?(COLLAB_IMPORT_SCOPES) log_and_return_error('Invalid scope', _('Your GitHub access token does not have the correct scope to import collaborators.'), :unprocessable_entity) end diff --git a/app/views/groups/settings/_git_access_protocols.html.haml b/app/views/groups/settings/_git_access_protocols.html.haml index c9cbe56e6ec..c6d32cae760 100644 --- a/app/views/groups/settings/_git_access_protocols.html.haml +++ b/app/views/groups/settings/_git_access_protocols.html.haml @@ -1,7 +1,7 @@ - if group.root? .form-group = f.label _('Enabled Git access protocols'), class: 'label-bold' - = f.select :enabled_git_access_protocol, options_for_select(enabled_git_access_protocol_options_for_group(group), group.enabled_git_access_protocol), {}, class: 'form-control', disabled: !::Gitlab::CurrentSettings.enabled_git_access_protocol.blank? + = f.select :enabled_git_access_protocol, options_for_select(enabled_git_access_protocol_options_for_group, group.enabled_git_access_protocol), {}, class: 'form-control', disabled: !::Gitlab::CurrentSettings.enabled_git_access_protocol.blank? - if !::Gitlab::CurrentSettings.enabled_git_access_protocol.blank? .form-text.text-muted = _("This setting has been configured at the instance level and cannot be overridden per group") diff --git a/app/views/groups/work_items/show.html.haml b/app/views/groups/work_items/show.html.haml index 7def8b0d6e6..7363d8f977a 100644 --- a/app/views/groups/work_items/show.html.haml +++ b/app/views/groups/work_items/show.html.haml @@ -4,4 +4,4 @@ - @gfm_form = true - @noteable_type = 'WorkItem' -#js-work-items{ data: work_items_index_data(@group).merge(iid: request.params['iid']) } +#js-work-items{ data: work_items_show_data(@group).merge(iid: request.params['iid']) } diff --git a/app/views/projects/issues/_work_item_links.html.haml b/app/views/projects/issues/_work_item_links.html.haml index bf23fdc761b..7a8f2163bf6 100644 --- a/app/views/projects/issues/_work_item_links.html.haml +++ b/app/views/projects/issues/_work_item_links.html.haml @@ -1,6 +1,6 @@ .js-work-item-links-root{ data: { issuable_id: @issue.id, issuable_iid: @issue.iid, full_path: @project.full_path, - wi: work_items_index_data(@project), + wi: work_items_show_data(@project), register_path: new_user_registration_path(redirect_to_referer: 'yes'), sign_in_path: new_session_path(:user, redirect_to_referer: 'yes') } } diff --git a/app/views/projects/work_items/show.html.haml b/app/views/projects/work_items/show.html.haml index 7e0bddf1b5d..c69e42917f1 100644 --- a/app/views/projects/work_items/show.html.haml +++ b/app/views/projects/work_items/show.html.haml @@ -4,4 +4,4 @@ - @gfm_form = true - @noteable_type = 'WorkItem' -#js-work-items{ data: work_items_index_data(@project) } +#js-work-items{ data: work_items_show_data(@project) } diff --git a/app/workers/concerns/gitlab/bitbucket_import/stage_methods.rb b/app/workers/concerns/gitlab/bitbucket_import/stage_methods.rb index 2885cc29532..51e2f5cff22 100644 --- a/app/workers/concerns/gitlab/bitbucket_import/stage_methods.rb +++ b/app/workers/concerns/gitlab/bitbucket_import/stage_methods.rb @@ -14,7 +14,7 @@ module Gitlab data_consistency :always - sidekiq_options dead: false, retry: 3 + sidekiq_options dead: false, retry: 6 sidekiq_retries_exhausted do |msg, e| Gitlab::Import::ImportFailureService.track( diff --git a/app/workers/concerns/gitlab/bitbucket_server_import/stage_methods.rb b/app/workers/concerns/gitlab/bitbucket_server_import/stage_methods.rb index db4e71051c0..cf5710e6108 100644 --- a/app/workers/concerns/gitlab/bitbucket_server_import/stage_methods.rb +++ b/app/workers/concerns/gitlab/bitbucket_server_import/stage_methods.rb @@ -14,7 +14,7 @@ module Gitlab data_consistency :always - sidekiq_options dead: false, retry: 3 + sidekiq_options dead: false, retry: 6 sidekiq_retries_exhausted do |msg, e| Gitlab::Import::ImportFailureService.track( diff --git a/app/workers/concerns/gitlab/jira_import/import_worker.rb b/app/workers/concerns/gitlab/jira_import/import_worker.rb index d18b9ff023b..c597e791cbe 100644 --- a/app/workers/concerns/gitlab/jira_import/import_worker.rb +++ b/app/workers/concerns/gitlab/jira_import/import_worker.rb @@ -8,9 +8,9 @@ module Gitlab included do include ApplicationWorker - sidekiq_options retry: 3 include ProjectImportOptions include Gitlab::JiraImport::QueueOptions + sidekiq_options retry: 6 end def perform(project_id) diff --git a/app/workers/gitlab/bitbucket_import/advance_stage_worker.rb b/app/workers/gitlab/bitbucket_import/advance_stage_worker.rb index ed89f332652..8242c5c8e9a 100644 --- a/app/workers/gitlab/bitbucket_import/advance_stage_worker.rb +++ b/app/workers/gitlab/bitbucket_import/advance_stage_worker.rb @@ -12,10 +12,6 @@ module Gitlab data_consistency :delayed - sidekiq_options dead: false, retry: 3 - - feature_category :importers - loggable_arguments 1, 2 # The known importer stages and their corresponding Sidekiq workers. diff --git a/app/workers/gitlab/bitbucket_server_import/advance_stage_worker.rb b/app/workers/gitlab/bitbucket_server_import/advance_stage_worker.rb index 1fc35725c9f..9ce3837e66f 100644 --- a/app/workers/gitlab/bitbucket_server_import/advance_stage_worker.rb +++ b/app/workers/gitlab/bitbucket_server_import/advance_stage_worker.rb @@ -12,10 +12,6 @@ module Gitlab data_consistency :delayed - sidekiq_options dead: false, retry: 3 - - feature_category :importers - loggable_arguments 1, 2 # The known importer stages and their corresponding Sidekiq workers. diff --git a/app/workers/gitlab/github_import/advance_stage_worker.rb b/app/workers/gitlab/github_import/advance_stage_worker.rb index 8de9850298b..316035fd683 100644 --- a/app/workers/gitlab/github_import/advance_stage_worker.rb +++ b/app/workers/gitlab/github_import/advance_stage_worker.rb @@ -14,8 +14,6 @@ module Gitlab include ::Gitlab::Import::AdvanceStage loggable_arguments 1, 2 - sidekiq_options retry: 6, dead: false - feature_category :importers # The known importer stages and their corresponding Sidekiq workers. # diff --git a/app/workers/gitlab/import/advance_stage.rb b/app/workers/gitlab/import/advance_stage.rb index 709957556d3..ccd5f906462 100644 --- a/app/workers/gitlab/import/advance_stage.rb +++ b/app/workers/gitlab/import/advance_stage.rb @@ -3,6 +3,8 @@ module Gitlab module Import module AdvanceStage + extend ActiveSupport::Concern + INTERVAL = 30.seconds.to_i TIMEOUT_DURATION = 2.hours @@ -12,6 +14,11 @@ module Gitlab # continuing to the next waiter. BLOCKING_WAIT_TIME = 5 + included do + sidekiq_options dead: false, retry: 6 + feature_category :importers + end + # project_id - The ID of the project being imported. # waiters - A Hash mapping Gitlab::JobWaiter keys to the number of # remaining jobs. diff --git a/app/workers/gitlab/jira_import/advance_stage_worker.rb b/app/workers/gitlab/jira_import/advance_stage_worker.rb index 9641b55a584..55285080d95 100644 --- a/app/workers/gitlab/jira_import/advance_stage_worker.rb +++ b/app/workers/gitlab/jira_import/advance_stage_worker.rb @@ -7,7 +7,6 @@ module Gitlab data_consistency :always - sidekiq_options retry: 3 include QueueOptions include ::Gitlab::Import::AdvanceStage diff --git a/app/workers/gitlab/jira_import/stage/start_import_worker.rb b/app/workers/gitlab/jira_import/stage/start_import_worker.rb index 3f6ad66e278..ceeccf41dee 100644 --- a/app/workers/gitlab/jira_import/stage/start_import_worker.rb +++ b/app/workers/gitlab/jira_import/stage/start_import_worker.rb @@ -8,11 +8,12 @@ module Gitlab data_consistency :always - sidekiq_options retry: 3 include ProjectStartImport include ProjectImportOptions include Gitlab::JiraImport::QueueOptions + sidekiq_options retry: 6 + attr_reader :project def perform(project_id) diff --git a/config/feature_flags/development/enforce_ssh_certificates.yml b/config/feature_flags/development/enforce_ssh_certificates.yml deleted file mode 100644 index beaa6c02869..00000000000 --- a/config/feature_flags/development/enforce_ssh_certificates.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: enforce_ssh_certificates -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132653 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/426235 -milestone: '16.5' -type: development -group: group::source code -default_enabled: false diff --git a/config/feature_flags/development/lfs_check.yml b/config/feature_flags/development/lfs_check.yml deleted file mode 100644 index 8e13d46a02f..00000000000 --- a/config/feature_flags/development/lfs_check.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: lfs_check -introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27451 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/233550 -milestone: '11.11' -type: development -group: group::source code -default_enabled: true diff --git a/data/whats_new/202401180001_16_8.yml b/data/whats_new/202401180001_16_8.yml index 694b082fed6..54ea99a54b1 100644 --- a/data/whats_new/202401180001_16_8.yml +++ b/data/whats_new/202401180001_16_8.yml @@ -1,34 +1,23 @@ -# This is a template for a "Whats New" release. -# A release typically contains multiple entries of features that we'd like to highlight. -# -# Below is an example of what a single entry should look like, it's required attributes, -# and what types we expect those attribute values to be. All attributes are required. -# -# For more information please refer to the handbook documentation here: -# https://about.gitlab.com/handbook/marketing/blog/release-posts/index.html#create-mr-for-whats-new-entries -# -# Please delete this line and above before submitting your merge request. - -- name: GCP Secret Manager support # Match the release post entry - description: | # Do not modify this line, instead modify the lines below. +- name: GCP Secret Manager support + description: | Secrets stored in GCP Secrets Manager can now be easily retrieved and used in CI/CD jobs. Our new integration simplifies the process of interacting with GCP Secrets Manager through GitLab CI/CD, helping you streamline your build and deploy processes! This is just one of the many ways [GitLab and Google Cloud are better together](https://about.gitlab.com/blog/2023/08/29/gitlab-google-partnership-s3c/)! - stage: Verify # String value of the stage that the feature was created in. e.g., Growth - self-managed: true # Boolean value (true or false) - gitlab-com: true # Boolean value (true or false) - available_in: [Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Premium, Ultimate] + stage: Verify + self-managed: true + gitlab-com: true + available_in: [Premium, Ultimate] documentation_link: https://docs.gitlab.com/ee/ci/secrets/gcp_secret_manager.html # This is the documentation URL, but can be a URL to a video if there is one - image_url: https://about.gitlab.com/images/16_8/gcp_secrets_mgr.png # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg - published_at: 2024-01-18 # YYYY-MM-DD - release: 16.8 # XX.Y + image_url: https://about.gitlab.com/images/16_8/gcp_secrets_mgr.png + published_at: 2024-01-18 + release: 16.8 -- name: Enforce 2FA for GitLab administrators # Match the release post entry - description: | # Do not modify this line, instead modify the lines below. +- name: Enforce 2FA for GitLab administrators + description: | You can now enforce whether GitLab administrators are required to use two-factor authentication (2FA) in their self-managed instance. It is good security practice to use 2FA for all accounts, especially for privileged accounts like administrators. If this setting is enforced, and an administrator does not already use 2FA, they must set 2FA up on their next sign-in. - stage: Govern # String value of the stage that the feature was created in. e.g., Growth - self-managed: true # Boolean value (true or false) - gitlab-com: false # Boolean value (true or false) - available_in: [Free, Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Premium, Ultimate] + stage: Govern + self-managed: true + gitlab-com: false + available_in: [Free, Premium, Ultimate] documentation_link: https://docs.gitlab.com/ee/security/two_factor_authentication.html#enforce-2fa-for-administrator-users # This is the documentation URL, but can be a URL to a video if there is one - image_url: https://img.youtube.com/vi/fHleeXzoB6k/hqdefault.jpg # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg - published_at: 2024-01-18 # YYYY-MM-DD - release: 16.8 # XX.Y + image_url: https://img.youtube.com/vi/fHleeXzoB6k/hqdefault.jpg + published_at: 2024-01-18 + release: 16.8 diff --git a/doc/administration/settings/sign_up_restrictions.md b/doc/administration/settings/sign_up_restrictions.md index 3ebb80c34ab..23aa3ee68de 100644 --- a/doc/administration/settings/sign_up_restrictions.md +++ b/doc/administration/settings/sign_up_restrictions.md @@ -83,6 +83,8 @@ by an administrator. Users can use their account only after they have been appro If an administrator increases or removes the user cap, users pending approval are automatically approved. +[View how to set up a user cap for groups](../../user/group/manage.md#user-cap-for-groups). + NOTE: For instances that use LDAP or OmniAuth, when [administrator approval for new sign-ups](#require-administrator-approval-for-new-sign-ups) is enabled or disabled, downtime might occur due to changes in the Rails configuration. diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index e8f95c5e5a3..1fa12bd1ee0 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -2683,6 +2683,28 @@ Input type: `CreateDiffNoteInput` | <a id="mutationcreatediffnoteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | | <a id="mutationcreatediffnotenote"></a>`note` | [`Note`](#note) | Note after mutation. | +### `Mutation.createDiscussion` + +Input type: `CreateDiscussionInput` + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="mutationcreatediscussionbody"></a>`body` | [`String!`](#string) | Content of the note. | +| <a id="mutationcreatediscussionclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| <a id="mutationcreatediscussionconfidential"></a>`confidential` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated:** This was renamed. Please use `internal`. Deprecated in 15.3. | +| <a id="mutationcreatediscussioninternal"></a>`internal` | [`Boolean`](#boolean) | Internal flag for a note. Default is false. | +| <a id="mutationcreatediscussionnoteableid"></a>`noteableId` | [`NoteableID!`](#noteableid) | Global ID of the resource to add a note to. | + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="mutationcreatediscussionclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| <a id="mutationcreatediscussionerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | +| <a id="mutationcreatediscussionnote"></a>`note` | [`Note`](#note) | Note after mutation. | + ### `Mutation.createEpic` Input type: `CreateEpicInput` diff --git a/doc/user/clusters/agent/gitops.md b/doc/user/clusters/agent/gitops.md index df63d8ce7be..7a3ab01e991 100644 --- a/doc/user/clusters/agent/gitops.md +++ b/doc/user/clusters/agent/gitops.md @@ -87,7 +87,7 @@ unnecessary pulls from GitLab. The agent for Kubernetes automatically detects Flux `GitRepository` objects that reference GitLab projects in the instance the agent is connected to, and configures a [`Receiver`](https://fluxcd.io/flux/components/notification/receiver/) for the instance. -When the agent for Kubernetes detects a `git push`, the `Receiver` is triggered +When the agent for Kubernetes detects a `git push` to a repository it has access to, the `Receiver` is triggered and Flux reconciles the cluster with any changes to the repository. To use immediate Git repository reconciliation, you must have a Kubernetes cluster that runs: @@ -100,6 +100,11 @@ but it doesn't guarantee that every `git push` event is received. You should sti [`GitRepository.spec.interval`](https://fluxcd.io/flux/components/source/gitrepositories/#interval) to an acceptable duration. +DISCLAIMER: +The agent only has access to the agent configuration project and all public projects. +The agent is not able to immediately reconcile any private projects, except the agent configuration project. +Allowing the agent to access private projects is proposed in [issue 389393](https://gitlab.com/gitlab-org/gitlab/-/issues/389393). + ### Custom webhook endpoints When the agent for Kubernetes calls the `Receiver` webhook, diff --git a/doc/user/index.md b/doc/user/index.md index 80f480d9e26..dc75d801330 100644 --- a/doc/user/index.md +++ b/doc/user/index.md @@ -9,10 +9,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w Get to know the GitLab end-to-end workflow. Configure permissions, organize your work, create and secure your application, and analyze its performance. Report on team productivity throughout the process. +- [Learn Git](../topics/git/index.md) - [Set up your organization](../topics/set_up_organization.md) - [Organize work with projects](../user/project/organize_work_with_projects.md) - [Plan and track work](../topics/plan_and_track.md) -- [Build your application](../topics/build_your_application.md) +- [Manage your code](../topics/manage_code.md) +- [Use CI/CD to build your application](../topics/build_your_application.md) - [Secure your application](../user/application_security/secure_your_application.md) - [Deploy and release your application](../topics/release_your_application.md) - [Monitor application performance](../operations/index.md) diff --git a/doc/user/project/repository/code_suggestions/repository_xray.md b/doc/user/project/repository/code_suggestions/repository_xray.md index d851ee94e34..465bfc8d16a 100644 --- a/doc/user/project/repository/code_suggestions/repository_xray.md +++ b/doc/user/project/repository/code_suggestions/repository_xray.md @@ -4,9 +4,11 @@ group: Code Creation info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments --- -# Repository X-Ray **(PREMIUM)** +# Repository X-Ray **(PREMIUM ALL)** -Repository X-Ray enhances GitLab Duo Code Suggestions by providing additional context to improve the accuracy and relevance of code recommendations. +> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/12060) in GitLab 16.7. + +Repository X-Ray enhances [GitLab Duo Code Suggestions](index.md) by providing additional context to improve the accuracy and relevance of code recommendations. Repository X-Ray gives the code assistant more insight into the project's codebase and dependencies to generate better code suggestions. It does this by analyzing key project configuration files such as `Gemfile.lock`, `package.json`, and `go.mod` to build additional context. diff --git a/gems/click_house-client/lib/click_house/client/formatter.rb b/gems/click_house-client/lib/click_house/client/formatter.rb index a19c55e3e3d..501afe7689c 100644 --- a/gems/click_house-client/lib/click_house/client/formatter.rb +++ b/gems/click_house-client/lib/click_house/client/formatter.rb @@ -5,13 +5,18 @@ module ClickHouse class Formatter DEFAULT = ->(value) { value } - TYPE_CASTERS = { + BASIC_TYPE_CASTERS = { 'UInt64' => ->(value) { Integer(value) }, "DateTime64(6, 'UTC')" => ->(value) { ActiveSupport::TimeZone['UTC'].parse(value) }, "IntervalSecond" => ->(value) { ActiveSupport::Duration.build(value.to_i) }, "IntervalMillisecond" => ->(value) { ActiveSupport::Duration.build(value.to_i / 1000.0) } }.freeze + TYPE_CASTERS = BASIC_TYPE_CASTERS.merge( + BASIC_TYPE_CASTERS.transform_keys { |type| "Nullable(#{type})" } + .transform_values { |caster| ->(value) { value.nil? ? nil : caster.call(value) } } + ) + def self.format(result) name_type_mapping = result['meta'].each_with_object({}) do |column, hash| hash[column['name']] = column['type'] diff --git a/gems/click_house-client/spec/click_house/client/formatter_spec.rb b/gems/click_house-client/spec/click_house/client/formatter_spec.rb index ca57187b098..2389eba5bfa 100644 --- a/gems/click_house-client/spec/click_house/client/formatter_spec.rb +++ b/gems/click_house-client/spec/click_house/client/formatter_spec.rb @@ -7,6 +7,8 @@ RSpec.describe ClickHouse::Client::Formatter do # this query here is just for documentation purposes, it generates the response below _query = <<~SQL.squish SELECT toUInt64(1) as uint64, + toNullable(toUInt64(2)) as nullable_uint64, + CAST(NULL AS Nullable(UInt64)) as nullable_uint64_null, toDateTime64('2016-06-15 23:00:00', 6, 'UTC') as datetime64_6, INTERVAL 1 second as interval_second, INTERVAL 1 millisecond as interval_millisecond @@ -21,6 +23,14 @@ RSpec.describe ClickHouse::Client::Formatter do "type": "UInt64" }, { + "name": "nullable_uint64", + "type": "Nullable(UInt64)" + }, + { + "name": "nullable_uint64_null", + "type": "Nullable(UInt64)" + }, + { "name": "datetime64_6", "type": "DateTime64(6, 'UTC')" }, @@ -29,8 +39,8 @@ RSpec.describe ClickHouse::Client::Formatter do "type": "IntervalSecond" }, { - "name": "interval_millisecond", - "type": "IntervalMillisecond" + "name": "interval_millisecond", + "type": "IntervalMillisecond" } ], @@ -38,6 +48,8 @@ RSpec.describe ClickHouse::Client::Formatter do [ { "uint64": "1", + "nullable_uint64": "2", + "nullable_uint64_null": null, "datetime64_6": "2016-06-15 23:00:00.000000", "interval_second": "1", "interval_millisecond": "1" @@ -48,7 +60,7 @@ RSpec.describe ClickHouse::Client::Formatter do "statistics": { - "elapsed": 0.002101, + "elapsed": 0.00168, "rows_read": 1, "bytes_read": 1 } @@ -61,6 +73,8 @@ RSpec.describe ClickHouse::Client::Formatter do expect(formatted_response).to( eq( [{ "uint64" => 1, + "nullable_uint64" => 2, + "nullable_uint64_null" => nil, "datetime64_6" => ActiveSupport::TimeZone["UTC"].parse("2016-06-15 23:00:00"), "interval_second" => 1.second, "interval_millisecond" => 0.001.seconds }] diff --git a/lib/gitlab/bitbucket_server_import/importers/pull_request_importer.rb b/lib/gitlab/bitbucket_server_import/importers/pull_request_importer.rb index 99f4adbe317..8fd602c851c 100644 --- a/lib/gitlab/bitbucket_server_import/importers/pull_request_importer.rb +++ b/lib/gitlab/bitbucket_server_import/importers/pull_request_importer.rb @@ -10,7 +10,7 @@ module Gitlab @project = project @formatter = Gitlab::ImportFormatter.new @user_finder = UserFinder.new(project) - @mentions_converter = Gitlab::BitbucketServerImport::MentionsConverter.new(project.id) + @mentions_converter = Gitlab::Import::MentionsConverter.new('bitbucket_server', project.id) # Object should behave as a object so we can remove object.is_a?(Hash) check # This will be fixed in https://gitlab.com/gitlab-org/gitlab/-/issues/412328 diff --git a/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer.rb b/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer.rb index 19e5cdcbdc2..4b7c5568dd6 100644 --- a/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer.rb +++ b/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer.rb @@ -11,7 +11,7 @@ module Gitlab @project = project @user_finder = UserFinder.new(project) @formatter = Gitlab::ImportFormatter.new - @mentions_converter = Gitlab::BitbucketServerImport::MentionsConverter.new(project.id) + @mentions_converter = Gitlab::Import::MentionsConverter.new('bitbucket_server', project.id) @object = hash.with_indifferent_access end diff --git a/lib/gitlab/bitbucket_server_import/importers/users_importer.rb b/lib/gitlab/bitbucket_server_import/importers/users_importer.rb index 156d89c2732..8b0b059b397 100644 --- a/lib/gitlab/bitbucket_server_import/importers/users_importer.rb +++ b/lib/gitlab/bitbucket_server_import/importers/users_importer.rb @@ -5,7 +5,7 @@ module Gitlab module Importers class UsersImporter include Loggable - include UserFromMention + include Gitlab::Import::UserFromMention BATCH_SIZE = 100 @@ -46,7 +46,7 @@ module Gitlab def cache_users(users) users_hash = users.each_with_object({}) do |user, hash| - cache_key = source_user_cache_key(project_id, user.username) + cache_key = source_user_cache_key('bitbucket_server', project_id, user.username) hash[cache_key] = user.email end diff --git a/lib/gitlab/checks/lfs_check.rb b/lib/gitlab/checks/lfs_check.rb index 1d1d24c8fcc..f2c4b28470d 100644 --- a/lib/gitlab/checks/lfs_check.rb +++ b/lib/gitlab/checks/lfs_check.rb @@ -7,10 +7,6 @@ module Gitlab ERROR_MESSAGE = 'LFS objects are missing. Ensure LFS is properly set up or try a manual "git lfs push --all".' def validate! - # This feature flag is used for disabling integrity check on some envs - # because these costy calculations may cause performance issues - return unless Feature.enabled?(:lfs_check, project) - return unless project.lfs_enabled? logger.log_timed(LOG_MESSAGE) do diff --git a/lib/gitlab/bitbucket_server_import/mentions_converter.rb b/lib/gitlab/import/mentions_converter.rb index 8b1eeb6e007..180a9f069e3 100644 --- a/lib/gitlab/bitbucket_server_import/mentions_converter.rb +++ b/lib/gitlab/import/mentions_converter.rb @@ -1,16 +1,17 @@ # frozen_string_literal: true module Gitlab - module BitbucketServerImport + module Import class MentionsConverter include UserFromMention MENTIONS_REGEX = User.reference_pattern MENTION_PLACEHOLDER = '~GITLAB_MENTION_PLACEHOLDER~' - attr_reader :project_id + attr_reader :importer, :project_id - def initialize(project_id) + def initialize(importer, project_id) + @importer = importer @project_id = project_id end diff --git a/lib/gitlab/bitbucket_server_import/user_from_mention.rb b/lib/gitlab/import/user_from_mention.rb index 907db245760..9e3489f91b4 100644 --- a/lib/gitlab/bitbucket_server_import/user_from_mention.rb +++ b/lib/gitlab/import/user_from_mention.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true module Gitlab - module BitbucketServerImport + module Import module UserFromMention - SOURCE_USER_CACHE_KEY = 'bitbucket_server/project/%s/source/username/%s' + SOURCE_USER_CACHE_KEY = '%s/project/%s/source/username/%s' def user_from_cache(mention) cached_email = read(mention) @@ -17,14 +17,14 @@ module Gitlab ::Gitlab::Cache::Import::Caching.write_multiple(hash, timeout: timeout) end - def source_user_cache_key(project_id, username) - format(SOURCE_USER_CACHE_KEY, project_id, username) + def source_user_cache_key(importer, project_id, username) + format(SOURCE_USER_CACHE_KEY, importer, project_id, username) end private def read(mention) - ::Gitlab::Cache::Import::Caching.read(source_user_cache_key(project_id, mention)) + ::Gitlab::Cache::Import::Caching.read(source_user_cache_key(importer, project_id, mention)) end def find_user(email) diff --git a/lib/gitlab/observability.rb b/lib/gitlab/observability.rb index d42d10cd0f4..9dd6632aeeb 100644 --- a/lib/gitlab/observability.rb +++ b/lib/gitlab/observability.rb @@ -25,8 +25,8 @@ module Gitlab def should_enable_observability_auth_scopes?(resource) # Enable the needed oauth scopes if tracing is enabled. if resource.is_a?(Group) || resource.is_a?(Project) - return Feature.enabled?(:observability_tracing, - resource.root_ancestor) + return Feature.enabled?(:observability_tracing, resource.root_ancestor) || + Feature.enabled?(:observability_metrics, resource.root_ancestor) end false diff --git a/lib/google_cloud_platform/artifact_registry/client.rb b/lib/google_cloud_platform/artifact_registry/client.rb new file mode 100644 index 00000000000..f371a3ce9c7 --- /dev/null +++ b/lib/google_cloud_platform/artifact_registry/client.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module GoogleCloudPlatform + module ArtifactRegistry + class Client < GoogleCloudPlatform::BaseClient + PAGE_SIZE = 10 + + def initialize(project:, user:, gcp_project_id:, gcp_location:, gcp_repository:, gcp_wlif:) + super(project: project, user: user) + @gcp_project_id = gcp_project_id + @gcp_location = gcp_location + @gcp_repository = gcp_repository + @gcp_wlif = gcp_wlif + end + + def list_docker_images(page_token: nil) + url = list_docker_images_url + response = ::Gitlab::HTTP.get( + url, + headers: headers, + query: query_params(page_token: page_token), + format: :plain, # disable httparty json parsing + extra_allowed_uris: [URI(GLGO_BASE_URL)] + ) + + if response.success? + ::Gitlab::Json.parse(response.body, symbolize_keys: true) + else + {} + end + end + + private + + def list_docker_images_url + "#{GLGO_BASE_URL}/gcp/ar/" \ + "projects/#{@gcp_project_id}/" \ + "locations/#{@gcp_location}/" \ + "repositories/#{@gcp_repository}/docker" + end + + def query_params(page_token: nil) + { + page_token: page_token, + page_size: PAGE_SIZE + }.compact + end + + def headers + jwt = encoded_jwt(wlif: @gcp_wlif) + { + 'Authorization' => "Bearer #{jwt}" + } + end + end + end +end diff --git a/lib/google_cloud_platform/base_client.rb b/lib/google_cloud_platform/base_client.rb new file mode 100644 index 00000000000..a1a13e1e0e9 --- /dev/null +++ b/lib/google_cloud_platform/base_client.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module GoogleCloudPlatform + class BaseClient + GLGO_BASE_URL = if Gitlab.staging? + 'https://glgo.staging.runway.gitlab.net' + else + 'https://glgo.runway.gitlab.net' + end + + def initialize(project:, user:) + @project = project + @user = user + end + + private + + def encoded_jwt(wlif:) + jwt = ::GoogleCloudPlatform::Jwt.new( + project: @project, + user: @user, + claims: { + audience: GLGO_BASE_URL, + wlif: wlif + } + ) + jwt.encoded + end + end +end diff --git a/lib/google_cloud_platform/jwt.rb b/lib/google_cloud_platform/jwt.rb new file mode 100644 index 00000000000..128dd5ae6f1 --- /dev/null +++ b/lib/google_cloud_platform/jwt.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +module GoogleCloudPlatform + class Jwt < ::JSONWebToken::RSAToken + extend ::Gitlab::Utils::Override + + JWT_OPTIONS_ERROR = 'This jwt needs jwt claims audience and wlif to be set.' + + NoSigningKeyError = Class.new(StandardError) + + def initialize(project:, user:, claims:) + super + + raise ArgumentError, JWT_OPTIONS_ERROR if claims[:audience].blank? || claims[:wlif].blank? + + @claims = claims + @project = project + @user = user + end + + def encoded + @custom_payload.merge!(custom_claims) + + super + end + + private + + override :subject + def subject + "project_#{@project.id}_user_#{@user.id}" + end + + override :key_data + def key_data + @key_data ||= begin + # TODO Feels strange to use the CI signing key but do + # we have a different signing key? + key_data = Gitlab::CurrentSettings.ci_jwt_signing_key + + raise NoSigningKeyError unless key_data + + key_data + end + end + + def custom_claims + { + namespace_id: namespace.id.to_s, + namespace_path: namespace.full_path, + root_namespace_path: root_namespace.full_path, + root_namespace_id: root_namespace.id.to_s, + project_id: @project.id.to_s, + project_path: @project.full_path, + user_id: @user&.id.to_s, + user_login: @user&.username, + user_email: @user&.email, + wlif: @claims[:wlif] + } + end + + def namespace + @project.namespace + end + + def root_namespace + @project.root_namespace + end + + override :issuer + def issuer + Feature.enabled?(:oidc_issuer_url) ? Gitlab.config.gitlab.url : Settings.gitlab.base_url + end + + override :audience + def audience + @claims[:audience] + end + + override :kid + def kid + rsa_key = OpenSSL::PKey::RSA.new(key_data) + rsa_key.public_key.to_jwk[:kid] + end + end +end diff --git a/lib/integrations/google_cloud_platform/artifact_registry/client.rb b/lib/integrations/google_cloud_platform/artifact_registry/client.rb deleted file mode 100644 index 32e09821814..00000000000 --- a/lib/integrations/google_cloud_platform/artifact_registry/client.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true - -module Integrations - module GoogleCloudPlatform - module ArtifactRegistry - class Client < Integrations::GoogleCloudPlatform::BaseClient - PAGE_SIZE = 10 - - def initialize(project:, user:, gcp_project_id:, gcp_location:, gcp_repository:, gcp_wlif:) - super(project: project, user: user) - @gcp_project_id = gcp_project_id - @gcp_location = gcp_location - @gcp_repository = gcp_repository - @gcp_wlif = gcp_wlif - end - - def list_docker_images(page_token: nil) - url = list_docker_images_url - response = ::Gitlab::HTTP.get( - url, - headers: headers, - query: query_params(page_token: page_token), - format: :plain, # disable httparty json parsing - extra_allowed_uris: [URI(GLGO_BASE_URL)] - ) - - if response.success? - ::Gitlab::Json.parse(response.body, symbolize_keys: true) - else - {} - end - end - - private - - def list_docker_images_url - "#{GLGO_BASE_URL}/gcp/ar/" \ - "projects/#{@gcp_project_id}/" \ - "locations/#{@gcp_location}/" \ - "repositories/#{@gcp_repository}/docker" - end - - def query_params(page_token: nil) - { - page_token: page_token, - page_size: PAGE_SIZE - }.compact - end - - def headers - jwt = encoded_jwt(wlif: @gcp_wlif) - { - 'Authorization' => "Bearer #{jwt}" - } - end - end - end - end -end diff --git a/lib/integrations/google_cloud_platform/base_client.rb b/lib/integrations/google_cloud_platform/base_client.rb deleted file mode 100644 index 937454cda43..00000000000 --- a/lib/integrations/google_cloud_platform/base_client.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -module Integrations - module GoogleCloudPlatform - class BaseClient - GLGO_BASE_URL = if Gitlab.staging? - 'https://glgo.staging.runway.gitlab.net' - else - 'https://glgo.runway.gitlab.net' - end - - def initialize(project:, user:) - @project = project - @user = user - end - - private - - def encoded_jwt(wlif:) - jwt = ::Integrations::GoogleCloudPlatform::Jwt.new( - project: @project, - user: @user, - claims: { - audience: GLGO_BASE_URL, - wlif: wlif - } - ) - jwt.encoded - end - end - end -end diff --git a/lib/integrations/google_cloud_platform/jwt.rb b/lib/integrations/google_cloud_platform/jwt.rb deleted file mode 100644 index 26343a3a9db..00000000000 --- a/lib/integrations/google_cloud_platform/jwt.rb +++ /dev/null @@ -1,88 +0,0 @@ -# frozen_string_literal: true - -module Integrations - module GoogleCloudPlatform - class Jwt < ::JSONWebToken::RSAToken - extend ::Gitlab::Utils::Override - - JWT_OPTIONS_ERROR = 'This jwt needs jwt claims audience and wlif to be set.' - - NoSigningKeyError = Class.new(StandardError) - - def initialize(project:, user:, claims:) - super - - raise ArgumentError, JWT_OPTIONS_ERROR if claims[:audience].blank? || claims[:wlif].blank? - - @claims = claims - @project = project - @user = user - end - - def encoded - @custom_payload.merge!(custom_claims) - - super - end - - private - - override :subject - def subject - "project_#{@project.id}_user_#{@user.id}" - end - - override :key_data - def key_data - @key_data ||= begin - # TODO Feels strange to use the CI signing key but do - # we have a different signing key? - key_data = Gitlab::CurrentSettings.ci_jwt_signing_key - - raise NoSigningKeyError unless key_data - - key_data - end - end - - def custom_claims - { - namespace_id: namespace.id.to_s, - namespace_path: namespace.full_path, - root_namespace_path: root_namespace.full_path, - root_namespace_id: root_namespace.id.to_s, - project_id: @project.id.to_s, - project_path: @project.full_path, - user_id: @user&.id.to_s, - user_login: @user&.username, - user_email: @user&.email, - wlif: @claims[:wlif] - } - end - - def namespace - @project.namespace - end - - def root_namespace - @project.root_namespace - end - - override :issuer - def issuer - Feature.enabled?(:oidc_issuer_url) ? Gitlab.config.gitlab.url : Settings.gitlab.base_url - end - - override :audience - def audience - @claims[:audience] - end - - override :kid - def kid - rsa_key = OpenSSL::PKey::RSA.new(key_data) - rsa_key.public_key.to_jwk[:kid] - end - end - end -end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 608b930f5c9..3090451b2ec 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -19579,6 +19579,9 @@ msgstr "" msgid "Error fetching the dependency list. Please check your network connection and try again." msgstr "" +msgid "Error fetching the dependency list: %{errorDetails}" +msgstr "" + msgid "Error loading branch data. Please try again." msgstr "" @@ -33913,9 +33916,6 @@ msgstr "" msgid "Only SSH" msgstr "" -msgid "Only SSH Certificates" -msgstr "" - msgid "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user." msgstr "" @@ -56952,6 +56952,9 @@ msgstr "" msgid "Your GitHub access token does not have the correct scope to import collaborators." msgstr "" +msgid "Your GitHub access token does not have the correct scope to import." +msgstr "" + msgid "Your GitLab account has been locked due to an excessive number of unsuccessful sign in attempts. You can wait for your account to automatically unlock in %{duration} or you can click the link below to unlock now." msgstr "" diff --git a/qa/qa/fixtures/files/one_b b/qa/qa/fixtures/files/one_b Binary files differdeleted file mode 100644 index ddd224c7520..00000000000 --- a/qa/qa/fixtures/files/one_b +++ /dev/null diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb index c7ad909e6de..27c5f59f381 100644 --- a/qa/qa/page/main/login.rb +++ b/qa/qa/page/main/login.rb @@ -44,7 +44,6 @@ module QA element 'github-login-button' element 'oidc-login-button' element 'gitlab-oauth-login-button' - element 'facebook-login-button' end view 'app/views/layouts/devise.html.haml' do @@ -184,11 +183,6 @@ module QA click_element 'github-login-button' end - def sign_in_with_facebook - set_initial_password_if_present - click_element 'facebook-login-button' - end - def sign_in_with_saml set_initial_password_if_present click_element 'saml-login-button' diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb index c62df7a8cde..cbd1c91a758 100644 --- a/qa/qa/runtime/env.rb +++ b/qa/qa/runtime/env.rb @@ -286,14 +286,6 @@ module QA ENV['QA_GITHUB_PASSWORD'] end - def facebook_username - ENV['QA_FACEBOOK_USERNAME'] - end - - def facebook_password - ENV['QA_FACEBOOK_PASSWORD'] - end - def forker? !!(forker_username && forker_password) end diff --git a/qa/qa/specs/features/browser_ui/10_govern/login/oauth_login_with_facebook_spec.rb b/qa/qa/specs/features/browser_ui/10_govern/login/oauth_login_with_facebook_spec.rb deleted file mode 100644 index 717c5d6d935..00000000000 --- a/qa/qa/specs/features/browser_ui/10_govern/login/oauth_login_with_facebook_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -module QA - RSpec.describe 'Govern', :orchestrated, :oauth, product_group: :authentication do - describe 'OAuth' do - it 'logs in with Facebook credentials', - testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/417115', - quarantine: { - type: :waiting_on, - issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/431392' - } do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - - Page::Main::Login.perform(&:sign_in_with_facebook) - - Vendor::Facebook::Page::Login.perform(&:login) - - expect(page).to have_content('Welcome to GitLab') - end - end - end -end diff --git a/qa/qa/vendor/facebook/page/login.rb b/qa/qa/vendor/facebook/page/login.rb deleted file mode 100644 index 99e79d2e5a4..00000000000 --- a/qa/qa/vendor/facebook/page/login.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module QA - module Vendor - module Facebook - module Page - class Login < Vendor::Page::Base - def login - fill_in 'email', with: QA::Runtime::Env.facebook_username - fill_in 'pass', with: QA::Runtime::Env.facebook_password - find('#loginbutton').click - - confirm_oauth_access - end - - def confirm_oauth_access - first('span', text: 'Continue as').click if has_css?('span', text: 'Continue as') - end - end - end - end - end -end diff --git a/spec/frontend/authentication/password/components/password_input_spec.js b/spec/frontend/authentication/password/components/password_input_spec.js index 62438e824cf..d31bfea224a 100644 --- a/spec/frontend/authentication/password/components/password_input_spec.js +++ b/spec/frontend/authentication/password/components/password_input_spec.js @@ -32,7 +32,6 @@ describe('PasswordInput', () => { expect(findPasswordInput().attributes('autocomplete')).toBe(propsData.autocomplete); expect(findPasswordInput().attributes('name')).toBe(propsData.name); expect(findPasswordInput().attributes('minlength')).toBe(propsData.minimumPasswordLength); - expect(findPasswordInput().attributes('data-qa-selector')).toBe(propsData.qaSelector); expect(findPasswordInput().attributes('data-testid')).toBe(propsData.testid); expect(findPasswordInput().attributes('title')).toBe(propsData.title); }); diff --git a/spec/frontend/members/components/table/members_table_spec.js b/spec/frontend/members/components/table/members_table_spec.js index c2400fbc142..9fcf1853ef5 100644 --- a/spec/frontend/members/components/table/members_table_spec.js +++ b/spec/frontend/members/components/table/members_table_spec.js @@ -45,8 +45,7 @@ describe('MembersTable', () => { members: [], tableFields: [], tableAttrs: { - table: { 'data-qa-selector': 'members_list' }, - tr: { 'data-qa-selector': 'member_row' }, + tr: { 'data-testid': 'member-row' }, }, pagination, ...state, @@ -274,16 +273,10 @@ describe('MembersTable', () => { }); }); - it('adds QA selector to table', () => { + it('adds QA testid to table row', () => { createComponent(); - expect(findTable().attributes('data-qa-selector')).toBe('members_list'); - }); - - it('adds QA selector to table row', () => { - createComponent(); - - expect(findTable().find('tbody tr').attributes('data-qa-selector')).toBe('member_row'); + expect(findTable().find('tbody tr').attributes('data-testid')).toBe('member-row'); }); describe('when required pagination data is provided', () => { diff --git a/spec/frontend/members/index_spec.js b/spec/frontend/members/index_spec.js index b1730cf3746..a48ed944292 100644 --- a/spec/frontend/members/index_spec.js +++ b/spec/frontend/members/index_spec.js @@ -13,7 +13,7 @@ describe('initMembersApp', () => { vm = initMembersApp(el, { [MEMBER_TYPES.user]: { tableFields: ['account'], - tableAttrs: { table: { 'data-qa-selector': 'members_list' } }, + tableAttrs: { table: { 'data-testid': 'members-list' } }, tableSortableFields: ['account'], requestFormatter: () => ({}), filteredSearchBar: { show: false }, @@ -61,7 +61,7 @@ describe('initMembersApp', () => { setup(); expect(vm.$store.state[MEMBER_TYPES.user].tableAttrs).toEqual({ - table: { 'data-qa-selector': 'members_list' }, + table: { 'data-testid': 'members-list' }, }); }); diff --git a/spec/frontend/work_items/components/work_item_assignees_spec.js b/spec/frontend/work_items/components/work_item_assignees_spec.js index 6c0042bdad7..b34eed21c60 100644 --- a/spec/frontend/work_items/components/work_item_assignees_spec.js +++ b/spec/frontend/work_items/components/work_item_assignees_spec.js @@ -14,9 +14,9 @@ import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutati import WorkItemAssignees from '~/work_items/components/work_item_assignees.vue'; import { i18n, - TASK_TYPE_NAME, - TRACKING_CATEGORY_SHOW, DEFAULT_PAGE_SIZE_ASSIGNEES, + TRACKING_CATEGORY_SHOW, + WORK_ITEM_TYPE_VALUE_TASK, } from '~/work_items/constants'; import { projectMembersResponseWithCurrentUser, @@ -97,7 +97,7 @@ describe('WorkItemAssignees component', () => { fullPath: 'test-project-path', workItemId, allowsMultipleAssignees, - workItemType: TASK_TYPE_NAME, + workItemType: WORK_ITEM_TYPE_VALUE_TASK, canUpdate, canInviteMembers, }, diff --git a/spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js index 36af0c5b3c8..3c65a29e438 100644 --- a/spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js +++ b/spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js @@ -13,8 +13,8 @@ import WorkItemTreeChildren from '~/work_items/components/work_item_links/work_i import WorkItemLinkChildContents from '~/work_items/components/shared/work_item_link_child_contents.vue'; import { WIDGET_TYPE_HIERARCHY, - TASK_TYPE_NAME, WORK_ITEM_TYPE_VALUE_OBJECTIVE, + WORK_ITEM_TYPE_VALUE_TASK, } from '~/work_items/constants'; import { @@ -47,7 +47,7 @@ describe('WorkItemLinkChild', () => { canUpdate = true, issuableGid = WORK_ITEM_ID, childItem = workItemTask, - workItemType = TASK_TYPE_NAME, + workItemType = WORK_ITEM_TYPE_VALUE_TASK, apolloProvider = null, } = {}) => { getWorkItemTreeQueryHandler = jest.fn().mockResolvedValue(workItemHierarchyTreeResponse); diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb index 807898884a1..6c4595ce4bb 100644 --- a/spec/helpers/groups_helper_spec.rb +++ b/spec/helpers/groups_helper_spec.rb @@ -533,24 +533,22 @@ RSpec.describe GroupsHelper, feature_category: :groups_and_projects do end describe "#enabled_git_access_protocol_options_for_group" do - let_it_be(:group) { create(:group) } - - subject { helper.enabled_git_access_protocol_options_for_group(group) } + subject { helper.enabled_git_access_protocol_options_for_group } before do - allow(::Gitlab::CurrentSettings).to receive(:enabled_git_access_protocol).and_return(instance_setting) + expect(::Gitlab::CurrentSettings).to receive(:enabled_git_access_protocol).and_return(instance_setting) end context "instance setting is nil" do let(:instance_setting) { nil } - it { is_expected.to include([_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]) } + it { is_expected.to contain_exactly([_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]) } end context "instance setting is blank" do - let(:instance_setting) { '' } + let(:instance_setting) { nil } - it { is_expected.to include([_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]) } + it { is_expected.to contain_exactly([_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]) } end context "instance setting is ssh" do diff --git a/spec/helpers/work_items_helper_spec.rb b/spec/helpers/work_items_helper_spec.rb index b790f21d412..59b8b13aea2 100644 --- a/spec/helpers/work_items_helper_spec.rb +++ b/spec/helpers/work_items_helper_spec.rb @@ -3,13 +3,13 @@ require "spec_helper" RSpec.describe WorkItemsHelper, feature_category: :team_planning do - describe '#work_items_index_data' do - subject(:work_items_index_data) { helper.work_items_index_data(project) } + describe '#work_items_show_data' do + subject(:work_items_show_data) { helper.work_items_show_data(project) } let_it_be(:project) { build(:project) } it 'returns the expected data properties' do - expect(work_items_index_data).to include( + expect(work_items_show_data).to include( { full_path: project.full_path, issues_list_path: project_issues_path(project), diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index fd51ebbc8fa..3c87ac258b3 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -75,10 +75,12 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate expect(subject.optional_scopes).to match_array %i[read_user read_api read_repository write_repository read_registry read_service_ping write_registry sudo admin_mode openid profile email read_observability write_observability create_runner k8s_proxy ai_features] end - context 'with observability_tracing feature flag' do - context 'when disabled' do + context 'with observability feature flags' do + feature_flags = [:observability_tracing, :observability_metrics] + + context 'when all disabled' do before do - stub_feature_flags(observability_tracing: false) + stub_feature_flags(feature_flags.index_with { false }) end it 'contains for group all resource bot scopes without observability scopes' do @@ -99,49 +101,55 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate end end - context 'when enabled for specific root group' do - let(:parent) { build_stubbed(:group) } - let(:group) do - build_stubbed(:group, parent: parent).tap { |g| g.namespace_settings = build_stubbed(:namespace_settings, namespace: g) } - end + flag_states = [true, false].repeated_permutation(feature_flags.length) + flag_tests = flag_states.filter(&:any?).map { |flags| Hash[feature_flags.zip(flags)] } - let(:project) { build_stubbed(:project, namespace: group) } + flag_tests.each do |flags| + context "with flags #{flags} enabled for specific root group" do + let(:parent) { build_stubbed(:group) } + let(:group) do + build_stubbed(:group, parent: parent).tap { |g| g.namespace_settings = build_stubbed(:namespace_settings, namespace: g) } + end - before do - stub_feature_flags(observability_tracing: parent) - end + let(:project) { build_stubbed(:project, namespace: group) } - it 'contains for group all resource bot scopes including observability scopes' do - expect(subject.available_scopes_for(group)).to match_array %i[api read_api read_repository write_repository read_registry write_registry read_observability write_observability create_runner k8s_proxy ai_features] - end + before do + flags.transform_values! { |v| v ? parent : false } + stub_feature_flags(flags) + end - it 'contains for admin user all non-default scopes with ADMIN access and without observability scopes' do - user = build_stubbed(:user, admin: true) + it 'contains for group all resource bot scopes including observability scopes' do + expect(subject.available_scopes_for(group)).to match_array %i[api read_api read_repository write_repository read_registry write_registry read_observability write_observability create_runner k8s_proxy ai_features] + end - expect(subject.available_scopes_for(user)).to match_array %i[api read_user read_api read_repository write_repository read_registry write_registry read_service_ping sudo admin_mode create_runner k8s_proxy ai_features] - end + it 'contains for admin user all non-default scopes with ADMIN access and without observability scopes' do + user = build_stubbed(:user, admin: true) - it 'contains for project all resource bot scopes including observability scopes' do - expect(subject.available_scopes_for(project)).to match_array %i[api read_api read_repository write_repository read_registry write_registry read_observability write_observability create_runner k8s_proxy ai_features] - end + expect(subject.available_scopes_for(user)).to match_array %i[api read_user read_api read_repository write_repository read_registry write_registry read_service_ping sudo admin_mode create_runner k8s_proxy ai_features] + end - it 'contains for other group all resource bot scopes without observability scopes' do - other_parent = build_stubbed(:group) - other_group = build_stubbed(:group, parent: other_parent).tap do |g| - g.namespace_settings = build_stubbed(:namespace_settings, namespace: g) + it 'contains for project all resource bot scopes including observability scopes' do + expect(subject.available_scopes_for(project)).to match_array %i[api read_api read_repository write_repository read_registry write_registry read_observability write_observability create_runner k8s_proxy ai_features] end - expect(subject.available_scopes_for(other_group)).to match_array %i[api read_api read_repository write_repository read_registry write_registry create_runner k8s_proxy ai_features] - end + it 'contains for other group all resource bot scopes without observability scopes' do + other_parent = build_stubbed(:group) + other_group = build_stubbed(:group, parent: other_parent).tap do |g| + g.namespace_settings = build_stubbed(:namespace_settings, namespace: g) + end - it 'contains for other project all resource bot scopes without observability scopes' do - other_parent = build_stubbed(:group) - other_group = build_stubbed(:group, parent: other_parent).tap do |g| - g.namespace_settings = build_stubbed(:namespace_settings, namespace: g) + expect(subject.available_scopes_for(other_group)).to match_array %i[api read_api read_repository write_repository read_registry write_registry create_runner k8s_proxy ai_features] end - other_project = build_stubbed(:project, namespace: other_group) - expect(subject.available_scopes_for(other_project)).to match_array %i[api read_api read_repository write_repository read_registry write_registry create_runner k8s_proxy ai_features] + it 'contains for other project all resource bot scopes without observability scopes' do + other_parent = build_stubbed(:group) + other_group = build_stubbed(:group, parent: other_parent).tap do |g| + g.namespace_settings = build_stubbed(:namespace_settings, namespace: g) + end + other_project = build_stubbed(:project, namespace: other_group) + + expect(subject.available_scopes_for(other_project)).to match_array %i[api read_api read_repository write_repository read_registry write_registry create_runner k8s_proxy ai_features] + end end end end diff --git a/spec/lib/gitlab/bitbucket_server_import/importers/pull_request_importer_spec.rb b/spec/lib/gitlab/bitbucket_server_import/importers/pull_request_importer_spec.rb index eeb2f9c8000..bff25fb723f 100644 --- a/spec/lib/gitlab/bitbucket_server_import/importers/pull_request_importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_server_import/importers/pull_request_importer_spec.rb @@ -18,7 +18,8 @@ RSpec.describe Gitlab::BitbucketServerImport::Importers::PullRequestImporter, fe it 'imports the merge request correctly' do expect_next(Gitlab::Import::MergeRequestCreator, project).to receive(:execute).and_call_original expect_next(Gitlab::BitbucketServerImport::UserFinder, project).to receive(:author_id).and_call_original - expect_next(Gitlab::BitbucketServerImport::MentionsConverter, project.id).to receive(:convert).and_call_original + expect_next(Gitlab::Import::MentionsConverter, 'bitbucket_server', + project.id).to receive(:convert).and_call_original expect { importer.execute }.to change { MergeRequest.count }.by(1) @@ -42,7 +43,7 @@ RSpec.describe Gitlab::BitbucketServerImport::Importers::PullRequestImporter, fe end it 'does not convert mentions' do - expect_next(Gitlab::BitbucketServerImport::MentionsConverter, project.id).not_to receive(:convert) + expect_next(Gitlab::Import::MentionsConverter, 'bitbucket_server', project.id).not_to receive(:convert) importer.execute end diff --git a/spec/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer_spec.rb b/spec/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer_spec.rb index 7b662c1a2c7..31035d8844e 100644 --- a/spec/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer_spec.rb @@ -17,7 +17,7 @@ RSpec.describe Gitlab::BitbucketServerImport::Importers::PullRequestNotesImporte let_it_be(:pull_request_data) { Gitlab::Json.parse(fixture_file('importers/bitbucket_server/pull_request.json')) } let_it_be(:pull_request) { BitbucketServer::Representation::PullRequest.new(pull_request_data) } let_it_be(:note_author) { create(:user, username: 'note_author', email: 'note_author@example.org') } - let(:mentions_converter) { Gitlab::BitbucketServerImport::MentionsConverter.new(project) } + let(:mentions_converter) { Gitlab::Import::MentionsConverter.new('bitbucket_server', project) } let!(:pull_request_author) do create(:user, username: 'pull_request_author', email: 'pull_request_author@example.org') @@ -81,7 +81,7 @@ RSpec.describe Gitlab::BitbucketServerImport::Importers::PullRequestNotesImporte end before do - allow(Gitlab::BitbucketServerImport::MentionsConverter).to receive(:new).and_return(mentions_converter) + allow(Gitlab::Import::MentionsConverter).to receive(:new).and_return(mentions_converter) end subject(:importer) { described_class.new(project.reload, pull_request.to_hash) } diff --git a/spec/lib/gitlab/checks/lfs_check_spec.rb b/spec/lib/gitlab/checks/lfs_check_spec.rb index f00915bc1ec..ef27b30475f 100644 --- a/spec/lib/gitlab/checks/lfs_check_spec.rb +++ b/spec/lib/gitlab/checks/lfs_check_spec.rb @@ -31,18 +31,6 @@ RSpec.describe Gitlab::Checks::LfsCheck, feature_category: :source_code_manageme allow(project).to receive(:lfs_enabled?).and_return(true) end - context 'with lfs_check feature disabled' do - before do - stub_feature_flags(lfs_check: false) - end - - it 'skips integrity check' do - expect_any_instance_of(Gitlab::Git::LfsChanges).not_to receive(:new_pointers) - - subject.validate! - end - end - context 'with deletion' do shared_examples 'a skipped integrity check' do it 'skips integrity check' do diff --git a/spec/lib/gitlab/bitbucket_server_import/mentions_converter_spec.rb b/spec/lib/gitlab/import/mentions_converter_spec.rb index 46800c924c9..122d7f227cc 100644 --- a/spec/lib/gitlab/bitbucket_server_import/mentions_converter_spec.rb +++ b/spec/lib/gitlab/import/mentions_converter_spec.rb @@ -2,12 +2,13 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketServerImport::MentionsConverter, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::Import::MentionsConverter, :clean_gitlab_redis_cache, feature_category: :importers do let(:project_id) { 12 } + let(:importer) { 'bitbucket_server' } let(:text) { 'text without @ mentions' } let(:source_user_cache_prefix) { "bitbucket_server/project/#{project_id}/source/username" } - subject(:converted_text) { described_class.new(project_id).convert(text) } + subject(:converted_text) { described_class.new(importer, project_id).convert(text) } describe '#convert' do context 'when the text has no mentions' do diff --git a/spec/lib/gitlab/bitbucket_server_import/user_from_mention_spec.rb b/spec/lib/gitlab/import/user_from_mention_spec.rb index 73f9cde8322..0dcd7f92ee6 100644 --- a/spec/lib/gitlab/bitbucket_server_import/user_from_mention_spec.rb +++ b/spec/lib/gitlab/import/user_from_mention_spec.rb @@ -2,22 +2,24 @@ require 'spec_helper' -RSpec.describe Gitlab::BitbucketServerImport::UserFromMention, :clean_gitlab_redis_cache, feature_category: :importers do +RSpec.describe Gitlab::Import::UserFromMention, :clean_gitlab_redis_cache, feature_category: :importers do let(:project_id) { 11 } let(:username) { '@johndoe' } let(:email) { 'john@gmail.com' } let(:hash) { { key: 'value' } } - let(:cache_key) { "bitbucket_server/project/#{project_id}/source/username/#{username}" } + let(:importer) { 'bitbucket_server' } + let(:cache_key) { "#{importer}/project/#{project_id}/source/username/#{username}" } let(:example) do Class.new do - include Gitlab::BitbucketServerImport::UserFromMention + include Gitlab::Import::UserFromMention - def initialize(project_id) + def initialize(importer, project_id) + @importer = importer @project_id = project_id end - attr_reader :project_id + attr_reader :project_id, :importer def foo(mention) user_from_cache(mention) @@ -29,7 +31,7 @@ RSpec.describe Gitlab::BitbucketServerImport::UserFromMention, :clean_gitlab_red end end - subject(:example_class) { example.new(project_id) } + subject(:example_class) { example.new(importer, project_id) } describe '#user_from_cache' do it 'returns nil if the cache is empty' do diff --git a/spec/lib/gitlab/observability_spec.rb b/spec/lib/gitlab/observability_spec.rb index 7af2daea11c..221923ac12a 100644 --- a/spec/lib/gitlab/observability_spec.rb +++ b/spec/lib/gitlab/observability_spec.rb @@ -56,44 +56,35 @@ RSpec.describe Gitlab::Observability, feature_category: :error_tracking do end end - before do - stub_feature_flags(observability_tracing: parent) - end - - describe 'when resource is group' do - context 'if observability_tracing FF enabled' do - it { is_expected.to be true } - end + feature_flags = [:observability_tracing, :observability_metrics] + flag_states = [true, false].repeated_permutation(feature_flags.length) + flag_tests = flag_states.map { |flags| Hash[feature_flags.zip(flags)] } - context 'if observability_tracing FF disabled' do + flag_tests.each do |flags| + context "with feature flag state #{flags}" do before do - stub_feature_flags(observability_tracing: false) + flags.transform_values! { |v| v ? parent : false } + stub_feature_flags(flags) end - it { is_expected.to be false } - end - end + let(:expected_enabled) { flags.values.any? } - describe 'when resource is project' do - let(:resource) { build_stubbed(:project, namespace: parent) } + describe 'when resource is group' do + it { is_expected.to be expected_enabled } + end - context 'if observability_tracing FF enabled' do - it { is_expected.to be true } - end + describe 'when resource is project' do + let(:resource) { build_stubbed(:project, namespace: parent) } - context 'if observability_tracing FF disabled' do - before do - stub_feature_flags(observability_tracing: false) + it { is_expected.to be expected_enabled } end - it { is_expected.to be false } - end - end + describe 'when resource is not a group or project' do + let(:resource) { build_stubbed(:user) } - describe 'when resource is not a group or project' do - let(:resource) { build_stubbed(:user) } - - it { is_expected.to be false } + it { is_expected.to be false } + end + end end end end diff --git a/spec/lib/gitlab/protocol_access_spec.rb b/spec/lib/gitlab/protocol_access_spec.rb index cae14c3d7cf..e7e81b4b3e1 100644 --- a/spec/lib/gitlab/protocol_access_spec.rb +++ b/spec/lib/gitlab/protocol_access_spec.rb @@ -10,34 +10,25 @@ RSpec.describe Gitlab::ProtocolAccess, feature_category: :source_code_management describe ".allowed?" do where(:protocol, :project, :admin_setting, :namespace_setting, :expected_result) do - "web" | nil | nil | nil | true - "ssh" | nil | nil | nil | true - "http" | nil | nil | nil | true - "ssh_certificates" | nil | nil | nil | true - "ssh" | nil | "" | nil | true - "http" | nil | "" | nil | true - "ssh_certificates" | nil | "" | nil | true - "ssh" | nil | "ssh" | nil | true - "http" | nil | "http" | nil | true - "ssh_certificates" | nil | "ssh_certificates" | nil | true - "ssh" | nil | "http" | nil | false - "http" | nil | "ssh" | nil | false - "ssh_certificates" | nil | "ssh" | nil | false - "ssh" | ref(:p1) | nil | "all" | true - "http" | ref(:p1) | nil | "all" | true - "ssh_certificates" | ref(:p1) | nil | "all" | true - "ssh" | ref(:p1) | nil | "ssh" | true - "http" | ref(:p1) | nil | "http" | true - "ssh_certificates" | ref(:p1) | nil | "ssh_certificates" | true - "ssh" | ref(:p1) | nil | "http" | false - "http" | ref(:p1) | nil | "ssh" | false - "ssh_certificates" | ref(:p1) | nil | "ssh" | false - "ssh" | ref(:p1) | "" | "all" | true - "http" | ref(:p1) | "" | "all" | true - "ssh_certificates" | ref(:p1) | "" | "all" | true - "ssh" | ref(:p1) | "ssh" | "ssh" | true - "http" | ref(:p1) | "http" | "http" | true - "ssh_certificates" | ref(:p1) | "ssh_certificates" | "ssh_certificates" | true + "web" | nil | nil | nil | true + "ssh" | nil | nil | nil | true + "http" | nil | nil | nil | true + "ssh" | nil | "" | nil | true + "http" | nil | "" | nil | true + "ssh" | nil | "ssh" | nil | true + "http" | nil | "http" | nil | true + "ssh" | nil | "http" | nil | false + "http" | nil | "ssh" | nil | false + "ssh" | ref(:p1) | nil | "all" | true + "http" | ref(:p1) | nil | "all" | true + "ssh" | ref(:p1) | nil | "ssh" | true + "http" | ref(:p1) | nil | "http" | true + "ssh" | ref(:p1) | nil | "http" | false + "http" | ref(:p1) | nil | "ssh" | false + "ssh" | ref(:p1) | "" | "all" | true + "http" | ref(:p1) | "" | "all" | true + "ssh" | ref(:p1) | "ssh" | "ssh" | true + "http" | ref(:p1) | "http" | "http" | true end with_them do diff --git a/spec/lib/integrations/google_cloud_platform/artifact_registry/client_spec.rb b/spec/lib/google_cloud_platform/artifact_registry/client_spec.rb index a258518953a..09ddba7c091 100644 --- a/spec/lib/integrations/google_cloud_platform/artifact_registry/client_spec.rb +++ b/spec/lib/google_cloud_platform/artifact_registry/client_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Integrations::GoogleCloudPlatform::ArtifactRegistry::Client, feature_category: :container_registry do +RSpec.describe GoogleCloudPlatform::ArtifactRegistry::Client, feature_category: :container_registry do let_it_be(:project) { create(:project) } let_it_be(:rsa_key) { OpenSSL::PKey::RSA.generate(3072) } let_it_be(:rsa_key_data) { rsa_key.to_s } diff --git a/spec/lib/integrations/google_cloud_platform/jwt_spec.rb b/spec/lib/google_cloud_platform/jwt_spec.rb index 51707c26a3a..d41056a8606 100644 --- a/spec/lib/integrations/google_cloud_platform/jwt_spec.rb +++ b/spec/lib/google_cloud_platform/jwt_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Integrations::GoogleCloudPlatform::Jwt, feature_category: :shared do +RSpec.describe GoogleCloudPlatform::Jwt, feature_category: :shared do let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } diff --git a/spec/models/namespace_setting_spec.rb b/spec/models/namespace_setting_spec.rb index c7449e047b0..07ac3248c0a 100644 --- a/spec/models/namespace_setting_spec.rb +++ b/spec/models/namespace_setting_spec.rb @@ -12,7 +12,7 @@ RSpec.describe NamespaceSetting, feature_category: :groups_and_projects, type: : end it { is_expected.to define_enum_for(:jobs_to_be_done).with_values([:basics, :move_repository, :code_storage, :exploring, :ci, :other]).with_suffix } - it { is_expected.to define_enum_for(:enabled_git_access_protocol).with_suffix } + it { is_expected.to define_enum_for(:enabled_git_access_protocol).with_values([:all, :ssh, :http]).with_suffix } describe 'default values' do subject(:setting) { described_class.new } diff --git a/spec/requests/api/graphql/mutations/notes/create/discussion_spec.rb b/spec/requests/api/graphql/mutations/notes/create/discussion_spec.rb new file mode 100644 index 00000000000..c7ed63c2560 --- /dev/null +++ b/spec/requests/api/graphql/mutations/notes/create/discussion_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Adding an DiscussionNote', feature_category: :code_review_workflow do + include GraphqlHelpers + + let_it_be(:current_user) { create(:user) } + + let(:noteable) { create(:merge_request, source_project: project, target_project: project) } + let(:project) { create(:project, :repository) } + let(:diff_refs) { noteable.diff_refs } + let(:mutation) do + variables = { + noteable_id: GitlabSchema.id_from_object(noteable).to_s, + body: 'Body text' + } + + graphql_mutation(:create_discussion, variables) + end + + def mutation_response + graphql_mutation_response(:create_discussion) + end + + it_behaves_like 'a Note mutation when the user does not have permission' + + context 'when the user has permission' do + before do + project.add_developer(current_user) + end + + it_behaves_like 'a Note mutation that creates a Note' + + it_behaves_like 'a Note mutation when there are active record validation errors', model: DiscussionNote + + it_behaves_like 'a Note mutation when there are rate limit validation errors' + + it 'returns the discussion' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(mutation_response['note']['body']).to eq('Body text') + end + end +end diff --git a/spec/requests/api/graphql/mutations/work_items/create_spec.rb b/spec/requests/api/graphql/mutations/work_items/create_spec.rb index 2c2cd5f2acc..78b93c3210b 100644 --- a/spec/requests/api/graphql/mutations/work_items/create_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/create_spec.rb @@ -281,18 +281,6 @@ RSpec.describe 'Create a work item', feature_category: :team_planning do it_behaves_like 'creates work item' - # This is a temporary measure just to ensure the internal id migration doesn't get conflicts - # More info in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139367 - context 'when making the request in a production environment' do - before do - stub_rails_env('production') - end - - it_behaves_like 'a mutation that returns top-level errors', errors: [ - 'Group level work items are disabled. Only project paths allowed in `namespacePath`.' - ] - end - context 'when the namespace_level_work_items feature flag is disabled' do before do stub_feature_flags(namespace_level_work_items: false) diff --git a/spec/services/google_cloud_platform/artifact_registry/list_docker_images_service_spec.rb b/spec/services/google_cloud_platform/artifact_registry/list_docker_images_service_spec.rb index f19cbaa21cd..d772634e682 100644 --- a/spec/services/google_cloud_platform/artifact_registry/list_docker_images_service_spec.rb +++ b/spec/services/google_cloud_platform/artifact_registry/list_docker_images_service_spec.rb @@ -26,10 +26,10 @@ RSpec.describe GoogleCloudPlatform::ArtifactRegistry::ListDockerImagesService, f describe '#execute' do let(:page_token) { nil } let(:list_docker_images_response) { dummy_list_response } - let(:client_double) { instance_double('::Integrations::GoogleCloudPlatform::ArtifactRegistry::Client') } + let(:client_double) { instance_double('::GoogleCloudPlatform::ArtifactRegistry::Client') } before do - allow(::Integrations::GoogleCloudPlatform::ArtifactRegistry::Client).to receive(:new) + allow(::GoogleCloudPlatform::ArtifactRegistry::Client).to receive(:new) .with( project: project, user: user, diff --git a/spec/services/import/github_service_spec.rb b/spec/services/import/github_service_spec.rb index 6fe17a31f3e..949031b961a 100644 --- a/spec/services/import/github_service_spec.rb +++ b/spec/services/import/github_service_spec.rb @@ -202,7 +202,25 @@ RSpec.describe Import::GithubService, feature_category: :importers do end end - context 'validates scopes when collaborator import is true' do + context 'validates minimum scope when collaborator import is false' do + let(:optional_stages) do + { + collaborators_import: false + } + end + + let(:headers) do + { + 'x-oauth-scopes' => 'write:packages' + } + end + + it 'returns error when scope is not adequate' do + expect(subject.execute(access_params, :github)).to include(minimum_scope_error) + end + end + + context 'validates collaborator scopes when collaborator import is true' do let(:optional_stages) do { collaborators_import: true @@ -211,12 +229,12 @@ RSpec.describe Import::GithubService, feature_category: :importers do let(:headers) do { - 'x-oauth-scopes' => 'read:user' + 'x-oauth-scopes' => 'repo, read:user' } end it 'returns error when scope is not adequate' do - expect(subject.execute(access_params, :github)).to include(scope_error) + expect(subject.execute(access_params, :github)).to include(collab_import_scope_error) end end @@ -355,7 +373,15 @@ RSpec.describe Import::GithubService, feature_category: :importers do } end - def scope_error + def minimum_scope_error + { + status: :error, + http_status: :unprocessable_entity, + message: 'Your GitHub access token does not have the correct scope to import.' + } + end + + def collab_import_scope_error { status: :error, http_status: :unprocessable_entity, diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb index 4067bce8d8d..4918c4e0082 100644 --- a/spec/workers/every_sidekiq_worker_spec.rb +++ b/spec/workers/every_sidekiq_worker_spec.rb @@ -247,21 +247,21 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do 'Geo::VerificationStateBackfillWorker' => false, 'Geo::VerificationTimeoutWorker' => false, 'Geo::VerificationWorker' => 3, - 'Gitlab::BitbucketImport::AdvanceStageWorker' => 3, - 'Gitlab::BitbucketImport::Stage::FinishImportWorker' => 3, - 'Gitlab::BitbucketImport::Stage::ImportIssuesWorker' => 3, - 'Gitlab::BitbucketImport::Stage::ImportIssuesNotesWorker' => 3, - 'Gitlab::BitbucketImport::Stage::ImportLfsObjectsWorker' => 3, - 'Gitlab::BitbucketImport::Stage::ImportPullRequestsWorker' => 3, - 'Gitlab::BitbucketImport::Stage::ImportPullRequestsNotesWorker' => 3, - 'Gitlab::BitbucketImport::Stage::ImportRepositoryWorker' => 3, - 'Gitlab::BitbucketServerImport::AdvanceStageWorker' => 3, - 'Gitlab::BitbucketServerImport::Stage::FinishImportWorker' => 3, - 'Gitlab::BitbucketServerImport::Stage::ImportLfsObjectsWorker' => 3, - 'Gitlab::BitbucketServerImport::Stage::ImportNotesWorker' => 3, - 'Gitlab::BitbucketServerImport::Stage::ImportPullRequestsWorker' => 3, - 'Gitlab::BitbucketServerImport::Stage::ImportRepositoryWorker' => 3, - 'Gitlab::BitbucketServerImport::Stage::ImportUsersWorker' => 3, + 'Gitlab::BitbucketImport::AdvanceStageWorker' => 6, + 'Gitlab::BitbucketImport::Stage::FinishImportWorker' => 6, + 'Gitlab::BitbucketImport::Stage::ImportIssuesWorker' => 6, + 'Gitlab::BitbucketImport::Stage::ImportIssuesNotesWorker' => 6, + 'Gitlab::BitbucketImport::Stage::ImportLfsObjectsWorker' => 6, + 'Gitlab::BitbucketImport::Stage::ImportPullRequestsWorker' => 6, + 'Gitlab::BitbucketImport::Stage::ImportPullRequestsNotesWorker' => 6, + 'Gitlab::BitbucketImport::Stage::ImportRepositoryWorker' => 6, + 'Gitlab::BitbucketServerImport::AdvanceStageWorker' => 6, + 'Gitlab::BitbucketServerImport::Stage::FinishImportWorker' => 6, + 'Gitlab::BitbucketServerImport::Stage::ImportLfsObjectsWorker' => 6, + 'Gitlab::BitbucketServerImport::Stage::ImportNotesWorker' => 6, + 'Gitlab::BitbucketServerImport::Stage::ImportPullRequestsWorker' => 6, + 'Gitlab::BitbucketServerImport::Stage::ImportRepositoryWorker' => 6, + 'Gitlab::BitbucketServerImport::Stage::ImportUsersWorker' => 6, 'Gitlab::GithubImport::AdvanceStageWorker' => 6, 'Gitlab::GithubImport::Attachments::ImportReleaseWorker' => 5, 'Gitlab::GithubImport::Attachments::ImportNoteWorker' => 5, @@ -297,14 +297,14 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do 'Gitlab::GithubGistsImport::ImportGistWorker' => 5, 'Gitlab::GithubGistsImport::StartImportWorker' => 5, 'Gitlab::GithubGistsImport::FinishImportWorker' => 5, - 'Gitlab::JiraImport::AdvanceStageWorker' => 5, + 'Gitlab::JiraImport::AdvanceStageWorker' => 6, 'Gitlab::JiraImport::ImportIssueWorker' => 5, - 'Gitlab::JiraImport::Stage::FinishImportWorker' => 5, - 'Gitlab::JiraImport::Stage::ImportAttachmentsWorker' => 5, - 'Gitlab::JiraImport::Stage::ImportIssuesWorker' => 5, - 'Gitlab::JiraImport::Stage::ImportLabelsWorker' => 5, - 'Gitlab::JiraImport::Stage::ImportNotesWorker' => 5, - 'Gitlab::JiraImport::Stage::StartImportWorker' => 5, + 'Gitlab::JiraImport::Stage::FinishImportWorker' => 6, + 'Gitlab::JiraImport::Stage::ImportAttachmentsWorker' => 6, + 'Gitlab::JiraImport::Stage::ImportIssuesWorker' => 6, + 'Gitlab::JiraImport::Stage::ImportLabelsWorker' => 6, + 'Gitlab::JiraImport::Stage::ImportNotesWorker' => 6, + 'Gitlab::JiraImport::Stage::StartImportWorker' => 6, 'GitlabPerformanceBarStatsWorker' => 3, 'GitlabSubscriptions::RefreshSeatsWorker' => 0, 'GitlabSubscriptions::AddOnPurchases::BulkRefreshUserAssignmentsWorker' => 0, |