summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-06-08 18:08:27 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-06-08 18:08:27 +0000
commit99c01aa6867b91b8d2279eb8d32794ea90d5dcdc (patch)
treeae36b06dd962230381080d9e2a31385cea5f8609
parent5693fb6ba7d21ba7b79775543a3f195eb989664b (diff)
downloadgitlab-ce-99c01aa6867b91b8d2279eb8d32794ea90d5dcdc.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/controllers/projects/import/jira_controller.rb27
-rw-r--r--app/models/concerns/import_state/sidekiq_job_tracker.rb2
-rw-r--r--app/models/merge_request.rb2
-rw-r--r--app/models/project_services/jira_service.rb4
-rw-r--r--app/models/service.rb1
-rw-r--r--app/models/user.rb24
-rw-r--r--app/services/todo_service.rb16
-rw-r--r--app/views/projects/import/jira/show.html.haml2
-rw-r--r--app/workers/all_queues.yml10
-rw-r--r--app/workers/gitlab/import/stuck_project_import_jobs_worker.rb22
-rw-r--r--app/workers/gitlab/phabricator_import/base_worker.rb2
-rw-r--r--changelogs/unreleased/216939-remove-async-mr-check-ff.yml5
-rw-r--r--config/initializers/1_settings.rb6
-rw-r--r--config/routes/project.rb4
-rw-r--r--config/webpack.config.js8
-rw-r--r--db/post_migrate/20200525144525_migrate_stuck_import_jobs_queue_to_stuck_project_import_jobs.rb15
-rw-r--r--db/structure.sql1
-rw-r--r--doc/administration/audit_events.md4
-rw-r--r--doc/administration/auth/README.md3
-rw-r--r--doc/administration/auth/authentiq.md3
-rw-r--r--doc/administration/auth/cognito.md7
-rw-r--r--doc/administration/auth/crowd.md3
-rw-r--r--doc/administration/auth/jwt.md3
-rw-r--r--doc/administration/auth/ldap/google_secure_ldap.md3
-rw-r--r--doc/administration/auth/ldap/index.md3
-rw-r--r--doc/administration/auth/ldap/ldap-troubleshooting.md7
-rw-r--r--doc/administration/auth/oidc.md3
-rw-r--r--doc/administration/auth/okta.md3
-rw-r--r--doc/administration/packages/container_registry.md10
-rw-r--r--doc/api/merge_requests.md6
-rw-r--r--doc/ci/variables/img/ci_job_stage_output_example.pngbin156322 -> 55081 bytes
-rw-r--r--doc/ci/variables/img/inherited_group_variables_v12_5.pngbin58215 -> 20448 bytes
-rw-r--r--doc/ci/variables/img/override_value_via_manual_pipeline_output.pngbin310224 -> 110898 bytes
-rw-r--r--doc/ci/variables/img/override_variable_manual_pipeline.pngbin52678 -> 17876 bytes
-rw-r--r--doc/development/github_importer.md12
-rw-r--r--doc/development/import_export.md35
-rw-r--r--doc/topics/autodevops/index.md134
-rw-r--r--doc/topics/autodevops/requirements.md134
-rw-r--r--doc/topics/autodevops/stages.md6
-rw-r--r--doc/user/analytics/code_review_analytics.md3
-rw-r--r--doc/user/analytics/index.md3
-rw-r--r--doc/user/analytics/productivity_analytics.md3
-rw-r--r--doc/user/analytics/repository_analytics.md3
-rw-r--r--doc/user/analytics/value_stream_analytics.md3
-rw-r--r--doc/user/compliance/compliance_dashboard/index.md3
-rw-r--r--doc/user/compliance/index.md7
-rw-r--r--doc/user/group/contribution_analytics/index.md3
-rw-r--r--doc/user/group/custom_project_templates.md3
-rw-r--r--doc/user/group/index.md3
-rw-r--r--doc/user/group/insights/index.md3
-rw-r--r--doc/user/group/issues_analytics/index.md3
-rw-r--r--doc/user/group/saml_sso/index.md3
-rw-r--r--doc/user/group/saml_sso/scim_setup.md3
-rw-r--r--doc/user/group/settings/import_export.md6
-rw-r--r--doc/user/packages/container_registry/index.md30
-rw-r--r--doc/user/permissions.md2
-rw-r--r--doc/user/profile/account/create_accounts.md3
-rw-r--r--doc/user/profile/account/delete_account.md3
-rw-r--r--doc/user/profile/account/two_factor_authentication.md3
-rw-r--r--doc/user/profile/index.md3
-rw-r--r--doc/user/profile/personal_access_tokens.md3
-rw-r--r--doc/user/profile/unknown_sign_in_notification.md7
-rw-r--r--doc/user/project/deploy_boards.md4
-rw-r--r--doc/user/project/import/bitbucket.md7
-rw-r--r--doc/user/project/import/bitbucket_server.md7
-rw-r--r--doc/user/project/import/clearcase.md7
-rw-r--r--doc/user/project/import/cvs.md7
-rw-r--r--doc/user/project/import/fogbugz.md7
-rw-r--r--doc/user/project/import/gemnasium.md7
-rw-r--r--doc/user/project/import/gitea.md7
-rw-r--r--doc/user/project/import/github.md7
-rw-r--r--doc/user/project/import/gitlab_com.md7
-rw-r--r--doc/user/project/import/index.md7
-rw-r--r--doc/user/project/import/manifest.md7
-rw-r--r--doc/user/project/import/perforce.md7
-rw-r--r--doc/user/project/import/phabricator.md7
-rw-r--r--doc/user/project/import/repo_by_url.md7
-rw-r--r--doc/user/project/import/svn.md7
-rw-r--r--doc/user/project/wiki/index.md8
-rw-r--r--lib/gitlab/import/set_async_jid.rb7
-rw-r--r--lib/gitlab/jira_import.rb6
-rw-r--r--spec/controllers/projects/import/jira_controller_spec.rb168
-rw-r--r--spec/frontend/behaviors/autosize_spec.js (renamed from spec/javascripts/behaviors/autosize_spec.js)0
-rw-r--r--spec/frontend/behaviors/bind_in_out_spec.js10
-rw-r--r--spec/frontend/behaviors/copy_as_gfm_spec.js (renamed from spec/javascripts/behaviors/copy_as_gfm_spec.js)14
-rw-r--r--spec/frontend/behaviors/gl_emoji/unicode_support_map_spec.js (renamed from spec/javascripts/behaviors/gl_emoji/unicode_support_map_spec.js)24
-rw-r--r--spec/frontend/behaviors/markdown/highlight_current_user_spec.js (renamed from spec/javascripts/behaviors/markdown/highlight_current_user_spec.js)0
-rw-r--r--spec/frontend/behaviors/requires_input_spec.js (renamed from spec/javascripts/behaviors/requires_input_spec.js)0
-rw-r--r--spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js (renamed from spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js)75
-rw-r--r--spec/frontend/helpers/dom_shims/image_element_properties.js2
-rw-r--r--spec/lib/gitlab/jira_import_spec.rb17
-rw-r--r--spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb16
-rw-r--r--spec/lib/gitlab/sidekiq_config_spec.rb2
-rw-r--r--spec/lib/gitlab/sidekiq_versioning/manager_spec.rb2
-rw-r--r--spec/models/merge_request_spec.rb20
-rw-r--r--spec/models/repository_spec.rb8
-rw-r--r--spec/models/service_spec.rb40
-rw-r--r--spec/services/projects/create_service_spec.rb15
-rw-r--r--spec/services/todo_service_spec.rb91
-rw-r--r--spec/workers/gitlab/import/stuck_project_import_jobs_worker_spec.rb27
100 files changed, 818 insertions, 479 deletions
diff --git a/app/controllers/projects/import/jira_controller.rb b/app/controllers/projects/import/jira_controller.rb
index 25fbb1328e4..976ac7df976 100644
--- a/app/controllers/projects/import/jira_controller.rb
+++ b/app/controllers/projects/import/jira_controller.rb
@@ -4,27 +4,30 @@ module Projects
module Import
class JiraController < Projects::ApplicationController
before_action :authenticate_user!
- before_action :check_issues_available!
before_action :authorize_read_project!
- before_action :authorize_admin_project!, only: [:import]
+ before_action :validate_jira_import_settings!
def show
end
- def import
- jira_project_key = jira_import_params[:jira_project_key]
+ private
- if jira_project_key.present?
- response = ::JiraImport::StartImportService.new(current_user, @project, jira_project_key).execute
- flash[:notice] = response.message if response.message.present?
- else
- flash[:alert] = 'No Jira project key has been provided.'
- end
+ def validate_jira_import_settings!
+ Gitlab::JiraImport.validate_project_settings!(@project, user: current_user, configuration_check: false)
+
+ true
+ rescue Projects::ImportService::Error => e
+ flash[:notice] = e.message
+ redirect_to project_issues_path(@project)
- redirect_to project_import_jira_path(@project)
+ false
end
- private
+ def jira_service
+ strong_memoize(:jira_service) do
+ @project.jira_service
+ end
+ end
def jira_import_params
params.permit(:jira_project_key)
diff --git a/app/models/concerns/import_state/sidekiq_job_tracker.rb b/app/models/concerns/import_state/sidekiq_job_tracker.rb
index 212cb8f01c7..b7d0ed0f51b 100644
--- a/app/models/concerns/import_state/sidekiq_job_tracker.rb
+++ b/app/models/concerns/import_state/sidekiq_job_tracker.rb
@@ -11,7 +11,7 @@ module ImportState
# Refreshes the expiration time of the associated import job ID.
#
# This method can be used by asynchronous importers to refresh the status,
- # preventing the StuckImportJobsWorker from marking the import as failed.
+ # preventing the Gitlab::Import::StuckProjectImportJobsWorker from marking the import as failed.
def refresh_jid_expiration
return unless jid
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 6faf45d1009..1453b1f11d2 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -877,7 +877,7 @@ class MergeRequest < ApplicationRecord
check_service = MergeRequests::MergeabilityCheckService.new(self)
- if async && Feature.enabled?(:async_merge_request_check_mergeability, project, default_enabled: true)
+ if async
check_service.async_execute
else
check_service.execute(retry_lease: false)
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index eee594ab4ca..4723ce9ccdc 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -203,6 +203,10 @@ class JiraService < IssueTrackerService
add_comment(data, jira_issue)
end
+ def valid_connection?
+ test(nil)[:success]
+ end
+
def test(_)
result = test_settings
success = result.present?
diff --git a/app/models/service.rb b/app/models/service.rb
index 6c4050f678e..e041db76727 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -355,6 +355,7 @@ class Service < ApplicationRecord
service.template = false
service.instance = false
+ service.inherit_from_id = integration.id if integration.instance?
service.project_id = project_id
service.active = false if service.invalid?
service
diff --git a/app/models/user.rb b/app/models/user.rb
index 5275a7dd8ed..036598fbc77 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -265,18 +265,20 @@ class User < ApplicationRecord
# User's role
enum role: { software_developer: 0, development_team_lead: 1, devops_engineer: 2, systems_administrator: 3, security_analyst: 4, data_analyst: 5, product_manager: 6, product_designer: 7, other: 8 }, _suffix: true
+ delegate :notes_filter_for,
+ :set_notes_filter,
+ :first_day_of_week, :first_day_of_week=,
+ :timezone, :timezone=,
+ :time_display_relative, :time_display_relative=,
+ :time_format_in_24h, :time_format_in_24h=,
+ :show_whitespace_in_diffs, :show_whitespace_in_diffs=,
+ :tab_width, :tab_width=,
+ :sourcegraph_enabled, :sourcegraph_enabled=,
+ :setup_for_company, :setup_for_company=,
+ :render_whitespace_in_code, :render_whitespace_in_code=,
+ to: :user_preference
+
delegate :path, to: :namespace, allow_nil: true, prefix: true
- delegate :notes_filter_for, to: :user_preference
- delegate :set_notes_filter, to: :user_preference
- delegate :first_day_of_week, :first_day_of_week=, to: :user_preference
- delegate :timezone, :timezone=, to: :user_preference
- delegate :time_display_relative, :time_display_relative=, to: :user_preference
- delegate :time_format_in_24h, :time_format_in_24h=, to: :user_preference
- delegate :show_whitespace_in_diffs, :show_whitespace_in_diffs=, to: :user_preference
- delegate :tab_width, :tab_width=, to: :user_preference
- delegate :sourcegraph_enabled, :sourcegraph_enabled=, to: :user_preference
- delegate :setup_for_company, :setup_for_company=, to: :user_preference
- delegate :render_whitespace_in_code, :render_whitespace_in_code=, to: :user_preference
delegate :job_title, :job_title=, to: :user_detail, allow_nil: true
accepts_nested_attributes_for :user_preference, update_only: true
diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb
index 9a1934b322f..e6fb0d3c72e 100644
--- a/app/services/todo_service.rb
+++ b/app/services/todo_service.rb
@@ -154,6 +154,14 @@ class TodoService
resolve_todos_for_target(awardable, current_user)
end
+ # When assigning an alert we should:
+ #
+ # * create a pending todo for new assignee if alert is assigned
+ #
+ def assign_alert(alert, current_user)
+ create_assignment_todo(alert, current_user, [])
+ end
+
# When user marks an issue as todo
def mark_todo(issuable, current_user)
attributes = attributes_for_todo(issuable.project, issuable, current_user, Todo::MARKED)
@@ -242,10 +250,10 @@ class TodoService
create_mention_todos(project, target, author, note, skip_users)
end
- def create_assignment_todo(issuable, author, old_assignees = [])
- if issuable.assignees.any?
- assignees = issuable.assignees - old_assignees
- attributes = attributes_for_todo(issuable.project, issuable, author, Todo::ASSIGNED)
+ def create_assignment_todo(target, author, old_assignees = [])
+ if target.assignees.any?
+ assignees = target.assignees - old_assignees
+ attributes = attributes_for_todo(target.project, target, author, Todo::ASSIGNED)
create_todos(assignees, attributes)
end
end
diff --git a/app/views/projects/import/jira/show.html.haml b/app/views/projects/import/jira/show.html.haml
index 5eaba080baa..a3e81521648 100644
--- a/app/views/projects/import/jira/show.html.haml
+++ b/app/views/projects/import/jira/show.html.haml
@@ -1,6 +1,6 @@
.js-jira-import-root{ data: { project_path: @project.full_path,
issues_path: project_issues_path(@project),
jira_integration_path: edit_project_service_path(@project, :jira),
- is_jira_configured: @project.jira_service.present?.to_s,
+ is_jira_configured: @project.jira_service&.valid_connection?.to_s,
in_progress_illustration: image_path('illustrations/export-import.svg'),
setup_illustration: image_path('illustrations/manual_action.svg') } }
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index bcb3679a8c5..0699be0f4cb 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -147,6 +147,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: cronjob:import_stuck_project_import_jobs
+ :feature_category: :importers
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :cpu
+ :weight: 1
+ :idempotent:
+ :tags: []
- :name: cronjob:issue_due_scheduler
:feature_category: :issue_tracking
:has_external_dependencies:
@@ -813,7 +821,7 @@
:tags: []
- :name: pipeline_background:ci_build_report_result
:feature_category: :continuous_integration
- :has_external_dependencies:
+ :has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
diff --git a/app/workers/gitlab/import/stuck_project_import_jobs_worker.rb b/app/workers/gitlab/import/stuck_project_import_jobs_worker.rb
new file mode 100644
index 00000000000..01979b2029f
--- /dev/null
+++ b/app/workers/gitlab/import/stuck_project_import_jobs_worker.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+module Gitlab
+ module Import
+ class StuckProjectImportJobsWorker # rubocop:disable Scalability/IdempotentWorker
+ include Gitlab::Import::StuckImportJob
+
+ private
+
+ def track_metrics(with_jid_count, without_jid_count)
+ Gitlab::Metrics.add_event(
+ :stuck_import_jobs,
+ projects_without_jid_count: without_jid_count,
+ projects_with_jid_count: with_jid_count
+ )
+ end
+
+ def enqueued_import_states
+ ProjectImportState.with_status([:scheduled, :started])
+ end
+ end
+ end
+end
diff --git a/app/workers/gitlab/phabricator_import/base_worker.rb b/app/workers/gitlab/phabricator_import/base_worker.rb
index 82ef9e825f9..2dc4855f854 100644
--- a/app/workers/gitlab/phabricator_import/base_worker.rb
+++ b/app/workers/gitlab/phabricator_import/base_worker.rb
@@ -13,7 +13,7 @@
# - It keeps track of the jobs so we know how many jobs are running for the
# project
# - It refreshes the import jid, so it doesn't get cleaned up by the
-# `StuckImportJobsWorker`
+# `Gitlab::Import::StuckProjectImportJobsWorker`
# - It marks the import as failed if a job failed to many times
# - It marks the import as finished when all remaining jobs are done
module Gitlab
diff --git a/changelogs/unreleased/216939-remove-async-mr-check-ff.yml b/changelogs/unreleased/216939-remove-async-mr-check-ff.yml
new file mode 100644
index 00000000000..b66cb44de4b
--- /dev/null
+++ b/changelogs/unreleased/216939-remove-async-mr-check-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove async_merge_request_check_mergeability feature flag
+merge_request: 33917
+author:
+type: changed
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 166649fc24a..fbea1e6b8c1 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -451,9 +451,9 @@ Settings.cron_jobs['trending_projects_worker']['job_class'] = 'TrendingProjectsW
Settings.cron_jobs['remove_unreferenced_lfs_objects_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['remove_unreferenced_lfs_objects_worker']['cron'] ||= '20 0 * * *'
Settings.cron_jobs['remove_unreferenced_lfs_objects_worker']['job_class'] = 'RemoveUnreferencedLfsObjectsWorker'
-Settings.cron_jobs['stuck_import_jobs_worker'] ||= Settingslogic.new({})
-Settings.cron_jobs['stuck_import_jobs_worker']['cron'] ||= '15 * * * *'
-Settings.cron_jobs['stuck_import_jobs_worker']['job_class'] = 'StuckImportJobsWorker'
+Settings.cron_jobs['import_stuck_project_import_jobs'] ||= Settingslogic.new({})
+Settings.cron_jobs['import_stuck_project_import_jobs']['cron'] ||= '15 * * * *'
+Settings.cron_jobs['import_stuck_project_import_jobs']['job_class'] = 'Gitlab::Import::StuckProjectImportJobsWorker'
Settings.cron_jobs['jira_import_stuck_jira_import_jobs'] ||= Settingslogic.new({})
Settings.cron_jobs['jira_import_stuck_jira_import_jobs']['cron'] ||= '* 0/15 * * *'
Settings.cron_jobs['jira_import_stuck_jira_import_jobs']['job_class'] = 'Gitlab::JiraImport::StuckJiraImportJobsWorker'
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 2b46754e98e..e35f8a7b5b5 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -324,9 +324,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
draw :wiki
namespace :import do
- resource :jira, only: [:show], controller: :jira do
- post :import
- end
+ resource :jira, only: [:show], controller: :jira
end
end
# End of the /-/ scope.
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 508407d3540..c17734ed3dc 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -514,6 +514,14 @@ module.exports = {
// This one is used to check against "EE" properly in application code
IS_EE: IS_EE ? 'window.gon && window.gon.ee' : JSON.stringify(false),
}),
+
+ /* Pikaday has a optional dependency to moment.
+ We are currently not utilizing moment.
+ Ignoring this import removes warning from our development build.
+ Upstream reference:
+ https://github.com/Pikaday/Pikaday/blob/5c1a7559be/pikaday.js#L14
+ */
+ new webpack.IgnorePlugin(/moment/, /pikaday/),
].filter(Boolean),
devServer: {
diff --git a/db/post_migrate/20200525144525_migrate_stuck_import_jobs_queue_to_stuck_project_import_jobs.rb b/db/post_migrate/20200525144525_migrate_stuck_import_jobs_queue_to_stuck_project_import_jobs.rb
new file mode 100644
index 00000000000..57e25c928f1
--- /dev/null
+++ b/db/post_migrate/20200525144525_migrate_stuck_import_jobs_queue_to_stuck_project_import_jobs.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class MigrateStuckImportJobsQueueToStuckProjectImportJobs < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ sidekiq_queue_migrate 'cronjob:stuck_import_jobs', to: 'cronjob:import_stuck_project_import_jobs'
+ end
+
+ def down
+ sidekiq_queue_migrate 'cronjob:import_stuck_project_import_jobs', to: 'cronjob:stuck_import_jobs'
+ end
+end
diff --git a/db/structure.sql b/db/structure.sql
index 64bcdb577ac..3500354ac07 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -13781,6 +13781,7 @@ COPY "schema_migrations" (version) FROM STDIN;
20200522235146
20200525114553
20200525121014
+20200525144525
20200526000407
20200526013844
20200526120714
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
index b80c725dad5..cc94d756f99 100644
--- a/doc/administration/audit_events.md
+++ b/doc/administration/audit_events.md
@@ -1,6 +1,6 @@
---
-stage: Monitor
-group: APM
+stage: Manage
+group: Analytics
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
diff --git a/doc/administration/auth/README.md b/doc/administration/auth/README.md
index f785724dc54..60e1dfb4637 100644
--- a/doc/administration/auth/README.md
+++ b/doc/administration/auth/README.md
@@ -1,6 +1,9 @@
---
comments: false
type: index
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# GitLab authentication and authorization
diff --git a/doc/administration/auth/authentiq.md b/doc/administration/auth/authentiq.md
index e9b32b64160..56f6fddc1af 100644
--- a/doc/administration/auth/authentiq.md
+++ b/doc/administration/auth/authentiq.md
@@ -1,5 +1,8 @@
---
type: reference
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Authentiq OmniAuth Provider
diff --git a/doc/administration/auth/cognito.md b/doc/administration/auth/cognito.md
index 8d5580ccb6c..1674cce1390 100644
--- a/doc/administration/auth/cognito.md
+++ b/doc/administration/auth/cognito.md
@@ -1,3 +1,10 @@
+---
+type: concepts, howto
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Amazon Web Services Cognito
Amazon Cognito lets you add user sign-up, sign-in, and access control to your GitLab instance.
diff --git a/doc/administration/auth/crowd.md b/doc/administration/auth/crowd.md
index 71938d4fd2b..254bd259344 100644
--- a/doc/administration/auth/crowd.md
+++ b/doc/administration/auth/crowd.md
@@ -1,5 +1,8 @@
---
type: reference
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Atlassian Crowd OmniAuth Provider
diff --git a/doc/administration/auth/jwt.md b/doc/administration/auth/jwt.md
index 5a773485842..29b192a4845 100644
--- a/doc/administration/auth/jwt.md
+++ b/doc/administration/auth/jwt.md
@@ -1,5 +1,8 @@
---
type: reference
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# JWT OmniAuth provider
diff --git a/doc/administration/auth/ldap/google_secure_ldap.md b/doc/administration/auth/ldap/google_secure_ldap.md
index 3a8913196af..2271ce93b6f 100644
--- a/doc/administration/auth/ldap/google_secure_ldap.md
+++ b/doc/administration/auth/ldap/google_secure_ldap.md
@@ -1,5 +1,8 @@
---
type: reference
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Google Secure LDAP **(CORE ONLY)**
diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md
index e8801879018..4a7a972596f 100644
--- a/doc/administration/auth/ldap/index.md
+++ b/doc/administration/auth/ldap/index.md
@@ -1,5 +1,8 @@
---
type: reference
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# General LDAP Setup
diff --git a/doc/administration/auth/ldap/ldap-troubleshooting.md b/doc/administration/auth/ldap/ldap-troubleshooting.md
index e3a45b3e3ef..909802b5dec 100644
--- a/doc/administration/auth/ldap/ldap-troubleshooting.md
+++ b/doc/administration/auth/ldap/ldap-troubleshooting.md
@@ -1,3 +1,10 @@
+---
+type: reference
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# LDAP Troubleshooting for Administrators
## Common Problems & Workflows
diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md
index 7a808636e94..c3875b39ef1 100644
--- a/doc/administration/auth/oidc.md
+++ b/doc/administration/auth/oidc.md
@@ -1,5 +1,8 @@
---
type: reference
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# OpenID Connect OmniAuth provider
diff --git a/doc/administration/auth/okta.md b/doc/administration/auth/okta.md
index e5139f3fe31..f7ab60ab56b 100644
--- a/doc/administration/auth/okta.md
+++ b/doc/administration/auth/okta.md
@@ -1,5 +1,8 @@
---
type: reference
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Okta SSO provider
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index beca41a14bc..a6de5e12270 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -435,6 +435,16 @@ storage:
NOTE: **Note:**
`your-s3-bucket` should only be the name of a bucket that exists, and can't include subdirectories.
+**Migrate without downtime**
+
+To migrate the data to AWS S3 without downtime:
+
+1. To reduce the amount of data to be migrated, run the [garbage collection tool without downtime](#performing-garbage-collection-without-downtime). Part of this process sets the registry to `read-only`.
+1. Copy the data to your AWS S3 bucket, for example with [AWS CLI's `cp`](https://docs.aws.amazon.com/cli/latest/reference/s3/cp.html) command.
+1. Configure your registry to use the S3 bucket for storage.
+1. Put the registry back to `read-write`.
+1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
### Disable redirect for storage driver
By default, users accessing a registry configured with a remote backend are redirected to the default backend for the storage driver. For example, registries can be configured using the `s3` storage driver, which redirects requests to a remote S3 bucket to alleviate load on the GitLab server.
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index e0cbd08f792..41c0428485f 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -74,8 +74,7 @@ endpoint, set the `with_merge_status_recheck` parameter to `true` in the query.
NOTE: **Note:**
[Starting in GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/29984),
-when `async_merge_request_check_mergeability` feature flag is enabled, the
-mergeability (`merge_status`) of each merge request will be checked
+the mergeability (`merge_status`) of each merge request will be checked
asynchronously when a request is made to this endpoint. Poll this API endpoint
to get updated status. This affects the `has_conflicts` property as it is
dependent on the `merge_status`. It'll return `false` unless `merge_status` is
@@ -555,8 +554,7 @@ Parameters:
NOTE: **Note:**
[Starting in GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/29984),
-when `async_merge_request_check_mergeability` feature flag is enabled, the
-mergeability (`merge_status`) of a merge request will be checked
+the mergeability (`merge_status`) of a merge request will be checked
asynchronously when a request is made to this endpoint. Poll this API endpoint
to get updated status. This affects the `has_conflicts` property as it is
dependent on the `merge_status`. It'll return `false` unless `merge_status` is
diff --git a/doc/ci/variables/img/ci_job_stage_output_example.png b/doc/ci/variables/img/ci_job_stage_output_example.png
index e333da57121..2344b19d9b3 100644
--- a/doc/ci/variables/img/ci_job_stage_output_example.png
+++ b/doc/ci/variables/img/ci_job_stage_output_example.png
Binary files differ
diff --git a/doc/ci/variables/img/inherited_group_variables_v12_5.png b/doc/ci/variables/img/inherited_group_variables_v12_5.png
index a13ba711083..cce024cfab8 100644
--- a/doc/ci/variables/img/inherited_group_variables_v12_5.png
+++ b/doc/ci/variables/img/inherited_group_variables_v12_5.png
Binary files differ
diff --git a/doc/ci/variables/img/override_value_via_manual_pipeline_output.png b/doc/ci/variables/img/override_value_via_manual_pipeline_output.png
index 8a13bb3849e..2d4c4d24520 100644
--- a/doc/ci/variables/img/override_value_via_manual_pipeline_output.png
+++ b/doc/ci/variables/img/override_value_via_manual_pipeline_output.png
Binary files differ
diff --git a/doc/ci/variables/img/override_variable_manual_pipeline.png b/doc/ci/variables/img/override_variable_manual_pipeline.png
index de768105aec..2b242466297 100644
--- a/doc/ci/variables/img/override_variable_manual_pipeline.png
+++ b/doc/ci/variables/img/override_variable_manual_pipeline.png
Binary files differ
diff --git a/doc/development/github_importer.md b/doc/development/github_importer.md
index 5d37d2f119f..5a490737f37 100644
--- a/doc/development/github_importer.md
+++ b/doc/development/github_importer.md
@@ -121,12 +121,12 @@ also reduce pressure on the system as a whole.
## Refreshing import JIDs
-GitLab includes a worker called `StuckImportJobsWorker` that will periodically
-run and mark project imports as failed if they have been running for more than
-15 hours. For GitHub projects, this poses a bit of a problem: importing large
-projects could take several hours depending on how often we hit the GitHub rate
-limit (more on this below), but we don't want `StuckImportJobsWorker` to mark
-our import as failed because of this.
+GitLab includes a worker called `Gitlab::Import::StuckProjectImportJobsWorker`
+that will periodically run and mark project imports as failed if they have been
+running for more than 15 hours. For GitHub projects, this poses a bit of a
+problem: importing large projects could take several hours depending on how
+often we hit the GitHub rate limit (more on this below), but we don't want
+`Gitlab::Import::StuckProjectImportJobsWorker` to mark our import as failed because of this.
To prevent this from happening we periodically refresh the expiration time of
the import process. This works by storing the JID of the import job in the
diff --git a/doc/development/import_export.md b/doc/development/import_export.md
index 8daf4924f0f..dca3cd503ca 100644
--- a/doc/development/import_export.md
+++ b/doc/development/import_export.md
@@ -44,19 +44,34 @@ WARN: Work still in progress <struct with JID>
### Timeouts
-Timeout errors occur due to the `StuckImportJobsWorker` marking the process as failed:
+Timeout errors occur due to the `Gitlab::Import::StuckProjectImportJobsWorker` marking the process as failed:
```ruby
-class StuckImportJobsWorker
- include ApplicationWorker
- include CronjobQueue
-
- IMPORT_JOBS_EXPIRATION = 15.hours.to_i
+module Gitlab
+ module Import
+ class StuckProjectImportJobsWorker
+ include Gitlab::Import::StuckImportJob
+ # ...
+ end
+ end
+end
- def perform
- imports_without_jid_count = mark_imports_without_jid_as_failed!
- imports_with_jid_count = mark_imports_with_jid_as_failed!
- ...
+module Gitlab
+ module Import
+ module StuckImportJob
+ # ...
+ IMPORT_JOBS_EXPIRATION = 15.hours.to_i
+ # ...
+ def perform
+ stuck_imports_without_jid_count = mark_imports_without_jid_as_failed!
+ stuck_imports_with_jid_count = mark_imports_with_jid_as_failed!
+
+ track_metrics(stuck_imports_with_jid_count, stuck_imports_without_jid_count)
+ end
+ # ...
+ end
+ end
+end
```
```shell
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 1c0cf82f29f..b92be0a0076 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -25,6 +25,8 @@ and GitLab does the rest, improving your productivity and efficiency.
For an introduction to Auto DevOps, watch [AutoDevOps in GitLab 11.0](https://youtu.be/0Tc0YYBxqi4).
+For requirements, see [Requirements for Auto DevOps](requirements.md) for more information.
+
## Enabled by default
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41729) in GitLab 11.3.
@@ -54,7 +56,7 @@ configuring a cluster on GKE. After configuring the provider, you can follow
the steps in the [quick start guide](quick_start_guide.md) to get started.
In [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/208132) and later, it is
-possible to leverage Auto DevOps to deploy to [AWS ECS](#aws-ecs).
+possible to leverage Auto DevOps to deploy to [AWS ECS](requirements.md#auto-devops-requirements-for-amazon-ecs).
## Comparison to application platforms and PaaS
@@ -111,136 +113,6 @@ NOTE: **Note**
Kubernetes clusters can [be used without](../../user/project/clusters/index.md)
Auto DevOps.
-## Requirements
-
-### Kubernetes
-
-To make full use of Auto DevOps with Kubernetes, you need:
-
-- **Kubernetes** (for [Auto Review Apps](stages.md#auto-review-apps),
- [Auto Deploy](stages.md#auto-deploy), and [Auto Monitoring](stages.md#auto-monitoring))
-
- To enable deployments, you need:
-
- 1. A [Kubernetes 1.12+ cluster](../../user/project/clusters/index.md) for your
- project. The easiest way is to create a
- [new cluster using the GitLab UI](../../user/project/clusters/add_remove_clusters.md#create-new-cluster).
- For Kubernetes 1.16+ clusters, you must perform additional configuration for
- [Auto Deploy for Kubernetes 1.16+](stages.md#kubernetes-116).
- 1. NGINX Ingress. You can deploy it to your Kubernetes cluster by installing
- the [GitLab-managed app for Ingress](../../user/clusters/applications.md#ingress),
- after configuring GitLab's Kubernetes integration in the previous step.
-
- Alternatively, you can use the
- [`nginx-ingress`](https://github.com/helm/charts/tree/master/stable/nginx-ingress)
- Helm chart to install Ingress manually.
-
- NOTE: **Note:**
- If you use your own Ingress instead of the one provided by GitLab's managed
- apps, ensure you're running at least version 0.9.0 of NGINX Ingress and
- [enable Prometheus metrics](https://github.com/helm/charts/tree/master/stable/nginx-ingress#prometheus-metrics)
- for the response metrics to appear. You must also
- [annotate](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)
- the NGINX Ingress deployment to be scraped by Prometheus using
- `prometheus.io/scrape: "true"` and `prometheus.io/port: "10254"`.
-
-- **Base domain** (for [Auto Review Apps](stages.md#auto-review-apps),
- [Auto Deploy](stages.md#auto-deploy), and [Auto Monitoring](stages.md#auto-monitoring))
-
- You need a domain configured with wildcard DNS, which all of your Auto DevOps
- applications will use. If you're using the
- [GitLab-managed app for Ingress](../../user/clusters/applications.md#ingress),
- the URL endpoint is automatically configured for you.
-
- You must also [specify the Auto DevOps base domain](#auto-devops-base-domain).
-
-- **GitLab Runner** (for all stages)
-
- Your Runner must be configured to run Docker, usually with either the
- [Docker](https://docs.gitlab.com/runner/executors/docker.html)
- or [Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html) executors, with
- [privileged mode enabled](https://docs.gitlab.com/runner/executors/docker.html#use-docker-in-docker-with-privileged-mode).
- The Runners don't need to be installed in the Kubernetes cluster, but the
- Kubernetes executor is easy to use and automatically autoscales.
- You can configure Docker-based Runners to autoscale as well, using
- [Docker Machine](https://docs.gitlab.com/runner/install/autoscaling.html).
-
- If you've configured GitLab's Kubernetes integration in the first step, you
- can deploy it to your cluster by installing the
- [GitLab-managed app for GitLab Runner](../../user/clusters/applications.md#gitlab-runner).
-
- Runners should be registered as [shared Runners](../../ci/runners/README.md#registering-a-shared-runner)
- for the entire GitLab instance, or [specific Runners](../../ci/runners/README.md#registering-a-specific-runner)
- that are assigned to specific projects (the default if you've installed the
- GitLab Runner managed application).
-
-- **Prometheus** (for [Auto Monitoring](stages.md#auto-monitoring))
-
- To enable Auto Monitoring, you need Prometheus installed either inside or
- outside your cluster, and configured to scrape your Kubernetes cluster.
- If you've configured GitLab's Kubernetes integration, you can deploy it to
- your cluster by installing the
- [GitLab-managed app for Prometheus](../../user/clusters/applications.md#prometheus).
-
- The [Prometheus service](../../user/project/integrations/prometheus.md)
- integration must be enabled for the project, or enabled as a
- [default service template](../../user/project/integrations/services_templates.md)
- for the entire GitLab installation.
-
- To get response metrics (in addition to system metrics), you must
- [configure Prometheus to monitor NGINX](../../user/project/integrations/prometheus_library/nginx_ingress.md#configuring-nginx-ingress-monitoring).
-
-- **cert-manager** (optional, for TLS/HTTPS)
-
- To enable HTTPS endpoints for your application, you must install cert-manager,
- a native Kubernetes certificate management controller that helps with issuing
- certificates. Installing cert-manager on your cluster issues a
- [Let’s Encrypt](https://letsencrypt.org/) certificate and ensures the
- certificates are valid and up-to-date. If you've configured GitLab's Kubernetes
- integration, you can deploy it to your cluster by installing the
- [GitLab-managed app for cert-manager](../../user/clusters/applications.md#cert-manager).
-
-If you don't have Kubernetes or Prometheus installed, then
-[Auto Review Apps](stages.md#auto-review-apps),
-[Auto Deploy](stages.md#auto-deploy), and [Auto Monitoring](stages.md#auto-monitoring)
-are skipped.
-
-After all requirements are met, you can [enable Auto DevOps](#enablingdisabling-auto-devops).
-
-### AWS ECS
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208132) in GitLab 13.0.
-
-You can choose to target [AWS ECS](../../ci/cloud_deployment/index.md) as a deployment platform instead of using Kubernetes.
-
-To get started on Auto DevOps to ECS, you'll have to add a specific Environment
-Variable. To do so, follow these steps:
-
-1. In your project, go to **Settings > CI / CD** and expand the **Variables**
- section.
-
-1. Specify which AWS platform to target during the Auto DevOps deployment
- by adding the `AUTO_DEVOPS_PLATFORM_TARGET` variable.
-
-1. Give this variable the value `ECS` before saving it.
-
-When you trigger a pipeline, if you have AutoDev Ops enabled and if you have correctly
-[entered AWS credentials as environment variables](../../ci/cloud_deployment/index.md#deploy-your-application-to-the-aws-elastic-container-service-ecs),
-your application will be deployed to AWS ECS.
-
-NOTE: **Note:**
-If you have both a valid `AUTO_DEVOPS_PLATFORM_TARGET` variable and a Kubernetes cluster tied to your project,
-only the deployment to Kubernetes will run.
-
-CAUTION: **Warning:**
-Setting the `AUTO_DEVOPS_PLATFORM_TARGET` variable to `ECS` will trigger jobs
-defined in the [`Jobs/Deploy/ECS.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml).
-However, it is not recommended to [include](../../ci/yaml/README.md#includetemplate)
-it on its own. This template is designed to be used with Auto DevOps only. It may change
-unexpectedly causing your pipeline to fail if included on its own. Also, the job
-names within this template may also change. Do not override these jobs names in your
-own pipeline, as the override will stop working when the name changes.
-
## Auto DevOps base domain
The Auto DevOps base domain is required to use
diff --git a/doc/topics/autodevops/requirements.md b/doc/topics/autodevops/requirements.md
new file mode 100644
index 00000000000..1239fbc4b1a
--- /dev/null
+++ b/doc/topics/autodevops/requirements.md
@@ -0,0 +1,134 @@
+# Requirements for Auto DevOps
+
+You can set up Auto DevOps for [Kubernetes](#auto-devops-requirements-for-kubernetes)
+or [Amazon Elastic Container Service (ECS)](#auto-devops-requirements-for-amazon-ecs).
+For more information about Auto DevOps, see [the main Auto DevOps page](index.md)
+or the [quick start guide](quick_start_guide.md).
+
+## Auto DevOps requirements for Kubernetes
+
+To make full use of Auto DevOps with Kubernetes, you need:
+
+- **Kubernetes** (for [Auto Review Apps](stages.md#auto-review-apps),
+ [Auto Deploy](stages.md#auto-deploy), and [Auto Monitoring](stages.md#auto-monitoring))
+
+ To enable deployments, you need:
+
+ 1. A [Kubernetes 1.12+ cluster](../../user/project/clusters/index.md) for your
+ project. The easiest way is to create a
+ [new cluster using the GitLab UI](../../user/project/clusters/add_remove_clusters.md#create-new-cluster).
+ For Kubernetes 1.16+ clusters, you must perform additional configuration for
+ [Auto Deploy for Kubernetes 1.16+](stages.md#kubernetes-116).
+ 1. NGINX Ingress. You can deploy it to your Kubernetes cluster by installing
+ the [GitLab-managed app for Ingress](../../user/clusters/applications.md#ingress),
+ after configuring GitLab's Kubernetes integration in the previous step.
+
+ Alternatively, you can use the
+ [`nginx-ingress`](https://github.com/helm/charts/tree/master/stable/nginx-ingress)
+ Helm chart to install Ingress manually.
+
+ NOTE: **Note:**
+ If you use your own Ingress instead of the one provided by GitLab's managed
+ apps, ensure you're running at least version 0.9.0 of NGINX Ingress and
+ [enable Prometheus metrics](https://github.com/helm/charts/tree/master/stable/nginx-ingress#prometheus-metrics)
+ for the response metrics to appear. You must also
+ [annotate](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)
+ the NGINX Ingress deployment to be scraped by Prometheus using
+ `prometheus.io/scrape: "true"` and `prometheus.io/port: "10254"`.
+
+- **Base domain** (for [Auto Review Apps](stages.md#auto-review-apps),
+ [Auto Deploy](stages.md#auto-deploy), and [Auto Monitoring](stages.md#auto-monitoring))
+
+ You need a domain configured with wildcard DNS, which all of your Auto DevOps
+ applications will use. If you're using the
+ [GitLab-managed app for Ingress](../../user/clusters/applications.md#ingress),
+ the URL endpoint is automatically configured for you.
+
+ You must also [specify the Auto DevOps base domain](index.md#auto-devops-base-domain).
+
+- **GitLab Runner** (for all stages)
+
+ Your Runner must be configured to run Docker, usually with either the
+ [Docker](https://docs.gitlab.com/runner/executors/docker.html)
+ or [Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html) executors, with
+ [privileged mode enabled](https://docs.gitlab.com/runner/executors/docker.html#use-docker-in-docker-with-privileged-mode).
+ The Runners don't need to be installed in the Kubernetes cluster, but the
+ Kubernetes executor is easy to use and automatically autoscales.
+ You can configure Docker-based Runners to autoscale as well, using
+ [Docker Machine](https://docs.gitlab.com/runner/install/autoscaling.html).
+
+ If you've configured GitLab's Kubernetes integration in the first step, you
+ can deploy it to your cluster by installing the
+ [GitLab-managed app for GitLab Runner](../../user/clusters/applications.md#gitlab-runner).
+
+ Runners should be registered as [shared Runners](../../ci/runners/README.md#registering-a-shared-runner)
+ for the entire GitLab instance, or [specific Runners](../../ci/runners/README.md#registering-a-specific-runner)
+ that are assigned to specific projects (the default if you've installed the
+ GitLab Runner managed application).
+
+- **Prometheus** (for [Auto Monitoring](stages.md#auto-monitoring))
+
+ To enable Auto Monitoring, you need Prometheus installed either inside or
+ outside your cluster, and configured to scrape your Kubernetes cluster.
+ If you've configured GitLab's Kubernetes integration, you can deploy it to
+ your cluster by installing the
+ [GitLab-managed app for Prometheus](../../user/clusters/applications.md#prometheus).
+
+ The [Prometheus service](../../user/project/integrations/prometheus.md)
+ integration must be enabled for the project, or enabled as a
+ [default service template](../../user/project/integrations/services_templates.md)
+ for the entire GitLab installation.
+
+ To get response metrics (in addition to system metrics), you must
+ [configure Prometheus to monitor NGINX](../../user/project/integrations/prometheus_library/nginx_ingress.md#configuring-nginx-ingress-monitoring).
+
+- **cert-manager** (optional, for TLS/HTTPS)
+
+ To enable HTTPS endpoints for your application, you must install cert-manager,
+ a native Kubernetes certificate management controller that helps with issuing
+ certificates. Installing cert-manager on your cluster issues a
+ [Let’s Encrypt](https://letsencrypt.org/) certificate and ensures the
+ certificates are valid and up-to-date. If you've configured GitLab's Kubernetes
+ integration, you can deploy it to your cluster by installing the
+ [GitLab-managed app for cert-manager](../../user/clusters/applications.md#cert-manager).
+
+If you don't have Kubernetes or Prometheus installed, then
+[Auto Review Apps](stages.md#auto-review-apps),
+[Auto Deploy](stages.md#auto-deploy), and [Auto Monitoring](stages.md#auto-monitoring)
+are skipped.
+
+After all requirements are met, you can [enable Auto DevOps](index.md#enablingdisabling-auto-devops).
+
+## Auto DevOps requirements for Amazon ECS
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208132) in GitLab 13.0.
+
+You can choose to target [Amazon Elastic Container Service (ECS)](../../ci/cloud_deployment/index.md) as a deployment platform instead of using Kubernetes.
+
+To get started on Auto DevOps to Amazon ECS, you'll have to add a specific Environment
+Variable. To do so, follow these steps:
+
+1. In your project, go to **Settings > CI / CD** and expand the **Variables**
+ section.
+
+1. Specify which AWS platform to target during the Auto DevOps deployment
+ by adding the `AUTO_DEVOPS_PLATFORM_TARGET` variable.
+
+1. Give this variable the value `ECS` before saving it.
+
+When you trigger a pipeline, if Auto DevOps is enabled and if you've correctly
+[entered AWS credentials as environment variables](../../ci/cloud_deployment/index.md#deploy-your-application-to-the-aws-elastic-container-service-ecs),
+your application will be deployed to Amazon ECS.
+
+NOTE: **Note:**
+If you have both a valid `AUTO_DEVOPS_PLATFORM_TARGET` variable and a Kubernetes cluster tied to your project,
+only the deployment to Kubernetes will run.
+
+CAUTION: **Warning:**
+Setting the `AUTO_DEVOPS_PLATFORM_TARGET` variable to `ECS` will trigger jobs
+defined in the [`Jobs/Deploy/ECS.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml).
+However, it's not recommended to [include](../../ci/yaml/README.md#includetemplate)
+it on its own. This template is designed to be used with Auto DevOps only. It may change
+unexpectedly causing your pipeline to fail if included on its own. Also, the job
+names within this template may also change. Don't override these jobs' names in your
+own pipeline, as the override will stop working when the name changes.
diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md
index 61023449e3b..8dc3acdc53e 100644
--- a/doc/topics/autodevops/stages.md
+++ b/doc/topics/autodevops/stages.md
@@ -196,7 +196,7 @@ see the documentation.
## Auto Review Apps
This is an optional step, since many projects don't have a Kubernetes cluster
-available. If the [requirements](index.md#requirements) are not met, the job is
+available. If the [requirements](requirements.md) are not met, the job is
silently skipped.
[Review Apps](../../ci/review_apps/index.md) are temporary application environments based on the
@@ -297,7 +297,7 @@ Any performance differences between the source and target branches are also
## Auto Deploy
This is an optional step, since many projects don't have a Kubernetes cluster
-available. If the [requirements](index.md#requirements) are not met, the job is skipped.
+available. If the [requirements](requirements.md) are not met, the job is skipped.
After a branch or merge request is merged into the project's default branch (usually
`master`), Auto Deploy deploys the application to a `production` environment in
@@ -598,7 +598,7 @@ GitLab provides some initial alerts for you after you install Prometheus:
To use Auto Monitoring:
-1. [Install and configure the requirements](index.md#requirements).
+1. [Install and configure the Auto DevOps requirements](requirements.md).
1. [Enable Auto DevOps](index.md#enablingdisabling-auto-devops), if you haven't done already.
1. Navigate to your project's **{rocket}** **CI/CD > Pipelines** and click **Run Pipeline**.
1. After the pipeline finishes successfully, open the
diff --git a/doc/user/analytics/code_review_analytics.md b/doc/user/analytics/code_review_analytics.md
index 26187a614cc..8c4c54153bb 100644
--- a/doc/user/analytics/code_review_analytics.md
+++ b/doc/user/analytics/code_review_analytics.md
@@ -2,8 +2,7 @@
description: "Learn how long your open merge requests have spent in code review, and what distinguishes the longest-running." # Up to ~200 chars long. They will be displayed in Google Search snippets. It may help to write the page intro first, and then reuse it here.
stage: Manage
group: Analytics
-To determine the technical writer assigned to the Stage/Group associated with this page, see:
- https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md
index 492b661b0dd..18f6d79ef23 100644
--- a/doc/user/analytics/index.md
+++ b/doc/user/analytics/index.md
@@ -1,8 +1,7 @@
---
stage: Manage
group: Analytics
-To determine the technical writer assigned to the Stage/Group associated with this page, see:
- https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Analytics
diff --git a/doc/user/analytics/productivity_analytics.md b/doc/user/analytics/productivity_analytics.md
index ef24ac71874..d6efa624aad 100644
--- a/doc/user/analytics/productivity_analytics.md
+++ b/doc/user/analytics/productivity_analytics.md
@@ -1,8 +1,7 @@
---
stage: Manage
group: Analytics
-To determine the technical writer assigned to the Stage/Group associated with this page, see:
- https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Productivity Analytics **(PREMIUM)**
diff --git a/doc/user/analytics/repository_analytics.md b/doc/user/analytics/repository_analytics.md
index 17032990b09..1c810e3581a 100644
--- a/doc/user/analytics/repository_analytics.md
+++ b/doc/user/analytics/repository_analytics.md
@@ -1,8 +1,7 @@
---
stage: Manage
group: Analytics
-To determine the technical writer assigned to the Stage/Group associated with this page, see:
- https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Repository Analytics
diff --git a/doc/user/analytics/value_stream_analytics.md b/doc/user/analytics/value_stream_analytics.md
index ca10a869558..0efe28ac5f7 100644
--- a/doc/user/analytics/value_stream_analytics.md
+++ b/doc/user/analytics/value_stream_analytics.md
@@ -1,8 +1,7 @@
---
stage: Manage
group: Analytics
-To determine the technical writer assigned to the Stage/Group associated with this page, see:
- https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Value Stream Analytics
diff --git a/doc/user/compliance/compliance_dashboard/index.md b/doc/user/compliance/compliance_dashboard/index.md
index c1b79043319..08a26a45b17 100644
--- a/doc/user/compliance/compliance_dashboard/index.md
+++ b/doc/user/compliance/compliance_dashboard/index.md
@@ -1,5 +1,8 @@
---
type: reference, howto
+stage: Manage
+group: Compliance
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Compliance Dashboard **(ULTIMATE)**
diff --git a/doc/user/compliance/index.md b/doc/user/compliance/index.md
index fd4af74e086..d0e73b47358 100644
--- a/doc/user/compliance/index.md
+++ b/doc/user/compliance/index.md
@@ -1,3 +1,10 @@
+---
+type: reference
+stage: Manage
+group: Compliance
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Compliance **(ULTIMATE)**
The compliance tools provided by GitLab let you keep an eye on various aspects of your project. The
diff --git a/doc/user/group/contribution_analytics/index.md b/doc/user/group/contribution_analytics/index.md
index 70e63f551cb..bcc6d958427 100644
--- a/doc/user/group/contribution_analytics/index.md
+++ b/doc/user/group/contribution_analytics/index.md
@@ -2,8 +2,7 @@
type: reference
stage: Manage
group: Analytics
-To determine the technical writer assigned to the Stage/Group associated with this page, see:
- https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Contribution Analytics **(STARTER)**
diff --git a/doc/user/group/custom_project_templates.md b/doc/user/group/custom_project_templates.md
index 42e532ef500..ebeacda24c6 100644
--- a/doc/user/group/custom_project_templates.md
+++ b/doc/user/group/custom_project_templates.md
@@ -1,5 +1,8 @@
---
type: reference
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Custom group-level project templates **(PREMIUM)**
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 3cd24546a30..324c912b2be 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -1,5 +1,8 @@
---
type: reference, howto
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Groups
diff --git a/doc/user/group/insights/index.md b/doc/user/group/insights/index.md
index cffbc013e66..dd1f8914392 100644
--- a/doc/user/group/insights/index.md
+++ b/doc/user/group/insights/index.md
@@ -2,8 +2,7 @@
type: reference, howto
stage: Manage
group: Analytics
-To determine the technical writer assigned to the Stage/Group associated with this page, see:
- https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Insights **(ULTIMATE)**
diff --git a/doc/user/group/issues_analytics/index.md b/doc/user/group/issues_analytics/index.md
index 91bfa4e457f..01cee3d09b8 100644
--- a/doc/user/group/issues_analytics/index.md
+++ b/doc/user/group/issues_analytics/index.md
@@ -2,8 +2,7 @@
type: reference
stage: Manage
group: Analytics
-To determine the technical writer assigned to the Stage/Group associated with this page, see:
- https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Issues Analytics **(PREMIUM)**
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 95488541415..81684038dc2 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -1,5 +1,8 @@
---
type: reference, howto
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# SAML SSO for GitLab.com groups **(SILVER ONLY)**
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index 93e2a07a4ca..a891962b38e 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -1,5 +1,8 @@
---
type: howto, reference
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# SCIM provisioning using SAML SSO for GitLab.com groups **(SILVER ONLY)**
diff --git a/doc/user/group/settings/import_export.md b/doc/user/group/settings/import_export.md
index 056ce6e9803..f24cbbccb1b 100644
--- a/doc/user/group/settings/import_export.md
+++ b/doc/user/group/settings/import_export.md
@@ -1,3 +1,9 @@
+---
+type: reference
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
# Group Import/Export
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2888) in GitLab 13.0 as an experimental feature. May change in future releases.
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index 271f11be0a4..8779b3ea9bd 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -554,6 +554,36 @@ run the policy may get backed up or fail completely. It is recommended you only
policies for projects that were created before GitLab 12.8 if you are confident the amount of tags
being cleaned up will be minimal.
+### Regex patterns
+
+The patterns that define which tags should be preserved or removed are defined using regular expressions, both for the UI and the API.
+
+Examples:
+
+- Match all tags:
+
+ ```plaintext
+ .*
+ ```
+
+- Match tags that start with `v`:
+
+ ```plaintext
+ v.+
+ ```
+
+- Match tags that contain `master`:
+
+ ```plaintext
+ master
+ ```
+
+- Match tags that either start with `v`, contain `master`, or contain `release`:
+
+ ```plaintext
+ (?:v.+|master|release)
+ ```
+
## Limitations
- Moving or renaming existing Container Registry repositories is not supported
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 10c63f0dfa1..49cf0fea789 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -295,7 +295,7 @@ project and should only have access to that project.
External users:
- Cannot create groups, projects, or personal snippets.
-- Can only access projects to which they are explicitly granted access,
+- Can only access public projects and projects to which they are explicitly granted access,
thus hiding all other internal or private ones from them (like being
logged out).
diff --git a/doc/user/profile/account/create_accounts.md b/doc/user/profile/account/create_accounts.md
index 2110bd0bc92..26c2c1bed89 100644
--- a/doc/user/profile/account/create_accounts.md
+++ b/doc/user/profile/account/create_accounts.md
@@ -1,5 +1,8 @@
---
type: reference
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Creating users **(CORE ONLY)**
diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md
index c9193c6d94c..3c6f2989091 100644
--- a/doc/user/profile/account/delete_account.md
+++ b/doc/user/profile/account/delete_account.md
@@ -1,5 +1,8 @@
---
type: howto
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Deleting a User account
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index 18f9fc59d7a..bfcaeaf6a15 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -1,5 +1,8 @@
---
type: howto
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Two-Factor Authentication
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index 61d0a8e460a..663a2888ee7 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -1,5 +1,8 @@
---
type: index, howto
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# User account
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index 377b6cd393b..e2c3dc74cf1 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -1,5 +1,8 @@
---
type: concepts, howto
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Personal access tokens
diff --git a/doc/user/profile/unknown_sign_in_notification.md b/doc/user/profile/unknown_sign_in_notification.md
index aa3efaa38bb..200358bb050 100644
--- a/doc/user/profile/unknown_sign_in_notification.md
+++ b/doc/user/profile/unknown_sign_in_notification.md
@@ -1,3 +1,10 @@
+---
+type: concepts, howto
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Email notification for unknown sign-ins
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27211) in GitLab 13.0.
diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md
index 50233ff1d37..0a613ff918b 100644
--- a/doc/user/project/deploy_boards.md
+++ b/doc/user/project/deploy_boards.md
@@ -41,6 +41,10 @@ knowledge. In particular, you should be familiar with:
- [Kubernetes namespaces](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)
- [Kubernetes canary deployments](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments)
+NOTE: **Note:**
+Apps that consist of multiple deployments are shown as duplicates on the deploy board.
+Follow [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/8463) for details.
+
## Use cases
Since the Deploy Board is a visual representation of the Kubernetes pods for a
diff --git a/doc/user/project/import/bitbucket.md b/doc/user/project/import/bitbucket.md
index 56717858b53..56266718d12 100644
--- a/doc/user/project/import/bitbucket.md
+++ b/doc/user/project/import/bitbucket.md
@@ -1,3 +1,10 @@
+---
+type: reference, howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Import your project from Bitbucket Cloud to GitLab
NOTE: **Note:**
diff --git a/doc/user/project/import/bitbucket_server.md b/doc/user/project/import/bitbucket_server.md
index 55df2d7294d..f0e730564d8 100644
--- a/doc/user/project/import/bitbucket_server.md
+++ b/doc/user/project/import/bitbucket_server.md
@@ -1,3 +1,10 @@
+---
+type: reference, howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Import your project from Bitbucket Server to GitLab
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20164) in GitLab 11.2.
diff --git a/doc/user/project/import/clearcase.md b/doc/user/project/import/clearcase.md
index 89a9f7da852..173ba71b167 100644
--- a/doc/user/project/import/clearcase.md
+++ b/doc/user/project/import/clearcase.md
@@ -1,3 +1,10 @@
+---
+type: reference, howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Migrating from ClearCase
[ClearCase](https://www.ibm.com/us-en/marketplace/rational-clearcase) is a set of
diff --git a/doc/user/project/import/cvs.md b/doc/user/project/import/cvs.md
index 3b2404912f7..d2e79458526 100644
--- a/doc/user/project/import/cvs.md
+++ b/doc/user/project/import/cvs.md
@@ -1,3 +1,10 @@
+---
+type: reference, howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Migrating from CVS
[CVS](https://savannah.nongnu.org/projects/cvs) is an old centralized version
diff --git a/doc/user/project/import/fogbugz.md b/doc/user/project/import/fogbugz.md
index 13409c93929..149b5d1913c 100644
--- a/doc/user/project/import/fogbugz.md
+++ b/doc/user/project/import/fogbugz.md
@@ -1,3 +1,10 @@
+---
+type: reference, howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Import your project from FogBugz to GitLab
It only takes a few simple steps to import your project from FogBugz.
diff --git a/doc/user/project/import/gemnasium.md b/doc/user/project/import/gemnasium.md
index cf9ac15f5ac..0d6e059f1cf 100644
--- a/doc/user/project/import/gemnasium.md
+++ b/doc/user/project/import/gemnasium.md
@@ -1,3 +1,10 @@
+---
+type: reference, howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Gemnasium **(ULTIMATE)**
This guide describes how to migrate from Gemnasium.com to your own GitLab
diff --git a/doc/user/project/import/gitea.md b/doc/user/project/import/gitea.md
index 94ab9d9195b..543fffd33d6 100644
--- a/doc/user/project/import/gitea.md
+++ b/doc/user/project/import/gitea.md
@@ -1,3 +1,10 @@
+---
+type: reference, howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Import your project from Gitea to GitLab
Import your projects from Gitea to GitLab with minimal effort.
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index 4c213f21920..b7754e60837 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -1,3 +1,10 @@
+---
+type: reference, howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Import your project from GitHub to GitLab
Using the importer, you can import your GitHub repositories to GitLab.com or to
diff --git a/doc/user/project/import/gitlab_com.md b/doc/user/project/import/gitlab_com.md
index 2f87f257754..b9aea629e85 100644
--- a/doc/user/project/import/gitlab_com.md
+++ b/doc/user/project/import/gitlab_com.md
@@ -1,3 +1,10 @@
+---
+type: reference, howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Project importing from GitLab.com to your private GitLab instance
You can import your existing GitLab.com projects to your GitLab instance, but keep in
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index 4f2cf2c5934..86b671c8371 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -1,3 +1,10 @@
+---
+type: reference, howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Migrating projects to a GitLab instance
1. [From Bitbucket Cloud](bitbucket.md)
diff --git a/doc/user/project/import/manifest.md b/doc/user/project/import/manifest.md
index 48dfa0a8987..0374e0acf9a 100644
--- a/doc/user/project/import/manifest.md
+++ b/doc/user/project/import/manifest.md
@@ -1,3 +1,10 @@
+---
+type: howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Import multiple repositories by uploading a manifest file
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/28811) in GitLab 11.2.
diff --git a/doc/user/project/import/perforce.md b/doc/user/project/import/perforce.md
index cbcef7a2fb0..dbc1c491493 100644
--- a/doc/user/project/import/perforce.md
+++ b/doc/user/project/import/perforce.md
@@ -1,3 +1,10 @@
+---
+type: howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Migrating from Perforce Helix
[Perforce Helix](https://www.perforce.com/) provides a set of tools which also
diff --git a/doc/user/project/import/phabricator.md b/doc/user/project/import/phabricator.md
index d8b9d1857f9..a19068199db 100644
--- a/doc/user/project/import/phabricator.md
+++ b/doc/user/project/import/phabricator.md
@@ -1,3 +1,10 @@
+---
+type: howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Import Phabricator tasks into a GitLab project
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/60562) in GitLab 12.0.
diff --git a/doc/user/project/import/repo_by_url.md b/doc/user/project/import/repo_by_url.md
index c20b1cb7f5e..9b5e43aae79 100644
--- a/doc/user/project/import/repo_by_url.md
+++ b/doc/user/project/import/repo_by_url.md
@@ -1,3 +1,10 @@
+---
+type: howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Import project from repo by URL
You can import your existing repositories by providing the Git URL:
diff --git a/doc/user/project/import/svn.md b/doc/user/project/import/svn.md
index cf034aafca9..dfd8be26c90 100644
--- a/doc/user/project/import/svn.md
+++ b/doc/user/project/import/svn.md
@@ -1,3 +1,10 @@
+---
+type: howto
+stage: Manage
+group: Import
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Migrating from SVN to GitLab
Subversion (SVN) is a central version control system (VCS) while
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index d84098b97bf..82dbeb0ff7e 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -185,6 +185,14 @@ them like you would do with every other Git repository.
On the right sidebar, click on **Clone repository** and follow the on-screen
instructions.
+Files that you add to your wiki locally must have one of the following
+supported extensions, depending on the markup language you wish to use,
+otherwise they will not display when pushed to GitLab:
+
+- Markdown extensions: `.mdown`, `.mkd`, `.mkdn`, `.md`, `.markdown`.
+- AsciiDoc extensions: `.adoc`, `.ad`, `.asciidoc`.
+- Other markup extensions: `.textile`, `.rdoc`, `.org`, `.creole`, `.wiki`, `.mediawiki`, `.rst`.
+
## Customizing sidebar
On the project's Wiki page, there is a right side navigation that renders the full Wiki pages list by default, with hierarchy.
diff --git a/lib/gitlab/import/set_async_jid.rb b/lib/gitlab/import/set_async_jid.rb
index 72832f57d0f..527d84477fe 100644
--- a/lib/gitlab/import/set_async_jid.rb
+++ b/lib/gitlab/import/set_async_jid.rb
@@ -2,8 +2,8 @@
# The original import JID is the JID of the RepositoryImportWorker job,
# which will be removed once that job completes. Reusing that JID could
-# result in StuckImportJobsWorker marking the job as stuck before we get
-# to running Stage::ImportRepositoryWorker.
+# result in Gitlab::Import::StuckProjectImportJobsWorker marking the job
+# as stuck before we get to running Stage::ImportRepositoryWorker.
#
# We work around this by setting the JID to a custom generated one, then
# refreshing it in the various stages whenever necessary.
@@ -13,8 +13,7 @@ module Gitlab
def self.set_jid(import_state)
jid = generate_jid(import_state)
- Gitlab::SidekiqStatus
- .set(jid, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION)
+ Gitlab::SidekiqStatus.set(jid, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION)
import_state.update_column(:jid, jid)
end
diff --git a/lib/gitlab/jira_import.rb b/lib/gitlab/jira_import.rb
index f7373a65f88..c7b5317e67b 100644
--- a/lib/gitlab/jira_import.rb
+++ b/lib/gitlab/jira_import.rb
@@ -10,16 +10,18 @@ module Gitlab
ITEMS_MAPPER_CACHE_KEY = 'jira-import/items-mapper/%{project_id}/%{collection_type}/%{jira_isssue_id}'
ALREADY_IMPORTED_ITEMS_CACHE_KEY = 'jira-importer/already-imported/%{project}/%{collection_type}'
- def self.validate_project_settings!(project, user: nil)
+ def self.validate_project_settings!(project, user: nil, configuration_check: true)
if user
raise Projects::ImportService::Error, _('Cannot import because issues are not available in this project.') unless project.feature_available?(:issues, user)
raise Projects::ImportService::Error, _('You do not have permissions to run the import.') unless user.can?(:admin_project, project)
end
+ return unless configuration_check
+
jira_service = project.jira_service
raise Projects::ImportService::Error, _('Jira integration not configured.') unless jira_service&.active?
- raise Projects::ImportService::Error, _('Unable to connect to the Jira instance. Please check your Jira integration configuration.') unless jira_service.test(nil)[:success]
+ raise Projects::ImportService::Error, _('Unable to connect to the Jira instance. Please check your Jira integration configuration.') unless jira_service&.valid_connection?
end
def self.jira_issue_cache_key(project_id, jira_issue_id)
diff --git a/spec/controllers/projects/import/jira_controller_spec.rb b/spec/controllers/projects/import/jira_controller_spec.rb
index 200f7ef812a..b82735a56b3 100644
--- a/spec/controllers/projects/import/jira_controller_spec.rb
+++ b/spec/controllers/projects/import/jira_controller_spec.rb
@@ -9,142 +9,94 @@ RSpec.describe Projects::Import::JiraController do
let_it_be(:project) { create(:project) }
let_it_be(:jira_project_key) { 'Test' }
- context 'with anonymous user' do
- context 'get show' do
- it 'redirects to issues page' do
- get :show, params: { namespace_id: project.namespace, project_id: project }
+ def ensure_correct_config
+ sign_in(user)
+ project.add_maintainer(user)
+ stub_feature_flags(jira_issue_import: true)
+ stub_jira_service_test
+ end
- expect(response).to redirect_to(new_user_session_path)
- end
+ shared_examples 'redirect with error' do |error|
+ it 'redirects to project issues path' do
+ subject
+
+ expect(response).to redirect_to(project_issues_path(project))
end
- context 'post import' do
- it 'redirects to issues page' do
- post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: jira_project_key }
+ it 'renders a correct error' do
+ subject
- expect(response).to redirect_to(new_user_session_path)
- end
+ expect(flash[:notice]).to eq(error)
end
end
- context 'with logged in user' do
- before do
- sign_in(user)
- project.add_maintainer(user)
- stub_jira_service_test
- end
-
- context 'when Jira service is enabled for the project' do
- let_it_be(:jira_service) { create(:jira_service, project: project) }
-
- context 'when user is developer' do
- let_it_be(:dev) { create(:user) }
+ shared_examples 'template with no message' do
+ it 'does not set any message' do
+ subject
- before do
- sign_in(dev)
- project.add_developer(dev)
- end
-
- context 'get show' do
- before do
- get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
- end
+ expect(flash).to be_empty
+ end
- it 'does not query Jira service' do
- expect(project).not_to receive(:jira_service)
- end
+ it 'renders show template' do
+ subject
- it 'renders show template' do
- expect(response).to render_template(:show)
- end
- end
+ expect(response).to render_template(template)
+ end
+ end
- context 'post import' do
- it 'returns 404' do
- post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: jira_project_key }
+ shared_examples 'users without permissions' do
+ context 'with anonymous user' do
+ it 'redirects to new user page' do
+ subject
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
+ expect(response).to redirect_to(new_user_session_path)
end
+ end
- context 'when issues disabled' do
- let_it_be(:disabled_issues_project) { create(:project, :public, :issues_disabled) }
-
- context 'get show' do
- it 'returns 404' do
- get :show, params: { namespace_id: project.namespace.to_param, project_id: disabled_issues_project }
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'post import' do
- it 'returns 404' do
- post :import, params: { namespace_id: disabled_issues_project.namespace, project_id: disabled_issues_project, jira_project_key: jira_project_key }
+ context 'when loged user is a developer' do
+ before do
+ create(:jira_service, project: project)
+ stub_jira_service_test
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
+ sign_in(user)
+ project.add_developer(user)
end
- context 'when running Jira import first time' do
- context 'post import' do
- context 'when Jira project key is empty' do
- it 'redirects back to show with an error' do
- post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: '' }
-
- expect(response).to redirect_to(project_import_jira_path(project))
- expect(flash[:alert]).to eq('No Jira project key has been provided.')
- end
- end
+ it_behaves_like 'redirect with error', 'You do not have permissions to run the import.'
+ end
+ end
- context 'when everything is ok' do
- it 'creates import state' do
- expect(project.latest_jira_import).to be_nil
+ describe 'GET #show' do
+ let(:template) { 'show' }
- post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: jira_project_key }
+ subject { get :show, params: { namespace_id: project.namespace, project_id: project } }
- project.reload
+ it_behaves_like 'users without permissions'
- jira_import = project.latest_jira_import
- expect(project.import_type).to eq 'jira'
- expect(jira_import.status).to eq 'scheduled'
- expect(jira_import.jira_project_key).to eq jira_project_key
- expect(response).to redirect_to(project_import_jira_path(project))
- end
- end
- end
+ context 'jira service configuration' do
+ before do
+ sign_in(user)
+ project.add_maintainer(user)
+ stub_feature_flags(jira_issue_import: true)
end
- context 'when import state is scheduled' do
- let_it_be(:jira_import_state) { create(:jira_import_state, :scheduled, project: project) }
-
- context 'post import' do
- it 'uses the existing import data' do
- post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'New Project' }
-
- expect(flash[:notice]).to eq('Jira import is already running.')
- expect(response).to redirect_to(project_import_jira_path(project))
- end
+ context 'when Jira service is not enabled for the project' do
+ it 'does not query Jira service' do
+ expect(project).not_to receive(:jira_service)
end
- end
- context 'when Jira import ran before' do
- let_it_be(:jira_import_state) { create(:jira_import_state, :finished, project: project, jira_project_key: jira_project_key) }
+ it_behaves_like 'template with no message'
+ end
- context 'post import' do
- it 'uses the existing import data' do
- post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'New Project' }
+ context 'when Jira service is not configured correctly for the project' do
+ let_it_be(:jira_service) { create(:jira_service, project: project) }
- project.reload
- expect(project.latest_jira_import.status).to eq 'scheduled'
- expect(project.jira_imports.size).to eq 2
- expect(project.jira_imports.first.jira_project_key).to eq jira_project_key
- expect(project.jira_imports.last.jira_project_key).to eq 'New Project'
- expect(response).to redirect_to(project_import_jira_path(project))
- end
+ before do
+ WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/serverInfo')
+ .to_raise(JIRA::HTTPError.new(double(message: 'Some failure.')))
end
+
+ it_behaves_like 'template with no message'
end
end
end
diff --git a/spec/javascripts/behaviors/autosize_spec.js b/spec/frontend/behaviors/autosize_spec.js
index 59abae479d4..59abae479d4 100644
--- a/spec/javascripts/behaviors/autosize_spec.js
+++ b/spec/frontend/behaviors/autosize_spec.js
diff --git a/spec/frontend/behaviors/bind_in_out_spec.js b/spec/frontend/behaviors/bind_in_out_spec.js
index 923b6d372dd..92a68ddd387 100644
--- a/spec/frontend/behaviors/bind_in_out_spec.js
+++ b/spec/frontend/behaviors/bind_in_out_spec.js
@@ -163,14 +163,8 @@ describe('BindInOut', () => {
describe('init', () => {
beforeEach(() => {
- // eslint-disable-next-line func-names
- jest.spyOn(BindInOut.prototype, 'addEvents').mockImplementation(function() {
- return this;
- });
- // eslint-disable-next-line func-names
- jest.spyOn(BindInOut.prototype, 'updateOut').mockImplementation(function() {
- return this;
- });
+ jest.spyOn(BindInOut.prototype, 'addEvents').mockReturnThis();
+ jest.spyOn(BindInOut.prototype, 'updateOut').mockReturnThis();
testContext.init = BindInOut.init({}, {});
});
diff --git a/spec/javascripts/behaviors/copy_as_gfm_spec.js b/spec/frontend/behaviors/copy_as_gfm_spec.js
index d653fca0988..cf96ac488a8 100644
--- a/spec/javascripts/behaviors/copy_as_gfm_spec.js
+++ b/spec/frontend/behaviors/copy_as_gfm_spec.js
@@ -27,7 +27,7 @@ describe('CopyAsGFM', () => {
}
it('wraps pasted code when not already in code tags', () => {
- spyOn(window.gl.utils, 'insertText').and.callFake((el, textFunc) => {
+ jest.spyOn(window.gl.utils, 'insertText').mockImplementation((el, textFunc) => {
const insertedText = textFunc('This is code: ', '');
expect(insertedText).toEqual('`code`');
@@ -37,7 +37,7 @@ describe('CopyAsGFM', () => {
});
it('does not wrap pasted code when already in code tags', () => {
- spyOn(window.gl.utils, 'insertText').and.callFake((el, textFunc) => {
+ jest.spyOn(window.gl.utils, 'insertText').mockImplementation((el, textFunc) => {
const insertedText = textFunc('This is code: `', '`');
expect(insertedText).toEqual('code');
@@ -90,16 +90,16 @@ describe('CopyAsGFM', () => {
.catch(done.fail);
});
- beforeEach(() => spyOn(clipboardData, 'setData'));
+ beforeEach(() => jest.spyOn(clipboardData, 'setData'));
describe('list handling', () => {
it('uses correct gfm for unordered lists', done => {
const selection = stubSelection('<li>List Item1</li><li>List Item2</li>\n', 'UL');
- spyOn(window, 'getSelection').and.returnValue(selection);
+ window.getSelection = jest.fn(() => selection);
simulateCopy();
- setTimeout(() => {
+ setImmediate(() => {
const expectedGFM = '* List Item1\n* List Item2';
expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
@@ -110,10 +110,10 @@ describe('CopyAsGFM', () => {
it('uses correct gfm for ordered lists', done => {
const selection = stubSelection('<li>List Item1</li><li>List Item2</li>\n', 'OL');
- spyOn(window, 'getSelection').and.returnValue(selection);
+ window.getSelection = jest.fn(() => selection);
simulateCopy();
- setTimeout(() => {
+ setImmediate(() => {
const expectedGFM = '1. List Item1\n1. List Item2';
expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
diff --git a/spec/javascripts/behaviors/gl_emoji/unicode_support_map_spec.js b/spec/frontend/behaviors/gl_emoji/unicode_support_map_spec.js
index f656b97fec2..aaee9c30cac 100644
--- a/spec/javascripts/behaviors/gl_emoji/unicode_support_map_spec.js
+++ b/spec/frontend/behaviors/gl_emoji/unicode_support_map_spec.js
@@ -1,28 +1,28 @@
import getUnicodeSupportMap from '~/emoji/support/unicode_support_map';
import AccessorUtilities from '~/lib/utils/accessor';
+import { useLocalStorageSpy } from 'helpers/local_storage_helper';
describe('Unicode Support Map', () => {
+ useLocalStorageSpy();
describe('getUnicodeSupportMap', () => {
const stringSupportMap = 'stringSupportMap';
beforeEach(() => {
- spyOn(AccessorUtilities, 'isLocalStorageAccessSafe');
- spyOn(window.localStorage, 'getItem');
- spyOn(window.localStorage, 'setItem');
- spyOn(JSON, 'parse');
- spyOn(JSON, 'stringify').and.returnValue(stringSupportMap);
+ jest.spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').mockImplementation(() => {});
+ jest.spyOn(JSON, 'parse').mockImplementation(() => {});
+ jest.spyOn(JSON, 'stringify').mockReturnValue(stringSupportMap);
});
- describe('if isLocalStorageAvailable is `true`', function() {
+ describe('if isLocalStorageAvailable is `true`', () => {
beforeEach(() => {
- AccessorUtilities.isLocalStorageAccessSafe.and.returnValue(true);
+ jest.spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').mockReturnValue(true);
getUnicodeSupportMap();
});
it('should call .getItem and .setItem', () => {
- const getArgs = window.localStorage.getItem.calls.allArgs();
- const setArgs = window.localStorage.setItem.calls.allArgs();
+ const getArgs = window.localStorage.getItem.mock.calls;
+ const setArgs = window.localStorage.setItem.mock.calls;
expect(getArgs[0][0]).toBe('gl-emoji-version');
expect(getArgs[1][0]).toBe('gl-emoji-user-agent');
@@ -36,15 +36,15 @@ describe('Unicode Support Map', () => {
});
});
- describe('if isLocalStorageAvailable is `false`', function() {
+ describe('if isLocalStorageAvailable is `false`', () => {
beforeEach(() => {
- AccessorUtilities.isLocalStorageAccessSafe.and.returnValue(false);
+ jest.spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').mockReturnValue(false);
getUnicodeSupportMap();
});
it('should not call .getItem or .setItem', () => {
- expect(window.localStorage.getItem.calls.count()).toBe(1);
+ expect(window.localStorage.getItem.mock.calls.length).toBe(1);
expect(window.localStorage.setItem).not.toHaveBeenCalled();
});
});
diff --git a/spec/javascripts/behaviors/markdown/highlight_current_user_spec.js b/spec/frontend/behaviors/markdown/highlight_current_user_spec.js
index 3305ddc412d..3305ddc412d 100644
--- a/spec/javascripts/behaviors/markdown/highlight_current_user_spec.js
+++ b/spec/frontend/behaviors/markdown/highlight_current_user_spec.js
diff --git a/spec/javascripts/behaviors/requires_input_spec.js b/spec/frontend/behaviors/requires_input_spec.js
index 617fe49b059..617fe49b059 100644
--- a/spec/javascripts/behaviors/requires_input_spec.js
+++ b/spec/frontend/behaviors/requires_input_spec.js
diff --git a/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js b/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
index f6232026915..6391a544985 100644
--- a/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js
+++ b/spec/frontend/behaviors/shortcuts/shortcuts_issuable_spec.js
@@ -1,15 +1,19 @@
-/* eslint-disable
- no-underscore-dangle
-*/
-
import $ from 'jquery';
+import 'mousetrap';
import initCopyAsGFM, { CopyAsGFM } from '~/behaviors/markdown/copy_as_gfm';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
+import { getSelectedFragment } from '~/lib/utils/common_utils';
const FORM_SELECTOR = '.js-main-target-form .js-vue-comment-form';
-describe('ShortcutsIssuable', function() {
+jest.mock('~/lib/utils/common_utils', () => ({
+ ...jest.requireActual('~/lib/utils/common_utils'),
+ getSelectedFragment: jest.fn().mockName('getSelectedFragment'),
+}));
+
+describe('ShortcutsIssuable', () => {
const fixtureName = 'snippets/show.html';
+
preloadFixtures(fixtureName);
beforeAll(done => {
@@ -27,21 +31,24 @@ describe('ShortcutsIssuable', function() {
loadFixtures(fixtureName);
$('body').append(
`<div class="js-main-target-form">
- <textare class="js-vue-comment-form"></textare>
+ <textarea class="js-vue-comment-form"></textarea>
</div>`,
);
document.querySelector('.js-new-note-form').classList.add('js-main-target-form');
- this.shortcut = new ShortcutsIssuable(true);
+
+ window.shortcut = new ShortcutsIssuable(true);
});
afterEach(() => {
$(FORM_SELECTOR).remove();
+
+ delete window.shortcut;
});
describe('replyWithSelectedText', () => {
// Stub window.gl.utils.getSelectedFragment to return a node with the provided HTML.
const stubSelection = (html, invalidNode) => {
- ShortcutsIssuable.__Rewire__('getSelectedFragment', () => {
+ getSelectedFragment.mockImplementation(() => {
const documentFragment = document.createDocumentFragment();
const node = document.createElement('div');
@@ -61,7 +68,7 @@ describe('ShortcutsIssuable', function() {
});
it('triggers `focus`', () => {
- const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
+ const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
expect(spy).toHaveBeenCalled();
@@ -80,7 +87,7 @@ describe('ShortcutsIssuable', function() {
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect($(FORM_SELECTOR).val()).toBe(
'This text was already here.\n\n> Selected text.\n\n',
);
@@ -96,17 +103,17 @@ describe('ShortcutsIssuable', function() {
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect(triggered).toBe(true);
done();
});
});
it('triggers `focus`', done => {
- const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
+ const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect(spy).toHaveBeenCalled();
done();
});
@@ -118,7 +125,7 @@ describe('ShortcutsIssuable', function() {
stubSelection('<p>This text has been selected.</p>');
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect($(FORM_SELECTOR).val()).toBe('> This text has been selected.\n\n');
done();
});
@@ -132,7 +139,7 @@ describe('ShortcutsIssuable', function() {
);
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect($(FORM_SELECTOR).val()).toBe(
'> Selected line one.\n>\n> Selected line two.\n>\n> Selected line three.\n\n',
);
@@ -149,17 +156,17 @@ describe('ShortcutsIssuable', function() {
it('does not add anything to the input', done => {
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect($(FORM_SELECTOR).val()).toBe('');
done();
});
});
it('triggers `focus`', done => {
- const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
+ const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect(spy).toHaveBeenCalled();
done();
});
@@ -174,17 +181,17 @@ describe('ShortcutsIssuable', function() {
it('only adds the valid part to the input', done => {
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect($(FORM_SELECTOR).val()).toBe('> Selected text.\n\n');
done();
});
});
it('triggers `focus`', done => {
- const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
+ const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect(spy).toHaveBeenCalled();
done();
});
@@ -198,7 +205,7 @@ describe('ShortcutsIssuable', function() {
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect(triggered).toBe(true);
done();
});
@@ -207,7 +214,7 @@ describe('ShortcutsIssuable', function() {
describe('with a selection in a valid block', () => {
beforeEach(() => {
- ShortcutsIssuable.__Rewire__('getSelectedFragment', () => {
+ getSelectedFragment.mockImplementation(() => {
const documentFragment = document.createDocumentFragment();
const node = document.createElement('div');
const originalNode = document.createElement('body');
@@ -228,17 +235,17 @@ describe('ShortcutsIssuable', function() {
it('adds the quoted selection to the input', done => {
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect($(FORM_SELECTOR).val()).toBe('> *Selected text.*\n\n');
done();
});
});
it('triggers `focus`', done => {
- const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
+ const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect(spy).toHaveBeenCalled();
done();
});
@@ -252,7 +259,7 @@ describe('ShortcutsIssuable', function() {
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect(triggered).toBe(true);
done();
});
@@ -261,7 +268,7 @@ describe('ShortcutsIssuable', function() {
describe('with a selection in an invalid block', () => {
beforeEach(() => {
- ShortcutsIssuable.__Rewire__('getSelectedFragment', () => {
+ getSelectedFragment.mockImplementation(() => {
const documentFragment = document.createDocumentFragment();
const node = document.createElement('div');
const originalNode = document.createElement('body');
@@ -282,17 +289,17 @@ describe('ShortcutsIssuable', function() {
it('does not add anything to the input', done => {
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect($(FORM_SELECTOR).val()).toBe('');
done();
});
});
it('triggers `focus`', done => {
- const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
+ const spy = jest.spyOn(document.querySelector(FORM_SELECTOR), 'focus');
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
+ setImmediate(() => {
expect(spy).toHaveBeenCalled();
done();
});
@@ -301,11 +308,11 @@ describe('ShortcutsIssuable', function() {
describe('with a valid selection with no text content', () => {
it('returns the proper markdown', done => {
- stubSelection('<img src="foo" alt="image" />');
+ stubSelection('<img src="https://gitlab.com/logo.png" alt="logo" />');
ShortcutsIssuable.replyWithSelectedText(true);
- setTimeout(() => {
- expect($(FORM_SELECTOR).val()).toBe('> ![image](http://localhost:9876/foo)\n\n');
+ setImmediate(() => {
+ expect($(FORM_SELECTOR).val()).toBe('> ![logo](https://gitlab.com/logo.png)\n\n');
done();
});
diff --git a/spec/frontend/helpers/dom_shims/image_element_properties.js b/spec/frontend/helpers/dom_shims/image_element_properties.js
index 525246e6ade..d94c157e44d 100644
--- a/spec/frontend/helpers/dom_shims/image_element_properties.js
+++ b/spec/frontend/helpers/dom_shims/image_element_properties.js
@@ -1,6 +1,6 @@
Object.defineProperty(global.HTMLImageElement.prototype, 'src', {
get() {
- return this.$_jest_src;
+ return this.$_jest_src || this.getAttribute('src');
},
set(val) {
this.$_jest_src = val;
diff --git a/spec/lib/gitlab/jira_import_spec.rb b/spec/lib/gitlab/jira_import_spec.rb
index 6272f913318..6f3c8bd6ecf 100644
--- a/spec/lib/gitlab/jira_import_spec.rb
+++ b/spec/lib/gitlab/jira_import_spec.rb
@@ -9,6 +9,9 @@ describe Gitlab::JiraImport do
include JiraServiceHelper
let_it_be(:project, reload: true) { create(:project) }
+ let(:additional_params) { {} }
+
+ subject { described_class.validate_project_settings!(project, additional_params) }
shared_examples 'raise Jira import error' do |message|
it 'returns error' do
@@ -17,6 +20,16 @@ describe Gitlab::JiraImport do
end
shared_examples 'jira configuration base checks' do
+ context 'with configuration_check set to false' do
+ before do
+ additional_params[:configuration_check] = false
+ end
+
+ it 'does not raise Jira integration error' do
+ expect { subject }.not_to raise_error
+ end
+ end
+
context 'when Jira service was not setup' do
it_behaves_like 'raise Jira import error', 'Jira integration not configured.'
end
@@ -40,8 +53,6 @@ describe Gitlab::JiraImport do
end
context 'without user param' do
- subject { described_class.validate_project_settings!(project) }
-
it_behaves_like 'jira configuration base checks'
context 'when jira connection is valid' do
@@ -56,7 +67,7 @@ describe Gitlab::JiraImport do
context 'with user param provided' do
let_it_be(:user) { create(:user) }
- subject { described_class.validate_project_settings!(project, user: user) }
+ let(:additional_params) { { user: user } }
context 'when user has permission to run import' do
before do
diff --git a/spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb b/spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb
index 7d738b8a569..7a8aba2d396 100644
--- a/spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb
+++ b/spec/lib/gitlab/sidekiq_config/cli_methods_spec.rb
@@ -77,7 +77,7 @@ describe Gitlab::SidekiqConfig::CliMethods do
describe '.expand_queues' do
let(:worker_queues) do
[
- 'cronjob:stuck_import_jobs',
+ 'cronjob:import_stuck_project_import_jobs',
'cronjob:jira_import_stuck_jira_import_jobs',
'cronjob:stuck_merge_jobs',
'post_receive'
@@ -93,12 +93,22 @@ describe Gitlab::SidekiqConfig::CliMethods do
allow(described_class).to receive(:worker_queues).and_return(worker_queues)
expect(described_class.expand_queues(['cronjob']))
- .to contain_exactly('cronjob', 'cronjob:stuck_import_jobs', 'cronjob:jira_import_stuck_jira_import_jobs', 'cronjob:stuck_merge_jobs')
+ .to contain_exactly(
+ 'cronjob',
+ 'cronjob:import_stuck_project_import_jobs',
+ 'cronjob:jira_import_stuck_jira_import_jobs',
+ 'cronjob:stuck_merge_jobs'
+ )
end
it 'expands queue namespaces to concrete queue names' do
expect(described_class.expand_queues(['cronjob'], worker_queues))
- .to contain_exactly('cronjob', 'cronjob:stuck_import_jobs', 'cronjob:jira_import_stuck_jira_import_jobs', 'cronjob:stuck_merge_jobs')
+ .to contain_exactly(
+ 'cronjob',
+ 'cronjob:import_stuck_project_import_jobs',
+ 'cronjob:jira_import_stuck_jira_import_jobs',
+ 'cronjob:stuck_merge_jobs'
+ )
end
it 'lets concrete queue names pass through' do
diff --git a/spec/lib/gitlab/sidekiq_config_spec.rb b/spec/lib/gitlab/sidekiq_config_spec.rb
index 58295da2041..66744d07aaa 100644
--- a/spec/lib/gitlab/sidekiq_config_spec.rb
+++ b/spec/lib/gitlab/sidekiq_config_spec.rb
@@ -18,7 +18,7 @@ describe Gitlab::SidekiqConfig do
expect(queues).to include('post_receive')
expect(queues).to include('merge')
- expect(queues).to include('cronjob:stuck_import_jobs')
+ expect(queues).to include('cronjob:import_stuck_project_import_jobs')
expect(queues).to include('cronjob:jira_import_stuck_jira_import_jobs')
expect(queues).to include('mailers')
expect(queues).to include('default')
diff --git a/spec/lib/gitlab/sidekiq_versioning/manager_spec.rb b/spec/lib/gitlab/sidekiq_versioning/manager_spec.rb
index e83fd6ef820..a528ce201a2 100644
--- a/spec/lib/gitlab/sidekiq_versioning/manager_spec.rb
+++ b/spec/lib/gitlab/sidekiq_versioning/manager_spec.rb
@@ -16,7 +16,7 @@ describe Gitlab::SidekiqVersioning::Manager do
expect(queues).to include('post_receive')
expect(queues).to include('repository_fork')
expect(queues).to include('cronjob')
- expect(queues).to include('cronjob:stuck_import_jobs')
+ expect(queues).to include('cronjob:import_stuck_project_import_jobs')
expect(queues).to include('cronjob:jira_import_stuck_jira_import_jobs')
expect(queues).to include('cronjob:stuck_merge_jobs')
expect(queues).to include('unknown')
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 1c3f0c9a93f..8c50966078f 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -2369,24 +2369,10 @@ describe MergeRequest do
end
context 'when async is true' do
- context 'and async_merge_request_check_mergeability feature flag is enabled' do
- it 'executes MergeabilityCheckService asynchronously' do
- expect(mergeability_service).to receive(:async_execute)
+ it 'executes MergeabilityCheckService asynchronously' do
+ expect(mergeability_service).to receive(:async_execute)
- subject.check_mergeability(async: true)
- end
- end
-
- context 'and async_merge_request_check_mergeability feature flag is disabled' do
- before do
- stub_feature_flags(async_merge_request_check_mergeability: false)
- end
-
- it 'executes MergeabilityCheckService' do
- expect(mergeability_service).to receive(:execute)
-
- subject.check_mergeability(async: true)
- end
+ subject.check_mergeability(async: true)
end
end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index c4b91e41c02..c698b40a4c0 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1446,17 +1446,13 @@ describe Repository do
let(:empty_repository) { create(:project_empty_repo).repository }
it 'returns empty array for an empty repository' do
- # rubocop:disable Style/WordArray
- expect(empty_repository.blobs_at(['master', 'foobar'])).to eq([])
- # rubocop:enable Style/WordArray
+ expect(empty_repository.blobs_at(%w[master foobar])).to eq([])
end
it 'returns blob array for a non-empty repository' do
repository.create_file(User.last, 'foobar', 'CONTENT', message: 'message', branch_name: 'master')
- # rubocop:disable Style/WordArray
- blobs = repository.blobs_at([['master', 'foobar']])
- # rubocop:enable Style/WordArray
+ blobs = repository.blobs_at([%w[master foobar]])
expect(blobs.first.name).to eq('foobar')
expect(blobs.size).to eq(1)
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index 5a145b5ea39..8698a6cf3d3 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -279,19 +279,31 @@ describe Service do
end
describe '.build_from_integration' do
- context 'when template is invalid' do
- it 'sets service template to inactive when template is invalid' do
- template = build(:prometheus_service, template: true, active: true, properties: {})
- template.save(validate: false)
+ context 'when integration is invalid' do
+ let(:integration) do
+ build(:prometheus_service, :template, active: true, properties: {})
+ .tap { |integration| integration.save(validate: false) }
+ end
- service = described_class.build_from_integration(project.id, template)
+ it 'sets service to inactive' do
+ service = described_class.build_from_integration(project.id, integration)
expect(service).to be_valid
expect(service.active).to be false
end
end
- describe 'build issue tracker from a template' do
+ context 'when integration is an instance' do
+ let(:integration) { create(:jira_service, :instance) }
+
+ it 'sets inherit_from_id from integration' do
+ service = described_class.build_from_integration(project.id, integration)
+
+ expect(service.inherit_from_id).to eq(integration.id)
+ end
+ end
+
+ describe 'build issue tracker from an integration' do
let(:title) { 'custom title' }
let(:description) { 'custom description' }
let(:url) { 'http://jira.example.com' }
@@ -305,9 +317,9 @@ describe Service do
}
end
- shared_examples 'service creation from a template' do
+ shared_examples 'service creation from an integration' do
it 'creates a correct service' do
- service = described_class.build_from_integration(project.id, template)
+ service = described_class.build_from_integration(project.id, integration)
expect(service).to be_active
expect(service.title).to eq(title)
@@ -324,30 +336,30 @@ describe Service do
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
context 'when data are stored in properties' do
let(:properties) { data_params.merge(title: title, description: description) }
- let!(:template) do
+ let!(:integration) do
create(:jira_service, :without_properties_callback, template: true, properties: properties.merge(additional: 'something'))
end
- it_behaves_like 'service creation from a template'
+ it_behaves_like 'service creation from an integration'
end
context 'when data are stored in separated fields' do
- let(:template) do
+ let(:integration) do
create(:jira_service, :template, data_params.merge(properties: {}, title: title, description: description))
end
- it_behaves_like 'service creation from a template'
+ it_behaves_like 'service creation from an integration'
end
context 'when data are stored in both properties and separated fields' do
let(:properties) { data_params.merge(title: title, description: description) }
- let(:template) do
+ let(:integration) do
create(:jira_service, :without_properties_callback, active: true, template: true, properties: properties).tap do |service|
create(:jira_tracker_data, data_params.merge(service: service))
end
end
- it_behaves_like 'service creation from a template'
+ it_behaves_like 'service creation from an integration'
end
end
end
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index d3a1a92d6f4..729e5d9c23d 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -453,24 +453,23 @@ describe Projects::CreateService, '#execute' do
subject(:project) { create_project(user, opts) }
context 'when there is an active instance-level and an active template integration' do
- before do
- create(:prometheus_service, :instance, api_url: 'https://prometheus.instance.com/')
- create(:prometheus_service, :template, api_url: 'https://prometheus.template.com/')
- end
+ let!(:template_integration) { create(:prometheus_service, :template, api_url: 'https://prometheus.template.com/') }
+ let!(:instance_integration) { create(:prometheus_service, :instance, api_url: 'https://prometheus.instance.com/') }
it 'creates a service from the instance-level integration' do
expect(project.services.count).to eq(1)
- expect(project.services.first.api_url).to eq('https://prometheus.instance.com/')
+ expect(project.services.first.api_url).to eq(instance_integration.api_url)
+ expect(project.services.first.inherit_from_id).to eq(instance_integration.id)
end
end
context 'when there is an active service template' do
- before do
- create(:prometheus_service, :template, active: true)
- end
+ let!(:template_integration) { create(:prometheus_service, :template, api_url: 'https://prometheus.template.com/') }
it 'creates a service from the template' do
expect(project.services.count).to eq(1)
+ expect(project.services.first.api_url).to eq(template_integration.api_url)
+ expect(project.services.first.inherit_from_id).to be_nil
end
end
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb
index 56725dd0bd8..f6e1608acbe 100644
--- a/spec/services/todo_service_spec.rb
+++ b/spec/services/todo_service_spec.rb
@@ -27,6 +27,39 @@ describe TodoService do
project.add_developer(skipped)
end
+ shared_examples 'reassigned target' do
+ it 'creates a pending todo for new assignee' do
+ target_unassigned.assignees = [john_doe]
+ service.send(described_method, target_unassigned, author)
+
+ should_create_todo(user: john_doe, target: target_unassigned, action: Todo::ASSIGNED)
+ end
+
+ it 'does not create a todo if unassigned' do
+ target_assigned.assignees = []
+
+ should_not_create_any_todo { service.send(described_method, target_assigned, author) }
+ end
+
+ it 'creates a todo if new assignee is the current user' do
+ target_assigned.assignees = [john_doe]
+ service.send(described_method, target_assigned, john_doe)
+
+ should_create_todo(user: john_doe, target: target_assigned, author: john_doe, action: Todo::ASSIGNED)
+ end
+
+ it 'does not create a todo for guests' do
+ service.send(described_method, target_assigned, author)
+ should_not_create_todo(user: guest, target: target_assigned, action: Todo::MENTIONED)
+ end
+
+ it 'does not create a directly addressed todo for guests' do
+ service.send(described_method, addressed_target_assigned, author)
+
+ should_not_create_todo(user: guest, target: addressed_target_assigned, action: Todo::DIRECTLY_ADDRESSED)
+ end
+ end
+
describe 'Issues' do
let(:issue) { create(:issue, project: project, assignees: [john_doe], author: author, description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") }
let(:addressed_issue) { create(:issue, project: project, assignees: [john_doe], author: author, description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") }
@@ -522,51 +555,21 @@ describe TodoService do
end
describe '#reassigned_issuable' do
- shared_examples 'reassigned issuable' do
- it 'creates a pending todo for new assignee' do
- issuable_unassigned.assignees = [john_doe]
- service.reassigned_issuable(issuable_unassigned, author)
-
- should_create_todo(user: john_doe, target: issuable_unassigned, action: Todo::ASSIGNED)
- end
-
- it 'does not create a todo if unassigned' do
- issuable_assigned.assignees = []
-
- should_not_create_any_todo { service.reassigned_issuable(issuable_assigned, author) }
- end
-
- it 'creates a todo if new assignee is the current user' do
- issuable_assigned.assignees = [john_doe]
- service.reassigned_issuable(issuable_assigned, john_doe)
-
- should_create_todo(user: john_doe, target: issuable_assigned, author: john_doe, action: Todo::ASSIGNED)
- end
-
- it 'does not create a todo for guests' do
- service.reassigned_issuable(issuable_assigned, author)
- should_not_create_todo(user: guest, target: issuable_assigned, action: Todo::MENTIONED)
- end
-
- it 'does not create a directly addressed todo for guests' do
- service.reassigned_issuable(addressed_issuable_assigned, author)
- should_not_create_todo(user: guest, target: addressed_issuable_assigned, action: Todo::DIRECTLY_ADDRESSED)
- end
- end
+ let(:described_method) { :reassigned_issuable }
context 'issuable is a merge request' do
- it_behaves_like 'reassigned issuable' do
- let(:issuable_assigned) { create(:merge_request, source_project: project, author: author, assignees: [john_doe], description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") }
- let(:addressed_issuable_assigned) { create(:merge_request, source_project: project, author: author, assignees: [john_doe], description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") }
- let(:issuable_unassigned) { create(:merge_request, source_project: project, author: author, assignees: []) }
+ it_behaves_like 'reassigned target' do
+ let(:target_assigned) { create(:merge_request, source_project: project, author: author, assignees: [john_doe], description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") }
+ let(:addressed_target_assigned) { create(:merge_request, source_project: project, author: author, assignees: [john_doe], description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") }
+ let(:target_unassigned) { create(:merge_request, source_project: project, author: author, assignees: []) }
end
end
context 'issuable is an issue' do
- it_behaves_like 'reassigned issuable' do
- let(:issuable_assigned) { create(:issue, project: project, author: author, assignees: [john_doe], description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") }
- let(:addressed_issuable_assigned) { create(:issue, project: project, author: author, assignees: [john_doe], description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") }
- let(:issuable_unassigned) { create(:issue, project: project, author: author, assignees: []) }
+ it_behaves_like 'reassigned target' do
+ let(:target_assigned) { create(:issue, project: project, author: author, assignees: [john_doe], description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") }
+ let(:addressed_target_assigned) { create(:issue, project: project, author: author, assignees: [john_doe], description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") }
+ let(:target_unassigned) { create(:issue, project: project, author: author, assignees: []) }
end
end
end
@@ -756,6 +759,16 @@ describe TodoService do
end
end
+ describe '#assign_alert' do
+ let(:described_method) { :assign_alert }
+
+ it_behaves_like 'reassigned target' do
+ let(:target_assigned) { create(:alert_management_alert, project: project, assignees: [john_doe]) }
+ let(:addressed_target_assigned) { create(:alert_management_alert, project: project, assignees: [john_doe]) }
+ let(:target_unassigned) { create(:alert_management_alert, project: project, assignees: []) }
+ end
+ end
+
describe '#merge_request_build_failed' do
let(:merge_participants) { [mr_unassigned.author, admin] }
diff --git a/spec/workers/gitlab/import/stuck_project_import_jobs_worker_spec.rb b/spec/workers/gitlab/import/stuck_project_import_jobs_worker_spec.rb
new file mode 100644
index 00000000000..5afc5717b82
--- /dev/null
+++ b/spec/workers/gitlab/import/stuck_project_import_jobs_worker_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Import::StuckProjectImportJobsWorker do
+ let(:worker) { described_class.new }
+
+ describe 'with scheduled import_status' do
+ it_behaves_like 'stuck import job detection' do
+ let(:import_state) { create(:project, :import_scheduled).import_state }
+
+ before do
+ import_state.update(jid: '123')
+ end
+ end
+ end
+
+ describe 'with started import_status' do
+ it_behaves_like 'stuck import job detection' do
+ let(:import_state) { create(:project, :import_started).import_state }
+
+ before do
+ import_state.update(jid: '123')
+ end
+ end
+ end
+end