Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-02-07 21:09:58 +00:00
parent 6cae2159b8
commit 919e3e3cd8
74 changed files with 254 additions and 181 deletions

View File

@ -1,10 +1,5 @@
<!-- Set the correct label and milestone using autocomplete for guidance. Please @mention only the DRI(s) for each stage or group rather than an entire department. --> <!-- Set the correct label and milestone using autocomplete for guidance. Please @mention only the DRI(s) for each stage or group rather than an entire department. -->
/label ~"release post" ~"release post item" ~"Technical Writing" ~devops:: ~group:: ~"release post item::deprecation"
/label ~"type::maintenance"
/milestone %
/assign `@EM/PM` (choose the DRI; remove backticks here, and below)
**Be sure to link this MR to the relevant deprecation issue(s).** **Be sure to link this MR to the relevant deprecation issue(s).**
- Deprecation Issue: - Deprecation Issue:
@ -42,10 +37,12 @@ They are frequently updated, and everyone should make sure they are aware of the
- [ ] Set yourself as the Assignee, meaning you are the DRI. - [ ] Set yourself as the Assignee, meaning you are the DRI.
- [ ] If the deprecation is a [breaking change](https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-change), add label `breaking change`. - [ ] If the deprecation is a [breaking change](https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-change), add label `breaking change`.
- [ ] Confirm this MR is labeled ~"release post item::deprecation"
- [ ] Follow the process to [create a deprecation YAML file](https://about.gitlab.com/handbook/marketing/blog/release-posts/#creating-a-deprecation-entry). - [ ] Follow the process to [create a deprecation YAML file](https://about.gitlab.com/handbook/marketing/blog/release-posts/#creating-a-deprecation-entry).
- [ ] Make sure that the milestone dates are based on the dates in [Product milestone creation](https://about.gitlab.com/handbook/product/milestones/#product-milestone-creation).
- [ ] Add reviewers by the 10th. - [ ] Add reviewers by the 10th.
- [ ] When ready to be merged and not later than the 15th, add the `~ready` label and @ message the TW for final review and merge. - [ ] Add scoped `devops::` and `group::` labels as necessary.
- [ ] Add the appropriate milestone to this MR.
- [ ] When ready to be merged (and no later than the 15th) `@mention` the TW for final review and merge.
## Reviewers ## Reviewers
@ -106,3 +103,7 @@ must be updated before this MR is merged:
1. Set the MR to merge when the pipeline succeeds (or merge if the pipeline is already complete). 1. Set the MR to merge when the pipeline succeeds (or merge if the pipeline is already complete).
If you have trouble running the Rake task, check the [troubleshooting steps](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecation-rake-task-troubleshooting). If you have trouble running the Rake task, check the [troubleshooting steps](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecation-rake-task-troubleshooting).
/label ~"release post" ~"release post item" ~"Technical Writing" ~"release post item::deprecation"
/label ~"type::maintenance"
/label ~"maintenance::refactor"

View File

@ -1,6 +1,5 @@
--- ---
RSpec/InvalidFeatureCategory: RSpec/InvalidFeatureCategory:
Details: grace period
Exclude: Exclude:
- 'ee/spec/controllers/admin/application_settings_controller_spec.rb' - 'ee/spec/controllers/admin/application_settings_controller_spec.rb'
- 'ee/spec/controllers/admin/applications_controller_spec.rb' - 'ee/spec/controllers/admin/applications_controller_spec.rb'
@ -8,44 +7,16 @@ RSpec/InvalidFeatureCategory:
- 'ee/spec/controllers/admin/emails_controller_spec.rb' - 'ee/spec/controllers/admin/emails_controller_spec.rb'
- 'ee/spec/controllers/countries_controller_spec.rb' - 'ee/spec/controllers/countries_controller_spec.rb'
- 'ee/spec/controllers/country_states_controller_spec.rb' - 'ee/spec/controllers/country_states_controller_spec.rb'
- 'ee/spec/controllers/ee/projects/autocomplete_sources_controller_spec.rb'
- 'ee/spec/controllers/groups/analytics/tasks_by_type_controller_spec.rb'
- 'ee/spec/controllers/sitemap_controller_spec.rb' - 'ee/spec/controllers/sitemap_controller_spec.rb'
- 'ee/spec/features/admin/admin_dashboard_spec.rb' - 'ee/spec/features/admin/admin_dashboard_spec.rb'
- 'ee/spec/features/admin/admin_emails_spec.rb'
- 'ee/spec/features/dashboards/operations_spec.rb' - 'ee/spec/features/dashboards/operations_spec.rb'
- 'ee/spec/features/groups/show_spec.rb'
- 'ee/spec/features/security/project/snippet/internal_access_spec.rb'
- 'ee/spec/features/security/project/snippet/private_access_spec.rb'
- 'ee/spec/features/security/project/snippet/public_access_spec.rb'
- 'ee/spec/features/work_items/okr_spec.rb'
- 'ee/spec/finders/work_items/widgets/filters/requirement_legacy_spec.rb'
- 'ee/spec/graphql/ee/resolvers/work_items_resolver_spec.rb'
- 'ee/spec/graphql/types/pipeline_security_report_finding_type_spec.rb'
- 'ee/spec/helpers/application_helper_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/pipeline/chain/validate/abilities_spec.rb'
- 'ee/spec/lib/gitlab/ci/reports/license_scanning/report_spec.rb'
- 'ee/spec/models/resource_iteration_event_spec.rb'
- 'ee/spec/models/resource_weight_event_spec.rb'
- 'ee/spec/models/work_items/widgets/requirement_legacy_spec.rb'
- 'ee/spec/policies/global_policy_spec.rb'
- 'ee/spec/requests/api/award_emoji_spec.rb' - 'ee/spec/requests/api/award_emoji_spec.rb'
- 'ee/spec/requests/api/settings_spec.rb' - 'ee/spec/requests/api/settings_spec.rb'
- 'ee/spec/requests/ee/groups/autocomplete_sources_spec.rb'
- 'ee/spec/serializers/autocomplete/iteration_entity_spec.rb'
- 'ee/spec/services/ee/groups/autocomplete_service_spec.rb'
- 'ee/spec/services/ee/merge_requests/after_create_service_spec.rb'
- 'ee/spec/services/ee/projects/autocomplete_service_spec.rb'
- 'ee/spec/services/vulnerability_feedback/create_service_spec.rb'
- 'ee/spec/services/work_items/widgets/iteration_service/create_service_spec.rb'
- 'ee/spec/services/work_items/widgets/iteration_service/update_service_spec.rb'
- 'spec/config/inject_enterprise_edition_module_spec.rb' - 'spec/config/inject_enterprise_edition_module_spec.rb'
- 'spec/config/object_store_settings_spec.rb' - 'spec/config/object_store_settings_spec.rb'
- 'spec/config/smime_signature_settings_spec.rb' - 'spec/config/smime_signature_settings_spec.rb'
- 'spec/contracts/provider_specs/helpers/provider/contract_source_helper_spec.rb' - 'spec/contracts/provider_specs/helpers/provider/contract_source_helper_spec.rb'
- 'spec/controllers/concerns/content_security_policy_patch_spec.rb' - 'spec/controllers/concerns/content_security_policy_patch_spec.rb'
- 'spec/controllers/import/github_controller_spec.rb'
- 'spec/controllers/registrations_controller_spec.rb'
- 'spec/features/action_cable_logging_spec.rb' - 'spec/features/action_cable_logging_spec.rb'
- 'spec/features/admin/admin_abuse_reports_spec.rb' - 'spec/features/admin/admin_abuse_reports_spec.rb'
- 'spec/features/admin/admin_appearance_spec.rb' - 'spec/features/admin/admin_appearance_spec.rb'
@ -60,54 +31,23 @@ RSpec/InvalidFeatureCategory:
- 'spec/features/frequently_visited_projects_and_groups_spec.rb' - 'spec/features/frequently_visited_projects_and_groups_spec.rb'
- 'spec/features/help_dropdown_spec.rb' - 'spec/features/help_dropdown_spec.rb'
- 'spec/features/help_pages_spec.rb' - 'spec/features/help_pages_spec.rb'
- 'spec/features/merge_request/user_can_see_draft_toggle_spec.rb'
- 'spec/features/monitor_sidebar_link_spec.rb' - 'spec/features/monitor_sidebar_link_spec.rb'
- 'spec/features/projects/issues/email_participants_spec.rb'
- 'spec/features/projects/snippets/create_snippet_spec.rb'
- 'spec/features/projects/snippets/show_spec.rb'
- 'spec/features/projects/snippets/user_comments_on_snippet_spec.rb'
- 'spec/features/projects/snippets/user_deletes_snippet_spec.rb'
- 'spec/features/projects/snippets/user_updates_snippet_spec.rb'
- 'spec/features/projects/snippets/user_views_snippets_spec.rb'
- 'spec/features/snippets_spec.rb'
- 'spec/features/unsubscribe_links_spec.rb' - 'spec/features/unsubscribe_links_spec.rb'
- 'spec/features/users/snippets_spec.rb'
- 'spec/features/whats_new_spec.rb' - 'spec/features/whats_new_spec.rb'
- 'spec/helpers/issuables_helper_spec.rb'
- 'spec/lib/api/base_spec.rb' - 'spec/lib/api/base_spec.rb'
- 'spec/lib/api/helpers_spec.rb' - 'spec/lib/api/helpers_spec.rb'
- 'spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb'
- 'spec/lib/gitlab/application_context_spec.rb' - 'spec/lib/gitlab/application_context_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/chain/validate/abilities_spec.rb'
- 'spec/lib/gitlab/database/migrations/batched_migration_last_id_spec.rb'
- 'spec/lib/gitlab/error_tracking/context_payload_generator_spec.rb' - 'spec/lib/gitlab/error_tracking/context_payload_generator_spec.rb'
- 'spec/lib/gitlab/error_tracking_spec.rb' - 'spec/lib/gitlab/error_tracking_spec.rb'
- 'spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb'
- 'spec/lib/gitlab/github_import/client_spec.rb'
- 'spec/lib/gitlab/github_import/clients/proxy_spec.rb'
- 'spec/lib/gitlab/graphql/tracers/logger_tracer_spec.rb' - 'spec/lib/gitlab/graphql/tracers/logger_tracer_spec.rb'
- 'spec/lib/gitlab/graphql/tracers/metrics_tracer_spec.rb' - 'spec/lib/gitlab/graphql/tracers/metrics_tracer_spec.rb'
- 'spec/lib/gitlab/import_export/version_checker_spec.rb'
- 'spec/lib/gitlab/metrics/background_transaction_spec.rb' - 'spec/lib/gitlab/metrics/background_transaction_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/worker_context/client_spec.rb' - 'spec/lib/gitlab/sidekiq_middleware/worker_context/client_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/worker_context/server_spec.rb' - 'spec/lib/gitlab/sidekiq_middleware/worker_context/server_spec.rb'
- 'spec/lib/gitlab/slug/path_spec.rb' - 'spec/lib/gitlab/slug/path_spec.rb'
- 'spec/lib/gitlab/utils/strong_memoize_spec.rb' - 'spec/lib/gitlab/utils/strong_memoize_spec.rb'
- 'spec/migrations/20220309084954_remove_leftover_external_pull_request_deletions_spec.rb'
- 'spec/migrations/20220329175119_remove_leftover_ci_job_artifact_deletions_spec.rb'
- 'spec/migrations/20220802204737_remove_deactivated_user_highest_role_stats_spec.rb'
- 'spec/migrations/20221209110934_update_import_sources_on_application_settings_spec.rb'
- 'spec/migrations/20221209110935_fix_update_import_sources_on_application_settings_spec.rb'
- 'spec/models/application_setting_spec.rb' - 'spec/models/application_setting_spec.rb'
- 'spec/models/integrations/apple_app_store_spec.rb'
- 'spec/models/issue_spec.rb'
- 'spec/models/namespaces/randomized_suffix_path_spec.rb' - 'spec/models/namespaces/randomized_suffix_path_spec.rb'
- 'spec/models/resource_event_spec.rb'
- 'spec/models/resource_label_event_spec.rb'
- 'spec/models/resource_milestone_event_spec.rb'
- 'spec/models/resource_state_event_spec.rb'
- 'spec/policies/global_policy_spec.rb'
- 'spec/policies/todo_policy_spec.rb'
- 'spec/requests/admin/version_check_controller_spec.rb' - 'spec/requests/admin/version_check_controller_spec.rb'
- 'spec/requests/api/admin/plan_limits_spec.rb' - 'spec/requests/api/admin/plan_limits_spec.rb'
- 'spec/requests/api/admin/sidekiq_spec.rb' - 'spec/requests/api/admin/sidekiq_spec.rb'
@ -115,16 +55,13 @@ RSpec/InvalidFeatureCategory:
- 'spec/requests/api/api_guard/response_coercer_middleware_spec.rb' - 'spec/requests/api/api_guard/response_coercer_middleware_spec.rb'
- 'spec/requests/api/award_emoji_spec.rb' - 'spec/requests/api/award_emoji_spec.rb'
- 'spec/requests/api/graphql/custom_emoji_query_spec.rb' - 'spec/requests/api/graphql/custom_emoji_query_spec.rb'
- 'spec/requests/api/graphql/gitlab_schema_spec.rb'
- 'spec/requests/api/graphql/multiplexed_queries_spec.rb' - 'spec/requests/api/graphql/multiplexed_queries_spec.rb'
- 'spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb' - 'spec/requests/api/graphql/mutations/admin/sidekiq_queues/delete_jobs_spec.rb'
- 'spec/requests/api/graphql/mutations/award_emojis/add_spec.rb' - 'spec/requests/api/graphql/mutations/award_emojis/add_spec.rb'
- 'spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb' - 'spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb'
- 'spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb' - 'spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb'
- 'spec/requests/api/graphql/mutations/ci/pipeline_schedule_play_spec.rb'
- 'spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb' - 'spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb'
- 'spec/requests/api/graphql/mutations/custom_emoji/destroy_spec.rb' - 'spec/requests/api/graphql/mutations/custom_emoji/destroy_spec.rb'
- 'spec/requests/api/graphql/project/project_statistics_spec.rb'
- 'spec/requests/api/graphql/query_spec.rb' - 'spec/requests/api/graphql/query_spec.rb'
- 'spec/requests/api/graphql_spec.rb' - 'spec/requests/api/graphql_spec.rb'
- 'spec/requests/api/internal/workhorse_spec.rb' - 'spec/requests/api/internal/workhorse_spec.rb'
@ -136,10 +73,3 @@ RSpec/InvalidFeatureCategory:
- 'spec/rubocop/cop/gitlab/doc_url_spec.rb' - 'spec/rubocop/cop/gitlab/doc_url_spec.rb'
- 'spec/rubocop/cop/lint/last_keyword_argument_spec.rb' - 'spec/rubocop/cop/lint/last_keyword_argument_spec.rb'
- 'spec/rubocop/cop/rspec/avoid_test_prof_spec.rb' - 'spec/rubocop/cop/rspec/avoid_test_prof_spec.rb'
- 'spec/services/lfs/file_transformer_spec.rb'
- 'spec/services/notes/create_service_spec.rb'
- 'spec/services/security/ci_configuration/sast_create_service_spec.rb'
- 'spec/services/users/assigned_issues_count_service_spec.rb'
- 'spec/tasks/gitlab/security/update_banned_ssh_keys_rake_spec.rb'
- 'spec/views/layouts/snippets.html.haml_spec.rb'
- 'spec/views/projects/commit/show.html.haml_spec.rb'

View File

@ -199,7 +199,7 @@ export default {
data-testid="pipeline-info-container" data-testid="pipeline-info-container"
data-qa-selector="merge_request_pipeline_info_content" data-qa-selector="merge_request_pipeline_info_content"
> >
{{ pipeline.details.event_type_name || pipeline.details.name }} {{ pipeline.details.event_type_name }}
<gl-link <gl-link
:href="pipeline.path" :href="pipeline.path"
class="pipeline-id" class="pipeline-id"

View File

@ -510,8 +510,6 @@ class ApplicationController < ActionController::Base
end end
def set_locale(&block) def set_locale(&block)
return Gitlab::I18n.with_user_locale(current_user, &block) unless Feature.enabled?(:preferred_language_switcher)
if current_user if current_user
Gitlab::I18n.with_user_locale(current_user, &block) Gitlab::I18n.with_user_locale(current_user, &block)
else else

View File

@ -6,8 +6,6 @@ module PreferredLanguageSwitcher
private private
def init_preferred_language def init_preferred_language
return unless Feature.enabled?(:preferred_language_switcher)
cookies[:preferred_language] = preferred_language cookies[:preferred_language] = preferred_language
end end

View File

@ -93,6 +93,23 @@ class Import::GithubController < Import::BaseController
end end
end end
def cancel_all
projects_to_cancel = Project.imported_from(provider_name).created_by(current_user).is_importing
canceled = projects_to_cancel.map do |project|
# #reset is called to make sure project was not finished/canceled brefore calling service
result = Import::Github::CancelProjectImportService.new(project.reset, current_user).execute
{
id: project.id,
status: result[:status],
error: result[:message]
}.compact
end
render json: canceled
end
protected protected
override :importable_repos override :importable_repos

View File

@ -18,18 +18,23 @@ module Mutations
required: true, required: true,
description: 'Project to be removed from the CI job token scope.' description: 'Project to be removed from the CI job token scope.'
argument :direction,
::Types::Ci::JobTokenScope::DirectionEnum,
required: false,
description: 'Direction of access, which defaults to outbound.'
field :ci_job_token_scope, field :ci_job_token_scope,
Types::Ci::JobTokenScopeType, Types::Ci::JobTokenScopeType,
null: true, null: true,
description: "CI job token's scope of access." description: "CI job token's scope of access."
def resolve(project_path:, target_project_path:) def resolve(project_path:, target_project_path:, direction: :outbound)
project = authorized_find!(project_path) project = authorized_find!(project_path)
target_project = Project.find_by_full_path(target_project_path) target_project = Project.find_by_full_path(target_project_path)
result = ::Ci::JobTokenScope::RemoveProjectService result = ::Ci::JobTokenScope::RemoveProjectService
.new(project, current_user) .new(project, current_user)
.execute(target_project) .execute(target_project, direction: direction)
if result.success? if result.success?
{ {

View File

@ -13,8 +13,9 @@ module Ci
belongs_to :target_project, class_name: 'Project' belongs_to :target_project, class_name: 'Project'
belongs_to :added_by, class_name: 'User' belongs_to :added_by, class_name: 'User'
scope :with_source, ->(project) { where(source_project: project) } scope :with_access_direction, ->(direction) { where(direction: direction) }
scope :with_target, ->(project) { where(target_project: project) } scope :with_source, ->(project) { where(source_project: project) }
scope :with_target, ->(project) { where(target_project: project) }
validates :source_project, presence: true validates :source_project, presence: true
validates :target_project, presence: true validates :target_project, presence: true

View File

@ -825,6 +825,7 @@ class Project < ApplicationRecord
scope :for_group, -> (group) { where(group: group) } scope :for_group, -> (group) { where(group: group) }
scope :for_group_and_its_subgroups, ->(group) { where(namespace_id: group.self_and_descendants.select(:id)) } scope :for_group_and_its_subgroups, ->(group) { where(namespace_id: group.self_and_descendants.select(:id)) }
scope :for_group_and_its_ancestor_groups, ->(group) { where(namespace_id: group.self_and_ancestors.select(:id)) } scope :for_group_and_its_ancestor_groups, ->(group) { where(namespace_id: group.self_and_ancestors.select(:id)) }
scope :is_importing, -> { with_import_state.where(import_state: { status: %w[started scheduled] }) }
class << self class << self
# Searches for a list of projects based on the query given in `query`. # Searches for a list of projects based on the query given in `query`.

View File

@ -42,7 +42,6 @@ class Ci::PipelineEntity < Grape::Entity
expose :duration expose :duration
expose :finished_at expose :finished_at
expose :event_type_name expose :event_type_name
expose :event_type_name, as: :name # To be removed in 15.7
end end
expose :merge_request, if: -> (*) { has_presentable_merge_request? }, with: MergeRequestForPipelineEntity do |pipeline| expose :merge_request, if: -> (*) { has_presentable_merge_request? }, with: MergeRequestForPipelineEntity do |pipeline|

View File

@ -22,10 +22,6 @@ class MergeRequests::PipelineEntity < Grape::Entity
pipeline.present.event_type_name pipeline.present.event_type_name
end end
expose :name do |pipeline| # To be removed in 15.7
pipeline.present.event_type_name
end
expose :artifacts do |pipeline, options| expose :artifacts do |pipeline, options|
rel = pipeline.downloadable_artifacts rel = pipeline.downloadable_artifacts

View File

@ -5,14 +5,16 @@ module Ci
class RemoveProjectService < ::BaseService class RemoveProjectService < ::BaseService
include EditScopeValidations include EditScopeValidations
def execute(target_project) def execute(target_project, direction: :outbound)
validate_edit!(project, target_project, current_user) validate_edit!(project, target_project, current_user)
if project == target_project if project == target_project
return ServiceResponse.error(message: "Source project cannot be removed from the job token scope") return ServiceResponse.error(message: "Source project cannot be removed from the job token scope")
end end
link = ::Ci::JobToken::ProjectScopeLink.for_source_and_target(project, target_project) link = ::Ci::JobToken::ProjectScopeLink
.with_access_direction(direction)
.for_source_and_target(project, target_project)
unless link unless link
return ServiceResponse.error(message: "Target project is not in the job token scope") return ServiceResponse.error(message: "Target project is not in the job token scope")

View File

@ -177,19 +177,17 @@ module Users
# Allowed params for user signup # Allowed params for user signup
def signup_params def signup_params
signup_params = [ [
:email, :email,
:name, :name,
:password, :password,
:password_automatically_set, :password_automatically_set,
:preferred_language,
:username, :username,
:user_type, :user_type,
:first_name, :first_name,
:last_name :last_name
] ]
signup_params << :preferred_language if ::Feature.enabled?(:preferred_language_switcher)
signup_params
end end
end end
end end

View File

@ -1,3 +1 @@
- return unless ::Feature.enabled?(:preferred_language_switcher)
.js-language-switcher{ data: { locales: ordered_selectable_locales.to_json } } .js-language-switcher{ data: { locales: ordered_selectable_locales.to_json } }

View File

@ -42,6 +42,7 @@ module BulkImports
def run def run
return skip_tracker if entity.failed? return skip_tracker if entity.failed?
raise(Pipeline::ExpiredError, 'Pipeline timeout') if job_timeout?
raise(Pipeline::FailedError, "Export from source instance failed: #{export_status.error}") if export_failed? raise(Pipeline::FailedError, "Export from source instance failed: #{export_status.error}") if export_failed?
raise(Pipeline::ExpiredError, 'Empty export status on source instance') if empty_export_timeout? raise(Pipeline::ExpiredError, 'Empty export status on source instance') if empty_export_timeout?
@ -171,5 +172,11 @@ module BulkImports
def lease_key def lease_key
"gitlab:bulk_imports:pipeline_worker:#{pipeline_tracker.id}" "gitlab:bulk_imports:pipeline_worker:#{pipeline_tracker.id}"
end end
def job_timeout?
return false unless file_extraction_pipeline?
time_since_tracker_created > Pipeline::NDJSON_EXPORT_TIMEOUT
end
end end
end end

View File

@ -1,7 +0,0 @@
---
name: preferred_language_switcher
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/101621
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/381181
milestone: '15.6'
type: development
default_enabled: false

View File

@ -22,6 +22,7 @@ namespace :import do
get :callback get :callback
get :realtime_changes get :realtime_changes
post :cancel post :cancel
post :cancel_all
end end
resource :gitea, only: [:create, :new], controller: :gitea do resource :gitea, only: [:create, :new], controller: :gitea do

View File

@ -1204,6 +1204,7 @@ Input type: `CiJobTokenScopeRemoveProjectInput`
| Name | Type | Description | | Name | Type | Description |
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| <a id="mutationcijobtokenscoperemoveprojectclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | | <a id="mutationcijobtokenscoperemoveprojectclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcijobtokenscoperemoveprojectdirection"></a>`direction` | [`CiJobTokenScopeDirection`](#cijobtokenscopedirection) | Direction of access, which defaults to outbound. |
| <a id="mutationcijobtokenscoperemoveprojectprojectpath"></a>`projectPath` | [`ID!`](#id) | Project that the CI job token scope belongs to. | | <a id="mutationcijobtokenscoperemoveprojectprojectpath"></a>`projectPath` | [`ID!`](#id) | Project that the CI job token scope belongs to. |
| <a id="mutationcijobtokenscoperemoveprojecttargetprojectpath"></a>`targetProjectPath` | [`ID!`](#id) | Project to be removed from the CI job token scope. | | <a id="mutationcijobtokenscoperemoveprojecttargetprojectpath"></a>`targetProjectPath` | [`ID!`](#id) | Project to be removed from the CI job token scope. |

View File

@ -25,5 +25,6 @@ each security partner:
- [Tenable](https://docs.tenable.com/tenableio/Content/ContainerSecurity/GetStarted.htm) - [Tenable](https://docs.tenable.com/tenableio/Content/ContainerSecurity/GetStarted.htm)
- [Venafi](https://marketplace.venafi.com/details/gitlab-ci-cd/) - [Venafi](https://marketplace.venafi.com/details/gitlab-ci-cd/)
- [Veracode](https://community.veracode.com/s/knowledgeitem/gitlab-ci-MCEKSYPRWL35BRTGOVI55SK5RI4A) - [Veracode](https://community.veracode.com/s/knowledgeitem/gitlab-ci-MCEKSYPRWL35BRTGOVI55SK5RI4A)
- [Fortify](https://www.microfocus.com/en-us/fortify-integrations/gitlab)
<!-- vale gitlab.Spelling = YES --> <!-- vale gitlab.Spelling = YES -->

View File

@ -22,31 +22,25 @@ To view Contribution Analytics:
1. On the top bar, select **Main menu > Groups** and find your group. 1. On the top bar, select **Main menu > Groups** and find your group.
1. On the left sidebar, select **Analytics > Contribution**. 1. On the left sidebar, select **Analytics > Contribution**.
## Using Contribution Analytics
Three bar graphs illustrate the number of contributions made by each group member: Three bar graphs illustrate the number of contributions made by each group member:
- Push events - Push events
- Merge requests - Merge requests
- Closed issues - Closed issues
### View a member's contributions
Hover over each bar to display the number of events for a specific group member. Hover over each bar to display the number of events for a specific group member.
![Contribution analytics bar graphs](img/group_stats_graph.png) ![Contribution analytics bar graphs](img/group_stats_graph.png)
## Changing the period time ### Zoom in on a chart
You can choose from the following three periods: You can zoom in on a bar chart to display only a subset of group members.
- Last week (default) To do this, select the sliders (**{status-paused}**) below the chart and slide them along the axis.
- Last month
- Last three months
Select the desired period from the calendar dropdown list. ### Sort contributions
![Contribution analytics choose period](img/group_stats_cal.png)
## Sorting by different factors
Contributions per group member are also presented in tabular format. Select a column header to sort the table by that column: Contributions per group member are also presented in tabular format. Select a column header to sort the table by that column:
@ -61,6 +55,18 @@ Contributions per group member are also presented in tabular format. Select a co
![Contribution analytics contributions table](img/group_stats_table.png) ![Contribution analytics contributions table](img/group_stats_table.png)
## Change the time period
You can choose from the following three periods:
- Last week (default)
- Last month
- Last three months
Select the desired period from the calendar dropdown list.
![Contribution analytics choose period](img/group_stats_cal.png)
## Contribution analytics GraphQL API ## Contribution analytics GraphQL API
To retrieve metrics for user contributions, use the [GraphQL](../../../api/graphql/reference/index.md#groupcontributions) API. To retrieve metrics for user contributions, use the [GraphQL](../../../api/graphql/reference/index.md#groupcontributions) API.

View File

@ -79,6 +79,7 @@ To migrate groups by direct transfer:
- Both GitLab instances must have group migration by direct transfer - Both GitLab instances must have group migration by direct transfer
[enabled in application settings](../../admin_area/settings/visibility_and_access_controls.md#enable-migration-of-groups-and-projects-by-direct-transfer) [enabled in application settings](../../admin_area/settings/visibility_and_access_controls.md#enable-migration-of-groups-and-projects-by-direct-transfer)
by an instance administrator. by an instance administrator.
- The source GitLab instance must be running GitLab 14.0 or later.
- You must have the Owner role on the source group to migrate from. - You must have the Owner role on the source group to migrate from.
- You must have at least the Maintainer role on the destination group to migrate to. Using the Developer role for this - You must have at least the Maintainer role on the destination group to migrate to. Using the Developer role for this
purpose was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/387891) in GitLab 15.8 and will be removed in purpose was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/387891) in GitLab 15.8 and will be removed in
@ -100,16 +101,16 @@ To ensure GitLab maps users and their contributions correctly:
[SAML SSO for GitLab.com groups](../../group/saml_sso/index.md), users must [SAML SSO for GitLab.com groups](../../group/saml_sso/index.md), users must
[link their SAML identity to their GitLab.com account](../../group/saml_sso/index.md#linking-saml-to-your-existing-gitlabcom-account). [link their SAML identity to their GitLab.com account](../../group/saml_sso/index.md#linking-saml-to-your-existing-gitlabcom-account).
### Connect to the source GitLab instance ### Connect the source GitLab instance
Create the group you want to import to and connect the source: Create the group you want to import to and connect the source GitLab instance:
1. Create either: 1. Create either:
- A new group. On the top bar, select **{plus-square}**, then **New group**, and select **Import group**. - A new group. On the top bar, select **{plus-square}**, then **New group**, and select **Import group**.
- A new subgroup. On existing group's page, either: - A new subgroup. On existing group's page, either:
- Select **New subgroup**. - Select **New subgroup**.
- On the top bar, Select **{plus-square}** and then **New subgroup**. Then on the left sidebar, select the **import an existing group** link. - On the top bar, Select **{plus-square}** and then **New subgroup**. Then on the left sidebar, select the **import an existing group** link.
1. Enter the URL of your source GitLab instance. 1. Enter the URL of a GitLab instance running GitLab 14.0 or later.
1. Generate or copy a [personal access token](../../../user/profile/personal_access_tokens.md) on your source GitLab 1. Generate or copy a [personal access token](../../../user/profile/personal_access_tokens.md) on your source GitLab
instance with: instance with:
- The `api` scope, if the source GitLab instance on version 15.1 or later. - The `api` scope, if the source GitLab instance on version 15.1 or later.

View File

@ -12,6 +12,7 @@ module BulkImports
FailedError = Class.new(StandardError) FailedError = Class.new(StandardError)
CACHE_KEY_EXPIRATION = 2.hours CACHE_KEY_EXPIRATION = 2.hours
NDJSON_EXPORT_TIMEOUT = 90.minutes
EMPTY_EXPORT_STATUS_TIMEOUT = 5.minutes EMPTY_EXPORT_STATUS_TIMEOUT = 5.minutes
def initialize(context) def initialize(context)

View File

@ -34463,6 +34463,9 @@ msgstr ""
msgid "ProtectedEnvironments|Approval rules" msgid "ProtectedEnvironments|Approval rules"
msgstr "" msgstr ""
msgid "ProtectedEnvironments|Delete deployment rule"
msgstr ""
msgid "ProtectedEnvironments|List of protected environments (%{protectedEnvironmentsCount})" msgid "ProtectedEnvironments|List of protected environments (%{protectedEnvironmentsCount})"
msgstr "" msgstr ""

View File

@ -329,9 +329,6 @@
"match": "regex", "match": "regex",
"regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$" "regex": "^\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d(:?[0-5]\\d)?|Z)$"
}, },
"$.body.pipelines[*].details.name": {
"match": "type"
},
"$.body.pipelines[*].details.manual_actions": { "$.body.pipelines[*].details.manual_actions": {
"min": 1 "min": 1
}, },

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Import::GithubController, feature_category: :import do RSpec.describe Import::GithubController, feature_category: :importers do
include ImportSpecHelper include ImportSpecHelper
let(:provider) { :github } let(:provider) { :github }
@ -419,4 +419,56 @@ RSpec.describe Import::GithubController, feature_category: :import do
end end
end end
end end
describe 'POST cancel_all' do
context 'when import is in progress' do
it 'returns success' do
project = create(:project, :import_scheduled, namespace: user.namespace, import_type: 'github', import_url: 'https://fake.url')
project2 = create(:project, :import_started, namespace: user.namespace, import_type: 'github', import_url: 'https://fake2.url')
expect(Import::Github::CancelProjectImportService)
.to receive(:new).with(project, user)
.and_return(double(execute: { status: :success, project: project }))
expect(Import::Github::CancelProjectImportService)
.to receive(:new).with(project2, user)
.and_return(double(execute: { status: :bad_request, message: 'The import cannot be canceled because it is finished' }))
post :cancel_all
expect(json_response).to eq([
{
'id' => project.id,
'status' => 'success'
},
{
'id' => project2.id,
'status' => 'bad_request',
'error' => 'The import cannot be canceled because it is finished'
}
])
end
end
context 'when there is no imports in progress' do
it 'returns an empty array' do
create(:project, :import_finished, namespace: user.namespace, import_type: 'github', import_url: 'https://fake.url')
post :cancel_all
expect(json_response).to eq([])
end
end
context 'when there is no projects created by user' do
it 'returns an empty array' do
other_user_project = create(:project, :import_started, import_type: 'github', import_url: 'https://fake.url')
post :cancel_all
expect(json_response).to eq([])
expect(other_user_project.import_status).to eq('started')
end
end
end
end end

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe RegistrationsController, feature_category: :users do RSpec.describe RegistrationsController, feature_category: :user_profile do
include TermsHelper include TermsHelper
include FullNameHelper include FullNameHelper

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Merge request > User sees draft toggle', feature_category: :code_review do RSpec.describe 'Merge request > User sees draft toggle', feature_category: :code_review_workflow do
let_it_be(:project) { create(:project, :public, :repository) } let_it_be(:project) { create(:project, :public, :repository) }
let(:user) { project.creator } let(:user) { project.creator }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'viewing an issue', :js, feature_category: :issue_email_participants do RSpec.describe 'viewing an issue', :js, feature_category: :service_desk do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:non_member) { create(:user) } let_it_be(:non_member) { create(:user) }
let_it_be(:project) { create(:project, :public) } let_it_be(:project) { create(:project, :public) }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Snippets > Create Snippet', :js, feature_category: :snippets do RSpec.describe 'Projects > Snippets > Create Snippet', :js, feature_category: :source_code_management do
include DropzoneHelper include DropzoneHelper
include Spec::Support::Helpers::Features::SnippetSpecHelpers include Spec::Support::Helpers::Features::SnippetSpecHelpers

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Snippets > Project snippet', :js, feature_category: :snippets do RSpec.describe 'Projects > Snippets > Project snippet', :js, feature_category: :source_code_management do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:project) do let_it_be(:project) do
create(:project, creator: user).tap do |p| create(:project, creator: user).tap do |p|

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Snippets > User comments on a snippet', :js, feature_category: :snippets do RSpec.describe 'Projects > Snippets > User comments on a snippet', :js, feature_category: :source_code_management do
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:snippet) { create(:project_snippet, :repository, project: project, author: user) } let_it_be(:snippet) { create(:project_snippet, :repository, project: project, author: user) }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Snippets > User deletes a snippet', :js, feature_category: :snippets do RSpec.describe 'Projects > Snippets > User deletes a snippet', :js, feature_category: :source_code_management do
let(:project) { create(:project) } let(:project) { create(:project) }
let!(:snippet) { create(:project_snippet, :repository, project: project, author: user) } let!(:snippet) { create(:project_snippet, :repository, project: project, author: user) }
let(:user) { create(:user) } let(:user) { create(:user) }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Snippets > User updates a snippet', :js, feature_category: :snippets do RSpec.describe 'Projects > Snippets > User updates a snippet', :js, feature_category: :source_code_management do
include Spec::Support::Helpers::Features::SnippetSpecHelpers include Spec::Support::Helpers::Features::SnippetSpecHelpers
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Projects > Snippets > User views snippets', feature_category: :snippets do RSpec.describe 'Projects > Snippets > User views snippets', feature_category: :source_code_management do
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let(:user) { create(:user) } let(:user) { create(:user) }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Snippets', feature_category: :snippets do RSpec.describe 'Snippets', feature_category: :source_code_management do
context 'when the project has snippets' do context 'when the project has snippets' do
let(:project) { create(:project, :public) } let(:project) { create(:project, :public) }
let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.first_owner, project: project) } let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.first_owner, project: project) }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Snippets tab on a user profile', :js, feature_category: :snippets do RSpec.describe 'Snippets tab on a user profile', :js, feature_category: :source_code_management do
context 'when the user has snippets' do context 'when the user has snippets' do
let(:user) { create(:user) } let(:user) { create(:user) }

View File

@ -837,7 +837,6 @@ export const mockPipelineTag = () => {
duration: 93, duration: 93,
finished_at: '2022-02-02T15:40:59.384Z', finished_at: '2022-02-02T15:40:59.384Z',
event_type_name: 'Pipeline', event_type_name: 'Pipeline',
name: 'Pipeline',
manual_actions: [], manual_actions: [],
scheduled_actions: [], scheduled_actions: [],
}, },
@ -1045,7 +1044,6 @@ export const mockPipelineBranch = () => {
duration: 75, duration: 75,
finished_at: '2022-01-14T18:02:35.842Z', finished_at: '2022-01-14T18:02:35.842Z',
event_type_name: 'Pipeline', event_type_name: 'Pipeline',
name: 'Pipeline',
manual_actions: [], manual_actions: [],
scheduled_actions: [], scheduled_actions: [],
}, },

View File

@ -224,7 +224,6 @@ describe('MRWidgetPipeline', () => {
({ pipeline } = JSON.parse(JSON.stringify(mockData))); ({ pipeline } = JSON.parse(JSON.stringify(mockData)));
pipeline.details.event_type_name = 'Pipeline'; pipeline.details.event_type_name = 'Pipeline';
pipeline.details.name = 'Pipeline';
pipeline.merge_request_event_type = undefined; pipeline.merge_request_event_type = undefined;
pipeline.ref.tag = false; pipeline.ref.tag = false;
pipeline.ref.branch = false; pipeline.ref.branch = false;
@ -266,7 +265,6 @@ describe('MRWidgetPipeline', () => {
describe('for a detached merge request pipeline', () => { describe('for a detached merge request pipeline', () => {
it('renders a pipeline widget that reads "Merge request pipeline <ID> <status> for <SHA>"', () => { it('renders a pipeline widget that reads "Merge request pipeline <ID> <status> for <SHA>"', () => {
pipeline.details.event_type_name = 'Merge request pipeline'; pipeline.details.event_type_name = 'Merge request pipeline';
pipeline.details.name = 'Merge request pipeline';
pipeline.merge_request_event_type = 'detached'; pipeline.merge_request_event_type = 'detached';
factory(); factory();

View File

@ -17,6 +17,7 @@ RSpec.describe Mutations::Ci::JobTokenScope::RemoveProject, feature_category: :c
end end
let(:target_project_path) { target_project.full_path } let(:target_project_path) { target_project.full_path }
let(:links_relation) { Ci::JobToken::ProjectScopeLink.with_source(project).with_target(target_project) }
subject do subject do
mutation.resolve(project_path: project.full_path, target_project_path: target_project_path) mutation.resolve(project_path: project.full_path, target_project_path: target_project_path)
@ -45,18 +46,39 @@ RSpec.describe Mutations::Ci::JobTokenScope::RemoveProject, feature_category: :c
target_project.add_guest(current_user) target_project.add_guest(current_user)
end end
it 'removes target project from the job token scope' do context 'with no direction specified' do
expect do it 'defaults to removing an outbound link to the target project' do
expect(subject).to include(ci_job_token_scope: be_present, errors: be_empty) expect do
end.to change { Ci::JobToken::ProjectScopeLink.count }.by(-1) expect(subject).to include(ci_job_token_scope: be_present, errors: be_empty)
end.to change { Ci::JobToken::ProjectScopeLink.count }.by(-1)
expect(links_relation.outbound.reload).to be_empty
end
end
context 'with direction specified' do
let(:service) { instance_double('Ci::JobTokenScope::RemoveProjectService') }
subject do
mutation.resolve(project_path: project.full_path, target_project_path: target_project_path, direction: 'inbound')
end
it 'executes project removal for the correct direction' do
expect(::Ci::JobTokenScope::RemoveProjectService)
.to receive(:new).with(project, current_user).and_return(service)
expect(service).to receive(:execute).with(target_project, direction: 'inbound')
.and_return(instance_double('ServiceResponse', "success?": true))
subject
end
end end
context 'when the service returns an error' do context 'when the service returns an error' do
let(:service) { double(:service) } let(:service) { instance_double('Ci::JobTokenScope::RemoveProjectService') }
it 'returns an error response' do it 'returns an error response' do
expect(::Ci::JobTokenScope::RemoveProjectService).to receive(:new).with(project, current_user).and_return(service) expect(::Ci::JobTokenScope::RemoveProjectService).to receive(:new).with(project, current_user).and_return(service)
expect(service).to receive(:execute).with(target_project).and_return(ServiceResponse.error(message: 'The error message')) expect(service).to receive(:execute).with(target_project, direction: :outbound).and_return(ServiceResponse.error(message: 'The error message'))
expect(subject.fetch(:ci_job_token_scope)).to be_nil expect(subject.fetch(:ci_job_token_scope)).to be_nil
expect(subject.fetch(:errors)).to include("The error message") expect(subject.fetch(:errors)).to include("The error message")

View File

@ -98,7 +98,7 @@ RSpec.describe IssuablesHelper, feature_category: :team_planning do
end end
end end
describe '#assigned_issuables_count', feature_category: :project_management do describe '#assigned_issuables_count', feature_category: :team_planning do
context 'when issuable is issues' do context 'when issuable is issues' do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project).tap { |p| p.add_developer(user) } } let_it_be(:project) { create(:project).tap { |p| p.add_developer(user) } }
@ -117,7 +117,7 @@ RSpec.describe IssuablesHelper, feature_category: :team_planning do
end end
end end
describe '#assigned_open_issues_count_text', feature_category: :project_management do describe '#assigned_open_issues_count_text', feature_category: :team_planning do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project).tap { |p| p.add_developer(user) } } let_it_be(:project) { create(:project).tap { |p| p.add_developer(user) } }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe BulkImports::Common::Pipelines::UploadsPipeline, feature_category: :import do RSpec.describe BulkImports::Common::Pipelines::UploadsPipeline, feature_category: :importers do
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:group) { create(:group) } let_it_be(:group) { create(:group) }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::BatchedMigrationLastId, feature_category: :pipeline_insights do RSpec.describe Gitlab::Database::Migrations::BatchedMigrationLastId, feature_category: :database do
subject(:test_sampling) { described_class.new(connection, base_dir) } subject(:test_sampling) { described_class.new(connection, base_dir) }
let(:base_dir) { Pathname.new(Dir.mktmpdir) } let(:base_dir) { Pathname.new(Dir.mktmpdir) }

View File

@ -4,7 +4,7 @@ require 'spec_helper'
require 'json' require 'json'
require 'tempfile' require 'tempfile'
RSpec.describe Gitlab::Git::RuggedImpl::UseRugged, feature_category: :gitlay do RSpec.describe Gitlab::Git::RuggedImpl::UseRugged, feature_category: :gitaly do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:repository) { project.repository } let(:repository) { project.repository }
let(:feature_flag_name) { wrapper.rugged_feature_keys.first } let(:feature_flag_name) { wrapper.rugged_feature_keys.first }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Client, feature_category: :importer do RSpec.describe Gitlab::GithubImport::Client, feature_category: :importers do
subject(:client) { described_class.new('foo', parallel: parallel) } subject(:client) { described_class.new('foo', parallel: parallel) }
let(:parallel) { true } let(:parallel) { true }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Clients::Proxy, :manage, feature_category: :import do RSpec.describe Gitlab::GithubImport::Clients::Proxy, :manage, feature_category: :importers do
subject(:client) { described_class.new(access_token, client_options) } subject(:client) { described_class.new(access_token, client_options) }
let(:access_token) { 'test_token' } let(:access_token) { 'test_token' }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::ImportExport::VersionChecker, feature_category: :import do RSpec.describe Gitlab::ImportExport::VersionChecker, feature_category: :importers do
include ImportExport::CommonUtil include ImportExport::CommonUtil
let!(:shared) { Gitlab::ImportExport::Shared.new(nil) } let!(:shared) { Gitlab::ImportExport::Shared.new(nil) }

View File

@ -3,7 +3,7 @@ require 'spec_helper'
require_migration! require_migration!
RSpec.describe RemoveLeftoverExternalPullRequestDeletions, feature_category: :sharding do RSpec.describe RemoveLeftoverExternalPullRequestDeletions, feature_category: :pods do
let(:deleted_records) { table(:loose_foreign_keys_deleted_records) } let(:deleted_records) { table(:loose_foreign_keys_deleted_records) }
let(:pending_record1) { deleted_records.create!(id: 1, fully_qualified_table_name: 'public.external_pull_requests', primary_key_value: 1, status: 1) } let(:pending_record1) { deleted_records.create!(id: 1, fully_qualified_table_name: 'public.external_pull_requests', primary_key_value: 1, status: 1) }

View File

@ -3,7 +3,7 @@ require 'spec_helper'
require_migration! require_migration!
RSpec.describe RemoveLeftoverCiJobArtifactDeletions, feature_category: :sharding do RSpec.describe RemoveLeftoverCiJobArtifactDeletions, feature_category: :pods do
let(:deleted_records) { table(:loose_foreign_keys_deleted_records) } let(:deleted_records) { table(:loose_foreign_keys_deleted_records) }
target_table_name = Ci::JobArtifact.table_name target_table_name = Ci::JobArtifact.table_name

View File

@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
require_migration! require_migration!
RSpec.describe RemoveDeactivatedUserHighestRoleStats, feature_category: :utilization do RSpec.describe RemoveDeactivatedUserHighestRoleStats, feature_category: :subscription_cost_management do
let!(:users) { table(:users) } let!(:users) { table(:users) }
let!(:user_highest_roles) { table(:user_highest_roles) } let!(:user_highest_roles) { table(:user_highest_roles) }

View File

@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
require_migration! require_migration!
RSpec.describe UpdateImportSourcesOnApplicationSettings, feature_category: :migration do RSpec.describe UpdateImportSourcesOnApplicationSettings, feature_category: :importers do
let(:settings) { table(:application_settings) } let(:settings) { table(:application_settings) }
let(:import_sources_with_google) { %w[google_code github git bitbucket bitbucket_server] } let(:import_sources_with_google) { %w[google_code github git bitbucket bitbucket_server] }
let(:import_sources_without_google) { %w[github git bitbucket bitbucket_server] } let(:import_sources_without_google) { %w[github git bitbucket bitbucket_server] }

View File

@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
require_migration! require_migration!
RSpec.describe FixUpdateImportSourcesOnApplicationSettings, feature_category: :migration do RSpec.describe FixUpdateImportSourcesOnApplicationSettings, feature_category: :importers do
let(:settings) { table(:application_settings) } let(:settings) { table(:application_settings) }
let(:import_sources) { %w[github git bitbucket bitbucket_server] } let(:import_sources) { %w[github git bitbucket bitbucket_server] }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Integrations::AppleAppStore, feature_category: :mobile_devops do RSpec.describe Integrations::AppleAppStore, feature_category: :mobile_signing_deployment do
describe 'Validations' do describe 'Validations' do
context 'when active' do context 'when active' do
before do before do

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Issue, feature_category: :project_management do RSpec.describe Issue, feature_category: :team_planning do
include ExternalAuthorizationServiceHelpers include ExternalAuthorizationServiceHelpers
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax

View File

@ -8813,6 +8813,16 @@ RSpec.describe Project, factory_default: :keep, feature_category: :projects do
end end
end end
describe '.is_importing' do
it 'returns projects that have import in progress' do
project_1 = create(:project, :import_scheduled, import_type: 'github')
project_2 = create(:project, :import_started, import_type: 'github')
create(:project, :import_finished, import_type: 'github')
expect(described_class.is_importing).to match_array([project_1, project_2])
end
end
private private
def finish_job(export_job) def finish_job(export_job)

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe ResourceEvent, feature_category: :team_planing, type: :model do RSpec.describe ResourceEvent, feature_category: :team_planning, type: :model do
let(:dummy_resource_label_event_class) do let(:dummy_resource_label_event_class) do
Class.new(ResourceEvent) do Class.new(ResourceEvent) do
self.table_name = 'resource_label_events' self.table_name = 'resource_label_events'

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe ResourceLabelEvent, feature_category: :team_planing, type: :model do RSpec.describe ResourceLabelEvent, feature_category: :team_planning, type: :model do
let_it_be(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
let_it_be(:issue) { create(:issue, project: project) } let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:merge_request) { create(:merge_request, source_project: project) } let_it_be(:merge_request) { create(:merge_request, source_project: project) }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe ResourceMilestoneEvent, feature_category: :team_planing, type: :model do RSpec.describe ResourceMilestoneEvent, feature_category: :team_planning, type: :model do
it_behaves_like 'a resource event' it_behaves_like 'a resource event'
it_behaves_like 'a resource event for issues' it_behaves_like 'a resource event for issues'
it_behaves_like 'a resource event for merge requests' it_behaves_like 'a resource event for merge requests'

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe ResourceStateEvent, feature_category: :team_planing, type: :model do RSpec.describe ResourceStateEvent, feature_category: :team_planning, type: :model do
subject { build(:resource_state_event, issue: issue) } subject { build(:resource_state_event, issue: issue) }
let(:issue) { create(:issue) } let(:issue) { create(:issue) }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe GlobalPolicy, feature_category: :security_policies do RSpec.describe GlobalPolicy, feature_category: :shared do
include TermsHelper include TermsHelper
let_it_be(:admin_user) { create(:admin) } let_it_be(:admin_user) { create(:admin) }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe TodoPolicy, feature_category: :project_management do RSpec.describe TodoPolicy, feature_category: :team_planning do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }

View File

@ -22,6 +22,7 @@ RSpec.describe 'CiJobTokenScopeRemoveProject', feature_category: :continuous_int
let(:variables) do let(:variables) do
{ {
direction: 'OUTBOUND',
project_path: project.full_path, project_path: project.full_path,
target_project_path: target_project.full_path target_project_path: target_project.full_path
} }
@ -67,7 +68,7 @@ RSpec.describe 'CiJobTokenScopeRemoveProject', feature_category: :continuous_int
target_project.add_guest(current_user) target_project.add_guest(current_user)
end end
it 'removes the target project from the job token scope' do it 'removes the target project from the job token outbound scope' do
expect do expect do
post_graphql_mutation(mutation, current_user: current_user) post_graphql_mutation(mutation, current_user: current_user)
expect(response).to have_gitlab_http_status(:success) expect(response).to have_gitlab_http_status(:success)

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'PipelineSchedulePlay', feature_category: :continuious_integration do RSpec.describe 'PipelineSchedulePlay', feature_category: :continuous_integration do
include GraphqlHelpers include GraphqlHelpers
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'rendering project statistics', feature_category: :project_statistics do RSpec.describe 'rendering project statistics', feature_category: :shared do
include GraphqlHelpers include GraphqlHelpers
let(:project) { create(:project) } let(:project) { create(:project) }

View File

@ -71,6 +71,10 @@ RSpec.describe Import::GithubController, 'routing' do
it 'to #personal_access_token' do it 'to #personal_access_token' do
expect(post('/import/github/personal_access_token')).to route_to('import/github#personal_access_token') expect(post('/import/github/personal_access_token')).to route_to('import/github#personal_access_token')
end end
it 'to #cancel_all' do
expect(post('/import/github/cancel_all')).to route_to('import/github#cancel_all')
end
end end
# personal_access_token_import_gitea POST /import/gitea/personal_access_token(.:format) import/gitea#personal_access_token # personal_access_token_import_gitea POST /import/gitea/personal_access_token(.:format) import/gitea#personal_access_token

View File

@ -36,11 +36,10 @@ RSpec.describe Ci::PipelineEntity do
expect(subject).to include :details expect(subject).to include :details
expect(subject[:details]) expect(subject[:details])
.to include :duration, :finished_at, :name, :event_type_name .to include :duration, :finished_at, :event_type_name
expect(subject[:details][:status]).to include :icon, :favicon, :text, :label, :tooltip expect(subject[:details][:status]).to include :icon, :favicon, :text, :label, :tooltip
expect(subject[:details][:event_type_name]).to eq('Merged result pipeline') expect(subject[:details][:event_type_name]).to eq('Merged result pipeline')
expect(subject[:details][:name]).to eq('Merged result pipeline')
end end
it 'contains flags' do it 'contains flags' do

View File

@ -33,12 +33,11 @@ RSpec.describe MergeRequests::PipelineEntity do
) )
expect(subject[:commit]).to include(:short_id, :commit_path) expect(subject[:commit]).to include(:short_id, :commit_path)
expect(subject[:ref]).to include(:branch) expect(subject[:ref]).to include(:branch)
expect(subject[:details]).to include(:artifacts, :name, :event_type_name, :status, :stages, :finished_at) expect(subject[:details]).to include(:artifacts, :event_type_name, :status, :stages, :finished_at)
expect(subject[:details][:status]).to include(:icon, :favicon, :text, :label, :tooltip) expect(subject[:details][:status]).to include(:icon, :favicon, :text, :label, :tooltip)
expect(subject[:flags]).to include(:merge_request_pipeline) expect(subject[:flags]).to include(:merge_request_pipeline)
expect(subject[:details][:event_type_name]).to eq('Merged result pipeline') expect(subject[:details][:event_type_name]).to eq('Merged result pipeline')
expect(subject[:details][:name]).to eq('Merged result pipeline')
end end
it 'returns presented coverage' do it 'returns presented coverage' do

View File

@ -2,7 +2,7 @@
require "spec_helper" require "spec_helper"
RSpec.describe Lfs::FileTransformer, feature_category: :git_lfs do RSpec.describe Lfs::FileTransformer, feature_category: :source_code_management do
let(:project) { create(:project, :repository, :wiki_repo) } let(:project) { create(:project, :repository, :wiki_repo) }
let(:repository) { project.repository } let(:repository) { project.repository }
let(:file_content) { 'Test file content' } let(:file_content) { 'Test file content' }

View File

@ -512,7 +512,7 @@ RSpec.describe Notes::CreateService, feature_category: :team_planning do
end end
end end
context 'personal snippet note', feature_category: :snippets do context 'personal snippet note', feature_category: :source_code_management do
subject { described_class.new(nil, user, params).execute } subject { described_class.new(nil, user, params).execute }
let(:snippet) { create(:personal_snippet) } let(:snippet) { create(:personal_snippet) }

View File

@ -2,7 +2,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Security::CiConfiguration::SastCreateService, :snowplow, feature_category: :sast do RSpec.describe Security::CiConfiguration::SastCreateService, :snowplow,
feature_category: :static_application_security_testing do
subject(:result) { described_class.new(project, user, params).execute } subject(:result) { described_class.new(project, user, params).execute }
let(:branch_name) { 'set-sast-config-1' } let(:branch_name) { 'set-sast-config-1' }

View File

@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Users::AssignedIssuesCountService, :use_clean_rails_memory_store_caching, RSpec.describe Users::AssignedIssuesCountService, :use_clean_rails_memory_store_caching,
feature_category: :project_management do feature_category: :team_planning do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:max_limit) { 10 } let_it_be(:max_limit) { 10 }

View File

@ -7,7 +7,7 @@ require 'rake_helper'
# is hit in the rake task. # is hit in the rake task.
require 'git' require 'git'
RSpec.describe 'gitlab:security namespace rake tasks', :silence_stdout, feature_category: :security do RSpec.describe 'gitlab:security namespace rake tasks', :silence_stdout, feature_category: :credential_management do
let(:fixture_path) { Rails.root.join('spec/fixtures/tasks/gitlab/security') } let(:fixture_path) { Rails.root.join('spec/fixtures/tasks/gitlab/security') }
let(:output_file) { File.join(__dir__, 'tmp/banned_keys_test.yml') } let(:output_file) { File.join(__dir__, 'tmp/banned_keys_test.yml') }
let(:git_url) { 'https://github.com/rapid7/ssh-badkeys.git' } let(:git_url) { 'https://github.com/rapid7/ssh-badkeys.git' }

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'layouts/snippets', feature_category: :snippets do RSpec.describe 'layouts/snippets', feature_category: :source_code_management do
before do before do
allow(view).to receive(:current_user).and_return(user) allow(view).to receive(:current_user).and_return(user)
allow(view).to receive(:current_user_mode).and_return(Gitlab::Auth::CurrentUserMode.new(user)) allow(view).to receive(:current_user_mode).and_return(Gitlab::Auth::CurrentUserMode.new(user))

View File

@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'projects/commit/show.html.haml', feature_category: :source_code do RSpec.describe 'projects/commit/show.html.haml', feature_category: :source_code_management do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:commit) { project.commit } let(:commit) { project.commit }

View File

@ -507,6 +507,40 @@ RSpec.describe BulkImports::PipelineWorker, feature_category: :importers do
end end
end end
context 'when job reaches timeout' do
it 'marks as failed and logs the error' do
old_created_at = pipeline_tracker.created_at
pipeline_tracker.update!(created_at: (BulkImports::Pipeline::NDJSON_EXPORT_TIMEOUT + 1.hour).ago)
expect_next_instance_of(Gitlab::Import::Logger) do |logger|
expect(logger)
.to receive(:error)
.with(
hash_including(
'pipeline_name' => 'NdjsonPipeline',
'bulk_import_entity_id' => entity.id,
'bulk_import_id' => entity.bulk_import_id,
'bulk_import_entity_type' => entity.source_type,
'source_full_path' => entity.source_full_path,
'class' => 'BulkImports::PipelineWorker',
'exception.backtrace' => anything,
'exception.class' => 'BulkImports::Pipeline::ExpiredError',
'exception.message' => 'Pipeline timeout',
'importer' => 'gitlab_migration',
'message' => 'Pipeline failed',
'source_version' => entity.bulk_import.source_version_info.to_s
)
)
end
subject.perform(pipeline_tracker.id, pipeline_tracker.stage, entity.id)
expect(pipeline_tracker.reload.status_name).to eq(:failed)
entity.update!(created_at: old_created_at)
end
end
context 'when export status is failed' do context 'when export status is failed' do
it 'marks as failed and logs the error' do it 'marks as failed and logs the error' do
allow_next_instance_of(BulkImports::ExportStatus) do |status| allow_next_instance_of(BulkImports::ExportStatus) do |status|