summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-04-30 06:10:03 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-04-30 06:10:03 +0000
commit27b43bd4d613cc7b8773ca0863b8d8f9b90f6d87 (patch)
tree8bc7959282786fd8acce856cfa75ad36fda5f020
parent6b8e9712617b97b2586c90fe7855aa38e0987831 (diff)
downloadgitlab-ce-27b43bd4d613cc7b8773ca0863b8d8f9b90f6d87.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/graphql/types/grafana_integration_type.rb2
-rw-r--r--app/models/jira_import_state.rb5
-rw-r--r--app/models/project.rb8
-rw-r--r--changelogs/unreleased/196862-drop-plan-id.yml5
-rw-r--r--changelogs/unreleased/208920-jira-import-usage-data.yml5
-rw-r--r--changelogs/unreleased/211984-jira-import-connection-test.yml5
-rw-r--r--db/post_migrate/20200424043515_drop_namespaces_plan_id.rb26
-rw-r--r--db/structure.sql7
-rw-r--r--doc/.vale/gitlab/ReferenceLinks.yml10
-rw-r--r--doc/administration/feature_flags.md6
-rw-r--r--doc/administration/geo/replication/troubleshooting.md6
-rw-r--r--doc/administration/scaling/index.md272
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql2
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json2
-rw-r--r--doc/api/graphql/reference/index.md2
-rw-r--r--doc/api/repositories.md2
-rw-r--r--doc/ci/yaml/README.md2
-rw-r--r--doc/development/documentation/index.md4
-rw-r--r--doc/development/fe_guide/graphql.md3
-rw-r--r--doc/user/clusters/applications.md6
-rw-r--r--doc/user/markdown.md98
-rw-r--r--lib/gitlab/usage_data.rb12
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/controllers/projects/import/jira_controller_spec.rb3
-rw-r--r--spec/factories/usage_data.rb5
-rw-r--r--spec/lib/gitlab/jira_import/base_importer_spec.rb20
-rw-r--r--spec/lib/gitlab/jira_import/issues_importer_spec.rb3
-rw-r--r--spec/lib/gitlab/jira_import/labels_importer_spec.rb17
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb3
-rw-r--r--spec/models/project_spec.rb113
-rw-r--r--spec/requests/api/graphql/mutations/jira_import/start_spec.rb3
-rw-r--r--spec/services/jira_import/start_import_service_spec.rb122
-rw-r--r--spec/support/helpers/jira_service_helper.rb5
-rw-r--r--spec/workers/gitlab/jira_import/stage/import_issues_worker_spec.rb3
-rw-r--r--spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb4
35 files changed, 510 insertions, 284 deletions
diff --git a/app/graphql/types/grafana_integration_type.rb b/app/graphql/types/grafana_integration_type.rb
index c0582b266ab..7db733fc62a 100644
--- a/app/graphql/types/grafana_integration_type.rb
+++ b/app/graphql/types/grafana_integration_type.rb
@@ -9,7 +9,7 @@ module Types
field :id, GraphQL::ID_TYPE, null: false,
description: 'Internal ID of the Grafana integration'
field :grafana_url, GraphQL::STRING_TYPE, null: false,
- description: 'Url for the Grafana host for the Grafana integration'
+ description: 'URL for the Grafana host for the Grafana integration'
field :enabled, GraphQL::BOOLEAN_TYPE, null: false,
description: 'Indicates whether Grafana integration is enabled'
field :created_at, Types::TimeType, null: false,
diff --git a/app/models/jira_import_state.rb b/app/models/jira_import_state.rb
index 71bb25470f5..92147794e88 100644
--- a/app/models/jira_import_state.rb
+++ b/app/models/jira_import_state.rb
@@ -3,6 +3,7 @@
class JiraImportState < ApplicationRecord
include AfterCommitQueue
include ImportState::SidekiqJobTracker
+ include UsageStatistics
self.table_name = 'jira_imports'
@@ -97,4 +98,8 @@ class JiraImportState < ApplicationRecord
}
)
end
+
+ def self.finished_imports_count
+ finished.sum(:imported_issues_count)
+ end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 6116cd76e37..502d3391d63 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -871,10 +871,12 @@ class Project < ApplicationRecord
raise Projects::ImportService::Error, _('Jira import feature is disabled.') unless jira_issues_import_feature_flag_enabled?
raise Projects::ImportService::Error, _('Jira integration not configured.') unless jira_service&.active?
- return unless user
+ if user
+ raise Projects::ImportService::Error, _('Cannot import because issues are not available in this project.') unless feature_available?(:issues, user)
+ raise Projects::ImportService::Error, _('You do not have permissions to run the import.') unless user.can?(:admin_project, self)
+ end
- raise Projects::ImportService::Error, _('Cannot import because issues are not available in this project.') unless feature_available?(:issues, user)
- raise Projects::ImportService::Error, _('You do not have permissions to run the import.') unless user.can?(:admin_project, self)
+ raise Projects::ImportService::Error, _('Unable to connect to the Jira instance. Please check your Jira integration configuration.') unless jira_service.test(nil)[:success]
end
def human_import_status_name
diff --git a/changelogs/unreleased/196862-drop-plan-id.yml b/changelogs/unreleased/196862-drop-plan-id.yml
new file mode 100644
index 00000000000..e56ab11b117
--- /dev/null
+++ b/changelogs/unreleased/196862-drop-plan-id.yml
@@ -0,0 +1,5 @@
+---
+title: Remove namespaces.plan_id column
+merge_request: 30351
+author:
+type: other
diff --git a/changelogs/unreleased/208920-jira-import-usage-data.yml b/changelogs/unreleased/208920-jira-import-usage-data.yml
new file mode 100644
index 00000000000..b52c91da212
--- /dev/null
+++ b/changelogs/unreleased/208920-jira-import-usage-data.yml
@@ -0,0 +1,5 @@
+---
+title: Add jira imports to usage data
+merge_request: 29925
+author:
+type: added
diff --git a/changelogs/unreleased/211984-jira-import-connection-test.yml b/changelogs/unreleased/211984-jira-import-connection-test.yml
new file mode 100644
index 00000000000..f2a9c362456
--- /dev/null
+++ b/changelogs/unreleased/211984-jira-import-connection-test.yml
@@ -0,0 +1,5 @@
+---
+title: Test Jira connection before running import
+merge_request: 29926
+author:
+type: changed
diff --git a/db/post_migrate/20200424043515_drop_namespaces_plan_id.rb b/db/post_migrate/20200424043515_drop_namespaces_plan_id.rb
new file mode 100644
index 00000000000..53ce13cc699
--- /dev/null
+++ b/db/post_migrate/20200424043515_drop_namespaces_plan_id.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class DropNamespacesPlanId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do # rubocop: disable Migration/WithLockRetriesWithoutDdlTransaction
+ remove_column :namespaces, :plan_id
+ end
+ end
+
+ def down
+ unless column_exists?(:namespaces, :plan_id)
+ with_lock_retries do # rubocop: disable Migration/WithLockRetriesWithoutDdlTransaction
+ add_column :namespaces, :plan_id, :integer
+ end
+ end
+
+ add_concurrent_index :namespaces, :plan_id
+ add_concurrent_foreign_key :namespaces, :plans, column: :plan_id, on_delete: :nullify
+ end
+end
diff --git a/db/structure.sql b/db/structure.sql
index cb7c96aeee8..c0a222b61df 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -4141,7 +4141,6 @@ CREATE TABLE public.namespaces (
require_two_factor_authentication boolean DEFAULT false NOT NULL,
two_factor_grace_period integer DEFAULT 48 NOT NULL,
cached_markdown_version integer,
- plan_id integer,
project_creation_level integer,
runners_token character varying,
trial_ends_on timestamp with time zone,
@@ -9950,8 +9949,6 @@ CREATE INDEX index_namespaces_on_path ON public.namespaces USING btree (path);
CREATE INDEX index_namespaces_on_path_trigram ON public.namespaces USING gin (path public.gin_trgm_ops);
-CREATE INDEX index_namespaces_on_plan_id ON public.namespaces USING btree (plan_id);
-
CREATE UNIQUE INDEX index_namespaces_on_push_rule_id ON public.namespaces USING btree (push_rule_id);
CREATE INDEX index_namespaces_on_require_two_factor_authentication ON public.namespaces USING btree (require_two_factor_authentication);
@@ -11395,9 +11392,6 @@ ALTER TABLE ONLY public.system_note_metadata
ALTER TABLE ONLY public.merge_requests
ADD CONSTRAINT fk_fd82eae0b9 FOREIGN KEY (head_pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.namespaces
- ADD CONSTRAINT fk_fdd12e5b80 FOREIGN KEY (plan_id) REFERENCES public.plans(id) ON DELETE SET NULL;
-
ALTER TABLE ONLY public.project_import_data
ADD CONSTRAINT fk_ffb9ee3a10 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
@@ -13629,6 +13623,7 @@ COPY "schema_migrations" (version) FROM STDIN;
20200423081441
20200423081519
20200423101529
+20200424043515
20200424050250
20200424101920
20200427064130
diff --git a/doc/.vale/gitlab/ReferenceLinks.yml b/doc/.vale/gitlab/ReferenceLinks.yml
new file mode 100644
index 00000000000..35a657710de
--- /dev/null
+++ b/doc/.vale/gitlab/ReferenceLinks.yml
@@ -0,0 +1,10 @@
+# Checks for the presence of reference-style links that must be inline.
+#
+# For a list of all options, see https://errata-ai.github.io/vale/styles/
+extends: existence
+message: 'Link "%s" must be inline.'
+link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#basic-link-criteria
+level: error
+scope: raw
+raw:
+ - '\n\[.*\]: .*'
diff --git a/doc/administration/feature_flags.md b/doc/administration/feature_flags.md
index bda488b903f..59cd5497032 100644
--- a/doc/administration/feature_flags.md
+++ b/doc/administration/feature_flags.md
@@ -29,14 +29,10 @@ them. It can be done by GitLab administrators with access to GitLab Rails
console.
If you used a certain feature and identified a bug, a misbehavior, or an
-error, it's very important that you **[provide feedback]** to GitLab as soon
+error, it's very important that you [**provide feedback**](https://gitlab.com/gitlab-org/gitlab/issues/new?issue[title]=Docs%20-%20feature%20flag%20feedback%3A%20Feature%20Name&issue[description]=Describe%20the%20problem%20you%27ve%20encountered.%0A%0A%3C!--%20Don%27t%20edit%20below%20this%20line%20--%3E%0A%0A%2Flabel%20~%22docs%5C-comments%22%20) to GitLab as soon
as possible so we can improve or fix it while behind a flag. When you upgrade
GitLab to an earlier version, the feature flag status may change.
-[provide feedback]: https://gitlab.com/gitlab-org/gitlab/issues/new?issue[title]=Docs%20-%20feature%20flag%20feedback%3A%20Feature%20Name&issue[description]=Describe%20the%20problem%20you%27ve%20encountered.%0A%0A%3C!--%20Don%27t%20edit%20below%20this%20line%20--%3E%0A%0A%2Flabel%20~%22docs%5C-comments%22%20
-
-<!-- Note: the link identifier above was used to facilitate review and update. -->
-
NOTE: **Note:**
Mind that features deployed behind feature flags may not be ready for
production use. However, disabling features behind flags that were deployed
diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
index 87dcb7e83b8..c19b0f775ce 100644
--- a/doc/administration/geo/replication/troubleshooting.md
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -497,6 +497,12 @@ to start again from scratch, there are a few steps that can help you:
gitlab-ctl start
```
+1. Refresh Foreign Data Wrapper tables
+
+ ```sh
+ gitlab-rake geo:db:refresh_foreign_tables
+ ```
+
## Fixing errors during a failover or when promoting a secondary to a primary node
The following are possible errors that might be encountered during failover or
diff --git a/doc/administration/scaling/index.md b/doc/administration/scaling/index.md
index 2817ce36f0a..23dadca7a9f 100644
--- a/doc/administration/scaling/index.md
+++ b/doc/administration/scaling/index.md
@@ -58,11 +58,11 @@ On different cloud vendors a best effort like for like can be used.
From 1 to 1,000 users, a single-node [Omnibus](https://docs.gitlab.com/omnibus/) setup with frequent backups is adequate.
Please refer to the [installation documentation](../../install/README.md) and [backup/restore documentation](https://docs.gitlab.com/omnibus/settings/backups.html#backup-and-restore-omnibus-gitlab-configuration).
-| Users | Configuration[^8] | GCP type | AWS type[^9] |
-|-------|----------------------|---------------|--------------|
-| 100 | 2 vCPU, 7.2GB Memory | n1-standard-2 | c5.2xlarge |
-| 500 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
-| 1000 | 8 vCPU, 30GB Memory | n1-standard-8 | m5.2xlarge |
+| Users | Configuration([8](#footnotes)) | GCP type | AWS type([9](#footnotes)) |
+|-------|--------------------------------|---------------|---------------------------|
+| 100 | 2 vCPU, 7.2GB Memory | n1-standard-2 | c5.2xlarge |
+| 500 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
+| 1000 | 8 vCPU, 30GB Memory | n1-standard-8 | m5.2xlarge |
This solution is appropriate for many teams that have a single server at their disposal. With automatic backup of the GitLab repositories, configuration, and the database, this can be an optimal solution if you don't have strict availability requirements.
@@ -86,20 +86,20 @@ this alternative in mind is [being worked on](https://gitlab.com/gitlab-org/qual
- **Test RPS rates:** API: 40 RPS, Web: 4 RPS, Git: 4 RPS
- **Known issues:** [List of known performance issues](https://gitlab.com/gitlab-org/gitlab/issues?label_name%5B%5D=Quality%3Aperformance-issues)
-| Service | Nodes | Configuration[^8] | GCP type | AWS type[^9] |
-| ----------------------------|-------|-----------------------|---------------|--------------|
-| GitLab Rails[^1] | 3 | 8 vCPU, 7.2GB Memory | n1-highcpu-8 | c5.2xlarge |
-| PostgreSQL | 3 | 2 vCPU, 7.5GB Memory | n1-standard-2 | m5.large |
-| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Gitaly[^2] [^5] [^7] | X | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
-| Redis[^3] | 3 | 2 vCPU, 7.5GB Memory | n1-standard-2 | m5.large |
-| Consul + Sentinel[^3] | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Sidekiq | 4 | 2 vCPU, 7.5GB Memory | n1-standard-2 | m5.large |
-| Cloud Object Storage[^4] | - | - | - | - |
-| NFS Server[^5] [^7] | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
-| Monitoring node | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| External load balancing node[^6] | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Internal load balancing node[^6] | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Service | Nodes | Configuration ([8](#footnotes)) | GCP type | AWS type ([9](#footnotes)) |
+|--------------------------------------------------------------|-------|---------------------------------|---------------|----------------------------|
+| GitLab Rails ([1](#footnotes)) | 3 | 8 vCPU, 7.2GB Memory | n1-highcpu-8 | c5.2xlarge |
+| PostgreSQL | 3 | 2 vCPU, 7.5GB Memory | n1-standard-2 | m5.large |
+| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Gitaly ([2](#footnotes)) ([5](#footnotes)) ([7](#footnotes)) | X | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
+| Redis ([3](#footnotes)) | 3 | 2 vCPU, 7.5GB Memory | n1-standard-2 | m5.large |
+| Consul + Sentinel ([3](#footnotes)) | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Sidekiq | 4 | 2 vCPU, 7.5GB Memory | n1-standard-2 | m5.large |
+| Cloud Object Storage ([4](#footnotes)) | - | - | - | - |
+| NFS Server ([5](#footnotes)) ([7](#footnotes)) | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
+| Monitoring node | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| External load balancing node ([6](#footnotes)) | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Internal load balancing node ([6](#footnotes)) | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
### Up to 5,000 users
@@ -107,20 +107,20 @@ this alternative in mind is [being worked on](https://gitlab.com/gitlab-org/qual
- **Test RPS rates:** API: 100 RPS, Web: 10 RPS, Git: 10 RPS
- **Known issues:** [List of known performance issues](https://gitlab.com/gitlab-org/gitlab/issues?label_name%5B%5D=Quality%3Aperformance-issues)
-| Service | Nodes | Configuration[^8] | GCP type | AWS type[^9] |
-| ----------------------------|-------|------------------------|---------------|--------------|
-| GitLab Rails[^1] | 3 | 16 vCPU, 14.4GB Memory | n1-highcpu-16 | c5.4xlarge |
-| PostgreSQL | 3 | 2 vCPU, 7.5GB Memory | n1-standard-2 | m5.large |
-| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Gitaly[^2] [^5] [^7] | X | 8 vCPU, 30GB Memory | n1-standard-8 | m5.2xlarge |
-| Redis[^3] | 3 | 2 vCPU, 7.5GB Memory | n1-standard-2 | m5.large |
-| Consul + Sentinel[^3] | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Sidekiq | 4 | 2 vCPU, 7.5GB Memory | n1-standard-2 | m5.large |
-| Cloud Object Storage[^4] | - | - | - | - |
-| NFS Server[^5] [^7] | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
-| Monitoring node | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| External load balancing node[^6] | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Internal load balancing node[^6] | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Service | Nodes | Configuration ([8](#footnotes)) | GCP type | AWS type ([9](#footnotes)) |
+|--------------------------------------------------------------|-------|---------------------------------|---------------|----------------------------|
+| GitLab Rails ([1](#footnotes)) | 3 | 16 vCPU, 14.4GB Memory | n1-highcpu-16 | c5.4xlarge |
+| PostgreSQL | 3 | 2 vCPU, 7.5GB Memory | n1-standard-2 | m5.large |
+| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Gitaly ([2](#footnotes)) ([5](#footnotes)) ([7](#footnotes)) | X | 8 vCPU, 30GB Memory | n1-standard-8 | m5.2xlarge |
+| Redis ([3](#footnotes)) | 3 | 2 vCPU, 7.5GB Memory | n1-standard-2 | m5.large |
+| Consul + Sentinel ([3](#footnotes)) | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Sidekiq | 4 | 2 vCPU, 7.5GB Memory | n1-standard-2 | m5.large |
+| Cloud Object Storage ([4](#footnotes)) | - | - | - | - |
+| NFS Server ([5](#footnotes)) ([7](#footnotes)) | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
+| Monitoring node | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| External load balancing node ([6](#footnotes)) | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Internal load balancing node ([6](#footnotes)) | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
### Up to 10,000 users
@@ -128,23 +128,23 @@ this alternative in mind is [being worked on](https://gitlab.com/gitlab-org/qual
- **Test RPS rates:** API: 200 RPS, Web: 20 RPS, Git: 20 RPS
- **Known issues:** [List of known performance issues](https://gitlab.com/gitlab-org/gitlab/issues?label_name%5B%5D=Quality%3Aperformance-issues)
-| Service | Nodes | GCP Configuration[^8] | GCP type | AWS type[^9] |
-| ----------------------------|-------|------------------------|----------------|--------------|
-| GitLab Rails[^1] | 3 | 32 vCPU, 28.8GB Memory | n1-highcpu-32 | c5.9xlarge |
-| PostgreSQL | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
-| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Gitaly[^2] [^5] [^7] | X | 16 vCPU, 60GB Memory | n1-standard-16 | m5.4xlarge |
-| Redis[^3] - Cache | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
-| Redis[^3] - Queues / Shared State | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
-| Redis Sentinel[^3] - Cache | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small |
-| Redis Sentinel[^3] - Queues / Shared State | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small |
-| Consul | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Sidekiq | 4 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
-| Cloud Object Storage[^4] | - | - | - | - |
-| NFS Server[^5] [^7] | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
-| Monitoring node | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
-| External load balancing node[^6] | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Internal load balancing node[^6] | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Service | Nodes | GCP Configuration ([8](#footnotes)) | GCP type | AWS type ([9](#footnotes)) |
+|--------------------------------------------------------------|-------|-------------------------------------|----------------|----------------------------|
+| GitLab Rails ([1](#footnotes)) | 3 | 32 vCPU, 28.8GB Memory | n1-highcpu-32 | c5.9xlarge |
+| PostgreSQL | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
+| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Gitaly ([2](#footnotes)) ([5](#footnotes)) ([7](#footnotes)) | X | 16 vCPU, 60GB Memory | n1-standard-16 | m5.4xlarge |
+| Redis ([3](#footnotes)) - Cache | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
+| Redis ([3](#footnotes)) - Queues / Shared State | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
+| Redis Sentinel ([3](#footnotes)) - Cache | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small |
+| Redis Sentinel ([3](#footnotes)) - Queues / Shared State | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small |
+| Consul | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Sidekiq | 4 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
+| Cloud Object Storage ([4](#footnotes)) | - | - | - | - |
+| NFS Server ([5](#footnotes)) ([7](#footnotes)) | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
+| Monitoring node | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
+| External load balancing node ([6](#footnotes)) | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Internal load balancing node ([6](#footnotes)) | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
### Up to 25,000 users
@@ -152,23 +152,23 @@ this alternative in mind is [being worked on](https://gitlab.com/gitlab-org/qual
- **Test RPS rates:** API: 500 RPS, Web: 50 RPS, Git: 50 RPS
- **Known issues:** [List of known performance issues](https://gitlab.com/gitlab-org/gitlab/issues?label_name%5B%5D=Quality%3Aperformance-issues)
-| Service | Nodes | Configuration[^8] | GCP type | AWS type[^9] |
-| ----------------------------|-------|------------------------|----------------|--------------|
-| GitLab Rails[^1] | 5 | 32 vCPU, 28.8GB Memory | n1-highcpu-32 | c5.9xlarge |
-| PostgreSQL | 3 | 8 vCPU, 30GB Memory | n1-standard-8 | m5.2xlarge |
-| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Gitaly[^2] [^5] [^7] | X | 32 vCPU, 120GB Memory | n1-standard-32 | m5.8xlarge |
-| Redis[^3] - Cache | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
-| Redis[^3] - Queues / Shared State | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
-| Redis Sentinel[^3] - Cache | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small |
-| Redis Sentinel[^3] - Queues / Shared State | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small |
-| Consul | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Sidekiq | 4 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
-| Cloud Object Storage[^4] | - | - | - | - |
-| NFS Server[^5] [^7] | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
-| Monitoring node | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
-| External load balancing node[^6] | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Internal load balancing node[^6] | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
+| Service | Nodes | Configuration ([8](#footnotes)) | GCP type | AWS type ([9](#footnotes)) |
+|--------------------------------------------------------------|-------|---------------------------------|----------------|----------------------------|
+| GitLab Rails ([1](#footnotes)) | 5 | 32 vCPU, 28.8GB Memory | n1-highcpu-32 | c5.9xlarge |
+| PostgreSQL | 3 | 8 vCPU, 30GB Memory | n1-standard-8 | m5.2xlarge |
+| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Gitaly ([2](#footnotes)) ([5](#footnotes)) ([7](#footnotes)) | X | 32 vCPU, 120GB Memory | n1-standard-32 | m5.8xlarge |
+| Redis ([3](#footnotes)) - Cache | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
+| Redis ([3](#footnotes)) - Queues / Shared State | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
+| Redis Sentinel ([3](#footnotes)) - Cache | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small |
+| Redis Sentinel ([3](#footnotes)) - Queues / Shared State | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small |
+| Consul | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Sidekiq | 4 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
+| Cloud Object Storage ([4](#footnotes)) | - | - | - | - |
+| NFS Server ([5](#footnotes)) ([7](#footnotes)) | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
+| Monitoring node | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
+| External load balancing node ([6](#footnotes)) | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Internal load balancing node ([6](#footnotes)) | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
### Up to 50,000 users
@@ -176,23 +176,23 @@ this alternative in mind is [being worked on](https://gitlab.com/gitlab-org/qual
- **Test RPS rates:** API: 1000 RPS, Web: 100 RPS, Git: 100 RPS
- **Known issues:** [List of known performance issues](https://gitlab.com/gitlab-org/gitlab/issues?label_name%5B%5D=Quality%3Aperformance-issues)
-| Service | Nodes | Configuration[^8] | GCP type | AWS type[^9] |
-| ----------------------------|-------|------------------------|----------------|--------------|
-| GitLab Rails[^1] | 12 | 32 vCPU, 28.8GB Memory | n1-highcpu-32 | c5.9xlarge |
-| PostgreSQL | 3 | 16 vCPU, 60GB Memory | n1-standard-16 | m5.4xlarge |
-| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Gitaly[^2] [^5] [^7] | X | 64 vCPU, 240GB Memory | n1-standard-64 | m5.16xlarge |
-| Redis[^3] - Cache | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
-| Redis[^3] - Queues / Shared State | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
-| Redis Sentinel[^3] - Cache | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small |
-| Redis Sentinel[^3] - Queues / Shared State | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small |
-| Consul | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Sidekiq | 4 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
-| NFS Server[^5] [^7] | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
-| Cloud Object Storage[^4] | - | - | - | - |
-| Monitoring node | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
-| External load balancing node[^6] | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
-| Internal load balancing node[^6] | 1 | 8 vCPU, 7.2GB Memory | n1-highcpu-8 | c5.2xlarge |
+| Service | Nodes | Configuration ([8](#footnotes)) | GCP type | AWS type ([9](#footnotes)) |
+|--------------------------------------------------------------|-------|---------------------------------|----------------|----------------------------|
+| GitLab Rails ([1](#footnotes)) | 12 | 32 vCPU, 28.8GB Memory | n1-highcpu-32 | c5.9xlarge |
+| PostgreSQL | 3 | 16 vCPU, 60GB Memory | n1-standard-16 | m5.4xlarge |
+| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Gitaly ([2](#footnotes)) ([5](#footnotes)) ([7](#footnotes)) | X | 64 vCPU, 240GB Memory | n1-standard-64 | m5.16xlarge |
+| Redis ([3](#footnotes)) - Cache | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
+| Redis ([3](#footnotes)) - Queues / Shared State | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
+| Redis Sentinel ([3](#footnotes)) - Cache | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small |
+| Redis Sentinel ([3](#footnotes)) - Queues / Shared State | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small |
+| Consul | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Sidekiq | 4 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge |
+| NFS Server ([5](#footnotes)) ([7](#footnotes)) | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
+| Cloud Object Storage ([4](#footnotes)) | - | - | - | - |
+| Monitoring node | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge |
+| External load balancing node ([6](#footnotes)) | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large |
+| Internal load balancing node ([6](#footnotes)) | 1 | 8 vCPU, 7.2GB Memory | n1-highcpu-8 | c5.2xlarge |
## Configuring GitLab to scale
@@ -206,9 +206,9 @@ listed below.
| Component | Description | Configuration instructions |
|-----------|-------------|----------------------------|
-| Load balancer(s)[^6] | Handles load balancing, typically when you have multiple GitLab application services nodes | [Load balancer configuration](../high_availability/load_balancer.md)[^6] |
-| Object storage service[^4] | Recommended store for shared data objects | [Cloud Object Storage configuration](../object_storage.md) |
-| NFS[^5] [^7] | Shared disk storage service. Can be used as an alternative for Gitaly or Object Storage. Required for GitLab Pages | [NFS configuration](../high_availability/nfs.md) |
+| Load balancer(s) ([6](#footnotes)) | Handles load balancing, typically when you have multiple GitLab application services nodes | [Load balancer configuration](../high_availability/load_balancer.md) ([6](#footnotes)) |
+| Object storage service ([4](#footnotes)) | Recommended store for shared data objects | [Cloud Object Storage configuration](../object_storage.md) |
+| NFS ([5](#footnotes)) ([7](#footnotes)) | Shared disk storage service. Can be used as an alternative for Gitaly or Object Storage. Required for GitLab Pages | [NFS configuration](../high_availability/nfs.md) |
### Components provided by Omnibus GitLab
@@ -218,61 +218,61 @@ order you'll typically configure them if they are required by your
| Component | Description | Configuration instructions |
|-----------|-------------|----------------------------|
-| [Consul](../../development/architecture.md#consul)[^3] | Service discovery and health checks/failover | [Consul HA configuration](../high_availability/consul.md) **(PREMIUM ONLY)** |
+| [Consul](../../development/architecture.md#consul) ([3](#footnotes)) | Service discovery and health checks/failover | [Consul HA configuration](../high_availability/consul.md) **(PREMIUM ONLY)** |
| [PostgreSQL](../../development/architecture.md#postgresql) | Database | [PostgreSQL configuration](https://docs.gitlab.com/omnibus/settings/database.html) |
| [PgBouncer](../../development/architecture.md#pgbouncer) | Database connection pooler | [PgBouncer configuration](../high_availability/pgbouncer.md#running-pgbouncer-as-part-of-a-non-ha-gitlab-installation) **(PREMIUM ONLY)** |
| Repmgr | PostgreSQL cluster management and failover | [PostgreSQL and Repmgr configuration](../high_availability/database.md) |
-| [Redis](../../development/architecture.md#redis)[^3] | Key/value store for fast data lookup and caching | [Redis configuration](../high_availability/redis.md) |
+| [Redis](../../development/architecture.md#redis) ([3](#footnotes)) | Key/value store for fast data lookup and caching | [Redis configuration](../high_availability/redis.md) |
| Redis Sentinel | High availability for Redis | [Redis Sentinel configuration](../high_availability/redis.md) |
-| [Gitaly](../../development/architecture.md#gitaly)[^2] [^5] [^7] | Provides access to Git repositories | [Gitaly configuration](../gitaly/index.md#running-gitaly-on-its-own-server) |
+| [Gitaly](../../development/architecture.md#gitaly) ([2](#footnotes)) ([5](#footnotes)) ([7](#footnotes)) | Provides access to Git repositories | [Gitaly configuration](../gitaly/index.md#running-gitaly-on-its-own-server) |
| [Sidekiq](../../development/architecture.md#sidekiq) | Asynchronous/background jobs | [Sidekiq configuration](../high_availability/sidekiq.md) |
-| [GitLab application services](../../development/architecture.md#unicorn)[^1] | Unicorn/Puma, Workhorse, GitLab Shell - serves front-end requests (UI, API, Git over HTTP/SSH) | [GitLab app scaling configuration](../high_availability/gitlab.md) |
+| [GitLab application services](../../development/architecture.md#unicorn)([1](#footnotes)) | Unicorn/Puma, Workhorse, GitLab Shell - serves front-end requests (UI, API, Git over HTTP/SSH) | [GitLab app scaling configuration](../high_availability/gitlab.md) |
| [Prometheus](../../development/architecture.md#prometheus) and [Grafana](../../development/architecture.md#grafana) | GitLab environment monitoring | [Monitoring node for scaling](../high_availability/monitoring_node.md) |
## Footnotes
-[^1]: In our architectures we run each GitLab Rails node using the Puma webserver
- and have its number of workers set to 90% of available CPUs along with 4 threads.
-
-[^2]: Gitaly node requirements are dependent on customer data, specifically the number of
- projects and their sizes. We recommend 2 nodes as an absolute minimum for HA environments
- and at least 4 nodes should be used when supporting 50,000 or more users.
- We also recommend that each Gitaly node should store no more than 5TB of data
- and have the number of [`gitaly-ruby` workers](../gitaly/index.md#gitaly-ruby)
- set to 20% of available CPUs. Additional nodes should be considered in conjunction
- with a review of expected data size and spread based on the recommendations above.
-
-[^3]: Recommended Redis setup differs depending on the size of the architecture.
- For smaller architectures (up to 5,000 users) we suggest one Redis cluster for all
- classes and that Redis Sentinel is hosted alongside Consul.
- For larger architectures (10,000 users or more) we suggest running a separate
- [Redis Cluster](../high_availability/redis.md#running-multiple-redis-clusters) for the Cache class
- and another for the Queues and Shared State classes respectively. We also recommend
- that you run the Redis Sentinel clusters separately as well for each Redis Cluster.
-
-[^4]: For data objects such as LFS, Uploads, Artifacts, etc. We recommend a [Cloud Object Storage service](../object_storage.md)
- over NFS where possible, due to better performance and availability.
-
-[^5]: NFS can be used as an alternative for both repository data (replacing Gitaly) and
- object storage but this isn't typically recommended for performance reasons. Note however it is required for
- [GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/issues/196).
-
-[^6]: Our architectures have been tested and validated with [HAProxy](https://www.haproxy.org/)
- as the load balancer. However other reputable load balancers with similar feature sets
- should also work instead but be aware these aren't validated.
-
-[^7]: We strongly recommend that any Gitaly and / or NFS nodes are set up with SSD disks over
- HDD with a throughput of at least 8,000 IOPS for read operations and 2,000 IOPS for write
- as these components have heavy I/O. These IOPS values are recommended only as a starter
- as with time they may be adjusted higher or lower depending on the scale of your
- environment's workload. If you're running the environment on a Cloud provider
- you may need to refer to their documentation on how configure IOPS correctly.
-
-[^8]: The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
- CPU platform on GCP. On different hardware you may find that adjustments, either lower
- or higher, are required for your CPU or Node counts accordingly. For more information, a
- [Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found
- [here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
-
-[^9]: AWS-equivalent configurations are rough suggestions and may change in the
- future. They have not yet been tested and validated.
+1. In our architectures we run each GitLab Rails node using the Puma webserver
+ and have its number of workers set to 90% of available CPUs along with 4 threads.
+
+1. Gitaly node requirements are dependent on customer data, specifically the number of
+ projects and their sizes. We recommend 2 nodes as an absolute minimum for HA environments
+ and at least 4 nodes should be used when supporting 50,000 or more users.
+ We also recommend that each Gitaly node should store no more than 5TB of data
+ and have the number of [`gitaly-ruby` workers](../gitaly/index.md#gitaly-ruby)
+ set to 20% of available CPUs. Additional nodes should be considered in conjunction
+ with a review of expected data size and spread based on the recommendations above.
+
+1. Recommended Redis setup differs depending on the size of the architecture.
+ For smaller architectures (up to 5,000 users) we suggest one Redis cluster for all
+ classes and that Redis Sentinel is hosted alongside Consul.
+ For larger architectures (10,000 users or more) we suggest running a separate
+ [Redis Cluster](../high_availability/redis.md#running-multiple-redis-clusters) for the Cache class
+ and another for the Queues and Shared State classes respectively. We also recommend
+ that you run the Redis Sentinel clusters separately as well for each Redis Cluster.
+
+1. For data objects such as LFS, Uploads, Artifacts, etc. We recommend a [Cloud Object Storage service](../object_storage.md)
+ over NFS where possible, due to better performance and availability.
+
+1. NFS can be used as an alternative for both repository data (replacing Gitaly) and
+ object storage but this isn't typically recommended for performance reasons. Note however it is required for
+ [GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/issues/196).
+
+1. Our architectures have been tested and validated with [HAProxy](https://www.haproxy.org/)
+ as the load balancer. However other reputable load balancers with similar feature sets
+ should also work instead but be aware these aren't validated.
+
+1. We strongly recommend that any Gitaly and / or NFS nodes are set up with SSD disks over
+ HDD with a throughput of at least 8,000 IOPS for read operations and 2,000 IOPS for write
+ as these components have heavy I/O. These IOPS values are recommended only as a starter
+ as with time they may be adjusted higher or lower depending on the scale of your
+ environment's workload. If you're running the environment on a Cloud provider
+ you may need to refer to their documentation on how configure IOPS correctly.
+
+1. The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
+ CPU platform on GCP. On different hardware you may find that adjustments, either lower
+ or higher, are required for your CPU or Node counts accordingly. For more information, a
+ [Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found
+ [here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
+
+1. AWS-equivalent configurations are rough suggestions and may change in the
+ future. They have not yet been tested and validated.
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index 245fcd300df..72dc13c51ae 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -3553,7 +3553,7 @@ type GrafanaIntegration {
enabled: Boolean!
"""
- Url for the Grafana host for the Grafana integration
+ URL for the Grafana host for the Grafana integration
"""
grafanaUrl: String!
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 84a6de1cf2a..2a99cf388b2 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -10207,7 +10207,7 @@
},
{
"name": "grafanaUrl",
- "description": "Url for the Grafana host for the Grafana integration",
+ "description": "URL for the Grafana host for the Grafana integration",
"args": [
],
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 313795141a1..4bf97ede2ed 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -577,7 +577,7 @@ Autogenerated return type of EpicTreeReorder
| --- | ---- | ---------- |
| `createdAt` | Time! | Timestamp of the issue's creation |
| `enabled` | Boolean! | Indicates whether Grafana integration is enabled |
-| `grafanaUrl` | String! | Url for the Grafana host for the Grafana integration |
+| `grafanaUrl` | String! | URL for the Grafana host for the Grafana integration |
| `id` | ID! | Internal ID of the Grafana integration |
| `token` **{warning-solid}** | String! | **Deprecated:** Plain text token has been masked for security reasons. Deprecated in 12.7 |
| `updatedAt` | Time! | Timestamp of the issue's last activity |
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index f261c9ab9f7..440db06792c 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -107,6 +107,8 @@ Parameters:
Get an archive of the repository. This endpoint can be accessed without
authentication if the repository is publicly accessible.
+This endpoint has a rate limit threshold of 5 requests per minute.
+
```plaintext
GET /projects/:id/repository/archive[.format]
```
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 2fb926540c6..1d1c8a76feb 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -2924,6 +2924,8 @@ Possible values for `when` are:
- `scheduler_failure`: Retry if the scheduler failed to assign the job to a runner.
- `data_integrity_failure`: Retry if there was a structural integrity problem detected.
+You can specify the number of [retry attempts for certain stages of job execution](#job-stages-attempts) using variables.
+
### `timeout`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/14887) in GitLab 12.3.
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 92044d3f942..2724958314c 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -171,8 +171,8 @@ Before getting started, make sure you read the introductory section
[documentation workflow](workflow.md).
- Use the current [merge request description template](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/merge_request_templates/Documentation.md)
-- Label the MR `Documentation`
-- Assign the correct milestone (see note below)
+- Label the MR `Documentation` (can only be done by people with `developer` access, for example, GitLab team members)
+- Assign the correct milestone per note below (can only be done by people with `developer` access, for example, GitLab team members)
Documentation will be merged if it is an improvement on existing content,
represents a good-faith effort to follow the template and style standards,
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index 353778980f4..e839f6bacd3 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -298,7 +298,8 @@ handleClick() {
GitLab's GraphQL API uses [Relay-style cursor pagination](https://www.apollographql.com/docs/react/data/pagination/#cursor-based)
for connection types. This means a "cursor" is used to keep track of where in the data
-set the next items should be fetched from.
+set the next items should be fetched from. [GraphQL Ruby Connection Concepts](https://graphql-ruby.org/pagination/connection_concepts.html)
+is a good overview and introduction to connections.
Every connection type (for example, `DesignConnection` and `DiscussionConnection`) has a field `pageInfo` that contains an information required for pagination:
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
index d1f49d6ea1f..69d057ad673 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.md
@@ -1024,11 +1024,11 @@ In addition, the following variables must be specified using [CI variables](../.
| CI Variable | Description |
|:---------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `JUPYTERHUB_PROXY_SECRET_TOKEN` | Sets [`proxy.secretToken`](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference.html#proxy-secrettoken). Generate using `openssl rand -hex 32`. |
-| `JUPYTERHUB_COOKIE_SECRET` | Sets [`hub.cookieSecret`](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference.html#hub-cookiesecret). Generate using `openssl rand -hex 32`. |
+| `JUPYTERHUB_PROXY_SECRET_TOKEN` | Secure string used for signing communications from the hub. See[`proxy.secretToken`](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference/reference.html#proxy-secrettoken). |
+| `JUPYTERHUB_COOKIE_SECRET` | Secure string used for signing secure cookies. See [`hub.cookieSecret`](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference/reference.html#hub-cookiesecret). |
| `JUPYTERHUB_HOST` | Hostname used for the installation. For example, `jupyter.gitlab.example.com`. |
| `JUPYTERHUB_GITLAB_HOST` | Hostname of the GitLab instance used for authentication. For example, `gitlab.example.com`. |
-| `JUPYTERHUB_AUTH_CRYPTO_KEY` | Sets [`auth.state.cryptoKey`](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference.html#auth-state-cryptokey). Generate using `openssl rand -hex 32`. |
+| `JUPYTERHUB_AUTH_CRYPTO_KEY` | A 32-byte encryption key used to set [`auth.state.cryptoKey`](https://zero-to-jupyterhub.readthedocs.io/en/stable/reference/reference.html#auth-state-cryptokey). |
| `JUPYTERHUB_AUTH_GITLAB_CLIENT_ID` | "Application ID" for the OAuth Application. |
| `JUPYTERHUB_AUTH_GITLAB_CLIENT_SECRET` | "Secret" for the OAuth Application. |
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index a1f83a47015..e7c75c7b8cd 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -828,23 +828,31 @@ Reference tags can use letters and other characters. Avoid using lowercase `w` o
(`_`) in footnote tag names until [this bug](https://gitlab.com/gitlab-org/gitlab/issues/24423) is
resolved.
-```markdown
-A footnote reference tag looks like this: [^1]
+<!--
+Do not edit the following codeblock. It uses HTML to skip the Vale ReferenceLinks test.
+-->
+
+<pre class="highlight"><code>A footnote reference tag looks like this: [^1]
This reference tag is a mix of letters and numbers. [^footnote-42]
-[^1]: This is the text inside a footnote.
+&#91;^1]: This is the text inside a footnote.
-[^footnote-42]: This is another footnote.
-```
+&#91;^footnote-42]: This is another footnote.
+</code></pre>
A footnote reference tag looks like this:[^1]
This reference tag is a mix of letters and numbers.[^footnote-42]
-[^1]: This is the text inside a footnote.
+<!--
+Do not delete the single space before the [^1] and [^footnotes] references below.
+These are used to force the Vale ReferenceLinks check to skip these examples.
+-->
+
+ [^1]: This is the text inside a footnote.
-[^footnote-42]: This is another footnote.
+ [^footnote-42]: This is another footnote.
### Headers
@@ -928,8 +936,11 @@ ___
Examples:
-```markdown
-Inline-style (hover to see title text):
+<!--
+Do not edit the following codeblock. It uses HTML to skip the Vale ReferenceLinks test.
+-->
+
+<pre class="highlight"><code>Inline-style (hover to see title text):
![alt text](img/markdown_logo.png "Title Text")
@@ -937,12 +948,12 @@ Reference-style (hover to see title text):
![alt text1][logo]
-[logo]: img/markdown_logo.png "Title Text"
-```
+&#91;logo]: img/markdown_logo.png "Title Text"
+</code></pre>
<!--
-DO NOT change the name of markdown_logo.png. This is used for a test
-in spec/controllers/help_controller_spec.rb.
+DO NOT change the name of markdown_logo.png. This is used for a test in
+spec/controllers/help_controller_spec.rb.
-->
Inline-style (hover to see title text):
@@ -951,9 +962,12 @@ Inline-style (hover to see title text):
Reference-style (hover to see title text):
-![alt text][logo]
+<!--
+The example below uses an in-line link to pass the Vale ReferenceLinks test.
+Do not change to a reference style link.
+-->
-[logo]: img/markdown_logo.png "Title Text"
+![alt text](img/markdown_logo.png "Title Text")
#### Videos
@@ -1036,7 +1050,10 @@ are separated into their own lines:
</dl>
```
-<!-- Note: The example below uses HTML to force correct rendering on docs.gitlab.com, Markdown will be fine in GitLab -->
+<!--
+Note: The example below uses HTML to force correct rendering on docs.gitlab.com,
+Markdown will be fine in GitLab.
+-->
<dl>
<dt>Markdown in HTML</dt>
@@ -1102,7 +1119,10 @@ PASTE LOGS HERE
</details>
````
-<!-- Note: The example below uses HTML to force correct rendering on docs.gitlab.com, Markdown will be fine in GitLab -->
+<!--
+The example below uses HTML to force correct rendering on docs.gitlab.com, Markdown
+will work correctly in GitLab.
+-->
<details>
<summary>Click this to collapse/fold.</summary>
@@ -1167,8 +1187,11 @@ A new line due to the previous backslash.
There are two ways to create links, inline-style and reference-style:
-```markdown
-- This is an [inline-style link](https://www.google.com)
+<!--
+Do not edit the following codeblock. It uses HTML to skip the Vale ReferenceLinks test.
+-->
+
+<pre class="highlight"><code>- This is an [inline-style link](https://www.google.com)
- This is a [link to a repository file in the same directory](index.md)
- This is a [relative link to a readme one directory higher](../README.md)
- This is a [link that also has title text](https://www.google.com "This link takes you to Google!")
@@ -1186,10 +1209,10 @@ Using references:
Some text to show that the reference links can follow later.
-[arbitrary case-insensitive reference text]: https://www.mozilla.org/en-US/
-[1]: https://slashdot.org
-[link text itself]: https://www.reddit.com
-```
+&#91;arbitrary case-insensitive reference text]: https://www.mozilla.org/en-US/
+&#91;1]: https://slashdot.org
+&#91;link text itself]: https://www.reddit.com
+</code></pre>
- This is an [inline-style link](https://www.google.com)
- This is a [link to a repository file in the same directory](index.md)
@@ -1203,15 +1226,16 @@ Using header ID anchors:
Using references:
-- This is a [reference-style link, see below][Arbitrary case-insensitive reference text]
-- You can [use numbers for reference-style link definitions, see below][1]
-- Or leave it empty and use the [link text itself][], see below.
+<!--
+The example below uses in-line links to pass the Vale ReferenceLinks test.
+Do not change to reference style links.
+-->
-Some text to show that the reference links can follow later.
+- This is a [reference-style link, see below](https://www.mozilla.org/en-US/)
+- You can [use numbers for reference-style link definitions, see below](https://slashdot.org)
+- Or leave it empty and use the [link text itself](https://www.reddit.com), see below.
-[arbitrary case-insensitive reference text]: https://www.mozilla.org/en-US/
-[1]: https://slashdot.org
-[link text itself]: https://www.reddit.com
+Some text to show that the reference links can follow later.
NOTE: **Note:** Relative links do not allow the referencing of project files in a wiki
page, or a wiki page in a project file. The reason for this is that a wiki is always
@@ -1261,8 +1285,11 @@ Examples:
4. And another item.
```
-<!-- The "2." and "4." in the example above are changed to "1." below, to match the style standards on docs.gitlab.com -->
-<!-- See https://docs.gitlab.com/ee/development/documentation/styleguide.html#lists -->
+<!--
+The "2." and "4." in the example above are changed to "1." below, to match the style
+standards on docs.gitlab.com.
+See https://docs.gitlab.com/ee/development/documentation/styleguide.html#lists
+-->
1. First ordered list item
1. Another item
@@ -1292,8 +1319,11 @@ They can even:
+ pluses
```
-<!-- The "*" and "+" in the example above are changed to "-" below, to match the style standards on docs.gitlab.com -->
-<!-- See https://docs.gitlab.com/ee/development/documentation/styleguide.html#lists -->
+<!--
+The "*" and "+" in the example above are changed to "-" below, to match the style
+standards on docs.gitlab.com.
+See https://docs.gitlab.com/ee/development/documentation/styleguide.html#lists
+-->
Unordered lists can:
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index 2272803fcfa..68e70ecf8e1 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -286,7 +286,7 @@ module Gitlab
results[:projects_slack_notifications_active] = results[:projects_slack_active]
results[:projects_slack_slash_active] = results[:projects_slack_slash_commands_active]
- results.merge(jira_usage)
+ results.merge(jira_usage).merge(jira_import_usage)
end
def jira_usage
@@ -320,6 +320,16 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
+ def jira_import_usage
+ finished_jira_imports = JiraImportState.finished
+
+ {
+ jira_imports_total_imported_count: count(finished_jira_imports),
+ jira_imports_projects_count: distinct_count(finished_jira_imports, :project_id),
+ jira_imports_total_imported_issues_count: alt_usage_data { JiraImportState.finished_imports_count }
+ }
+ end
+
def user_preferences_usage
{} # augmented in EE
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 6e09d3122da..e039b26112c 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -22233,6 +22233,9 @@ msgstr ""
msgid "Unable to connect to server: %{error}"
msgstr ""
+msgid "Unable to connect to the Jira instance. Please check your Jira integration configuration."
+msgstr ""
+
msgid "Unable to convert Kubernetes logs encoding to UTF-8"
msgstr ""
diff --git a/spec/controllers/projects/import/jira_controller_spec.rb b/spec/controllers/projects/import/jira_controller_spec.rb
index c3bf0c09fba..d1b0a086576 100644
--- a/spec/controllers/projects/import/jira_controller_spec.rb
+++ b/spec/controllers/projects/import/jira_controller_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe Projects::Import::JiraController do
+ include JiraServiceHelper
+
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:jira_project_key) { 'Test' }
@@ -61,6 +63,7 @@ describe Projects::Import::JiraController do
before do
stub_feature_flags(jira_issue_import: true)
stub_feature_flags(jira_issue_import_vue: false)
+ stub_jira_service_test
end
context 'when Jira service is enabled for the project' do
diff --git a/spec/factories/usage_data.rb b/spec/factories/usage_data.rb
index b633038b83b..e75d5bd7d18 100644
--- a/spec/factories/usage_data.rb
+++ b/spec/factories/usage_data.rb
@@ -12,6 +12,11 @@ FactoryBot.define do
create(:jira_service, :jira_cloud_service, project: projects[2])
create(:jira_service, :without_properties_callback, project: projects[3],
properties: { url: 'https://mysite.atlassian.net' })
+ jira_label = create(:label, project: projects[0])
+ create(:jira_import_state, :finished, project: projects[0], label: jira_label, failed_to_import_count: 2, imported_issues_count: 7, total_issue_count: 9)
+ create(:jira_import_state, :finished, project: projects[1], label: jira_label, imported_issues_count: 3, total_issue_count: 3)
+ create(:jira_import_state, :finished, project: projects[1], label: jira_label, imported_issues_count: 3)
+ create(:jira_import_state, :scheduled, project: projects[1], label: jira_label)
create(:prometheus_service, project: projects[1])
create(:service, project: projects[0], type: 'SlackSlashCommandsService', active: true)
create(:service, project: projects[1], type: 'SlackService', active: true)
diff --git a/spec/lib/gitlab/jira_import/base_importer_spec.rb b/spec/lib/gitlab/jira_import/base_importer_spec.rb
index f22efcb8743..ecaf3def589 100644
--- a/spec/lib/gitlab/jira_import/base_importer_spec.rb
+++ b/spec/lib/gitlab/jira_import/base_importer_spec.rb
@@ -3,12 +3,17 @@
require 'spec_helper'
describe Gitlab::JiraImport::BaseImporter do
+ include JiraServiceHelper
+
let(:project) { create(:project) }
describe 'with any inheriting class' do
- context 'when feature flag disabled' do
+ context 'when an error is returned from the project validation' do
before do
stub_feature_flags(jira_issue_import: false)
+
+ allow(project).to receive(:validate_jira_import_settings!)
+ .and_raise(Projects::ImportService::Error, 'Jira import feature is disabled.')
end
it 'raises exception' do
@@ -16,20 +21,17 @@ describe Gitlab::JiraImport::BaseImporter do
end
end
- context 'when feature flag enabled' do
+ context 'when project validation is ok' do
+ let!(:jira_service) { create(:jira_service, project: project) }
+
before do
stub_feature_flags(jira_issue_import: true)
- end
+ stub_jira_service_test
- context 'when Jira service was not setup' do
- it 'raises exception' do
- expect { described_class.new(project) }.to raise_error(Projects::ImportService::Error, 'Jira integration not configured.')
- end
+ allow(project).to receive(:validate_jira_import_settings!)
end
context 'when Jira service exists' do
- let!(:jira_service) { create(:jira_service, project: project) }
-
context 'when Jira import data is not present' do
it 'raises exception' do
expect { described_class.new(project) }.to raise_error(Projects::ImportService::Error, 'Unable to find Jira project to import data from.')
diff --git a/spec/lib/gitlab/jira_import/issues_importer_spec.rb b/spec/lib/gitlab/jira_import/issues_importer_spec.rb
index 8e16fd3e978..a7cf19a9a5b 100644
--- a/spec/lib/gitlab/jira_import/issues_importer_spec.rb
+++ b/spec/lib/gitlab/jira_import/issues_importer_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe Gitlab::JiraImport::IssuesImporter do
+ include JiraServiceHelper
+
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:jira_import) { create(:jira_import_state, project: project) }
@@ -12,6 +14,7 @@ describe Gitlab::JiraImport::IssuesImporter do
before do
stub_feature_flags(jira_issue_import: true)
+ stub_jira_service_test
end
describe '#imported_items_cache_key' do
diff --git a/spec/lib/gitlab/jira_import/labels_importer_spec.rb b/spec/lib/gitlab/jira_import/labels_importer_spec.rb
index 9b24021d8d4..4d33ede136e 100644
--- a/spec/lib/gitlab/jira_import/labels_importer_spec.rb
+++ b/spec/lib/gitlab/jira_import/labels_importer_spec.rb
@@ -3,9 +3,11 @@
require 'spec_helper'
describe Gitlab::JiraImport::LabelsImporter do
- let_it_be(:user) { create(:user) }
- let_it_be(:group) { create(:group) }
- let_it_be(:project) { create(:project, group: group) }
+ include JiraServiceHelper
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
let_it_be(:jira_service) { create(:jira_service, project: project) }
subject { described_class.new(project).execute }
@@ -13,13 +15,14 @@ describe Gitlab::JiraImport::LabelsImporter do
before do
stub_feature_flags(jira_issue_import: true)
stub_const('Gitlab::JiraImport::LabelsImporter::MAX_LABELS', 2)
-
- WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/serverInfo')
- .to_return(body: { url: 'http://url' }.to_json )
end
describe '#execute', :clean_gitlab_redis_cache do
- context 'when jira import label is missing from jira import' do
+ before do
+ stub_jira_service_test
+ end
+
+ context 'when label is missing from jira import' do
let_it_be(:no_label_jira_import) { create(:jira_import_state, label: nil, project: project) }
it 'raises error' do
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index da157eec39f..858ee360d8a 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -44,6 +44,9 @@ describe Gitlab::UsageData, :aggregate_failures do
expect(count_data[:projects_jira_active]).to eq(4)
expect(count_data[:projects_jira_server_active]).to eq(2)
expect(count_data[:projects_jira_cloud_active]).to eq(2)
+ expect(count_data[:jira_imports_projects_count]).to eq(2)
+ expect(count_data[:jira_imports_total_imported_count]).to eq(3)
+ expect(count_data[:jira_imports_total_imported_issues_count]).to eq(13)
expect(count_data[:projects_slack_notifications_active]).to eq(2)
expect(count_data[:projects_slack_slash_active]).to eq(1)
expect(count_data[:projects_slack_active]).to eq(2)
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 18f77592cd6..78c0e8aef1a 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -5945,6 +5945,119 @@ describe Project do
end
end
+ describe '#validate_jira_import_settings!' do
+ include JiraServiceHelper
+
+ let_it_be(:project, reload: true) { create(:project) }
+
+ shared_examples 'raise Jira import error' do |message|
+ it 'returns error' do
+ expect { subject }.to raise_error(Projects::ImportService::Error, message)
+ end
+ end
+
+ shared_examples 'jira configuration base checks' do
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(jira_issue_import: false)
+ end
+
+ it_behaves_like 'raise Jira import error', 'Jira import feature is disabled.'
+ end
+
+ context 'when feature flag is enabled' do
+ before do
+ stub_feature_flags(jira_issue_import: true)
+ end
+
+ context 'when Jira service was not setup' do
+ it_behaves_like 'raise Jira import error', 'Jira integration not configured.'
+ end
+
+ context 'when Jira service exists' do
+ let!(:jira_service) { create(:jira_service, project: project, active: true) }
+
+ context 'when Jira connection is not valid' do
+ 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 'raise Jira import error', 'Unable to connect to the Jira instance. Please check your Jira integration configuration.'
+ end
+ end
+ end
+ end
+
+ before do
+ stub_jira_service_test
+ end
+
+ context 'without user param' do
+ subject { project.validate_jira_import_settings! }
+
+ it_behaves_like 'jira configuration base checks'
+
+ context 'when jira connection is valid' do
+ let!(:jira_service) { create(:jira_service, project: project, active: true) }
+
+ it 'does not return any error' do
+ expect { subject }.not_to raise_error
+ end
+ end
+ end
+
+ context 'with user param provided' do
+ let_it_be(:user) { create(:user) }
+
+ subject { project.validate_jira_import_settings!(user: user) }
+
+ context 'when user has permission to run import' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it_behaves_like 'jira configuration base checks'
+ end
+
+ context 'when feature flag is enabled' do
+ before do
+ stub_feature_flags(jira_issue_import: true)
+ end
+
+ context 'when user does not have permissions to run the import' do
+ before do
+ create(:jira_service, project: project, active: true)
+
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'raise Jira import error', 'You do not have permissions to run the import.'
+ end
+
+ context 'when user has permission to run import' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ let!(:jira_service) { create(:jira_service, project: project, active: true) }
+
+ context 'when issues feature is disabled' do
+ let_it_be(:project, reload: true) { create(:project, :issues_disabled) }
+
+ it_behaves_like 'raise Jira import error', 'Cannot import because issues are not available in this project.'
+ end
+
+ context 'when everything is ok' do
+ it 'does not return any error' do
+ expect { subject }.not_to raise_error
+ end
+ end
+ end
+ end
+ end
+ end
+
def finish_job(export_job)
export_job.start
export_job.finish
diff --git a/spec/requests/api/graphql/mutations/jira_import/start_spec.rb b/spec/requests/api/graphql/mutations/jira_import/start_spec.rb
index c7dcb21ad83..84110098400 100644
--- a/spec/requests/api/graphql/mutations/jira_import/start_spec.rb
+++ b/spec/requests/api/graphql/mutations/jira_import/start_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
describe 'Starting a Jira Import' do
+ include JiraServiceHelper
include GraphqlHelpers
let_it_be(:user) { create(:user) }
@@ -104,6 +105,8 @@ describe 'Starting a Jira Import' do
before do
project.reload
+
+ stub_jira_service_test
end
context 'when issues feature are disabled' do
diff --git a/spec/services/jira_import/start_import_service_spec.rb b/spec/services/jira_import/start_import_service_spec.rb
index 1eefffe11fa..759e4f3363f 100644
--- a/spec/services/jira_import/start_import_service_spec.rb
+++ b/spec/services/jira_import/start_import_service_spec.rb
@@ -3,113 +3,89 @@
require 'spec_helper'
describe JiraImport::StartImportService do
+ include JiraServiceHelper
+
let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project) }
let(:key) { 'KEY' }
subject { described_class.new(user, project, key).execute }
- context 'when feature flag disabled' do
+ context 'when an error is returned from the project validation' do
before do
- stub_feature_flags(jira_issue_import: false)
+ allow(project).to receive(:validate_jira_import_settings!)
+ .and_raise(Projects::ImportService::Error, 'Jira import feature is disabled.')
end
it_behaves_like 'responds with error', 'Jira import feature is disabled.'
end
- context 'when feature flag enabled' do
+ context 'when project validation is ok' do
+ let!(:jira_service) { create(:jira_service, project: project, active: true) }
+
before do
- stub_feature_flags(jira_issue_import: true)
+ stub_jira_service_test
+ allow(project).to receive(:validate_jira_import_settings!)
end
- context 'when user does not have permissions to run the import' do
- before do
- create(:jira_service, project: project, active: true)
+ context 'when Jira project key is not provided' do
+ let(:key) { '' }
- project.add_developer(user)
- end
-
- it_behaves_like 'responds with error', 'You do not have permissions to run the import.'
+ it_behaves_like 'responds with error', 'Unable to find Jira project to import data from.'
end
- context 'when user has permission to run import' do
- before do
- project.add_maintainer(user)
- end
+ context 'when correct data provided' do
+ let(:fake_key) { 'some-key' }
- context 'when Jira service was not setup' do
- it_behaves_like 'responds with error', 'Jira integration not configured.'
- end
+ subject { described_class.new(user, project, fake_key).execute }
- context 'when Jira service exists' do
- let!(:jira_service) { create(:jira_service, project: project, active: true) }
+ context 'when import is already running' do
+ let_it_be(:jira_import_state) { create(:jira_import_state, :started, project: project) }
- context 'when Jira project key is not provided' do
- let(:key) { '' }
+ it_behaves_like 'responds with error', 'Jira import is already running.'
+ end
- it_behaves_like 'responds with error', 'Unable to find Jira project to import data from.'
+ context 'when everything is ok' do
+ it 'returns success response' do
+ expect(subject).to be_a(ServiceResponse)
+ expect(subject).to be_success
end
- context 'when issues feature are disabled' do
- let_it_be(:project, reload: true) { create(:project, :issues_disabled) }
+ it 'schedules Jira import' do
+ subject
- it_behaves_like 'responds with error', 'Cannot import because issues are not available in this project.'
+ expect(project.latest_jira_import).to be_scheduled
end
- context 'when correct data provided' do
- let(:fake_key) { 'some-key' }
-
- subject { described_class.new(user, project, fake_key).execute }
-
- context 'when import is already running' do
- let_it_be(:jira_import_state) { create(:jira_import_state, :started, project: project) }
+ it 'creates Jira import data' do
+ jira_import = subject.payload[:import_data]
- it_behaves_like 'responds with error', 'Jira import is already running.'
- end
-
- context 'when everything is ok' do
- it 'returns success response' do
- expect(subject).to be_a(ServiceResponse)
- expect(subject).to be_success
- end
-
- it 'schedules Jira import' do
- subject
-
- expect(project.latest_jira_import).to be_scheduled
- end
- end
-
- it 'creates Jira import data' do
- jira_import = subject.payload[:import_data]
-
- expect(jira_import.jira_project_xid).to eq(0)
- expect(jira_import.jira_project_name).to eq(fake_key)
- expect(jira_import.jira_project_key).to eq(fake_key)
- expect(jira_import.user).to eq(user)
- end
+ expect(jira_import.jira_project_xid).to eq(0)
+ expect(jira_import.jira_project_name).to eq(fake_key)
+ expect(jira_import.jira_project_key).to eq(fake_key)
+ expect(jira_import.user).to eq(user)
+ end
- it 'creates Jira import label' do
- expect { subject }.to change { Label.count }.by(1)
- end
+ it 'creates Jira import label' do
+ expect { subject }.to change { Label.count }.by(1)
+ end
- it 'creates Jira label title with correct number' do
- jira_import = subject.payload[:import_data]
+ it 'creates Jira label title with correct number' do
+ jira_import = subject.payload[:import_data]
- label_title = "jira-import::#{jira_import.jira_project_key}-1"
- expect(jira_import.label.title).to eq(label_title)
- end
+ label_title = "jira-import::#{jira_import.jira_project_key}-1"
+ expect(jira_import.label.title).to eq(label_title)
+ end
+ end
- context 'when multiple Jira imports for same Jira project' do
- let!(:jira_imports) { create_list(:jira_import_state, 3, :finished, project: project, jira_project_key: fake_key)}
+ context 'when multiple Jira imports for same Jira project' do
+ let!(:jira_imports) { create_list(:jira_import_state, 3, :finished, project: project, jira_project_key: fake_key)}
- it 'creates Jira label title with correct number' do
- jira_import = subject.payload[:import_data]
+ it 'creates Jira label title with correct number' do
+ jira_import = subject.payload[:import_data]
- label_title = "jira-import::#{jira_import.jira_project_key}-4"
- expect(jira_import.label.title).to eq(label_title)
- end
- end
+ label_title = "jira-import::#{jira_import.jira_project_key}-4"
+ expect(jira_import.label.title).to eq(label_title)
end
end
end
diff --git a/spec/support/helpers/jira_service_helper.rb b/spec/support/helpers/jira_service_helper.rb
index c23a8d52c84..198bedfe3bc 100644
--- a/spec/support/helpers/jira_service_helper.rb
+++ b/spec/support/helpers/jira_service_helper.rb
@@ -78,6 +78,11 @@ module JiraServiceHelper
JIRA_API + "/issue/#{issue_id}"
end
+ def stub_jira_service_test
+ WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/serverInfo')
+ .to_return(body: { url: 'http://url' }.to_json)
+ end
+
def stub_jira_urls(issue_id)
WebMock.stub_request(:get, jira_project_url)
WebMock.stub_request(:get, jira_api_comment_url(issue_id)).to_return(body: jira_issue_comments)
diff --git a/spec/workers/gitlab/jira_import/stage/import_issues_worker_spec.rb b/spec/workers/gitlab/jira_import/stage/import_issues_worker_spec.rb
index e19acbebd66..f2067522af4 100644
--- a/spec/workers/gitlab/jira_import/stage/import_issues_worker_spec.rb
+++ b/spec/workers/gitlab/jira_import/stage/import_issues_worker_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe Gitlab::JiraImport::Stage::ImportIssuesWorker do
+ include JiraServiceHelper
+
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, import_type: 'jira') }
@@ -25,6 +27,7 @@ describe Gitlab::JiraImport::Stage::ImportIssuesWorker do
before do
stub_feature_flags(jira_issue_import: true)
+ stub_jira_service_test
end
context 'when import did not start' do
diff --git a/spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb b/spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb
index 505137e9b22..7f289de5422 100644
--- a/spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb
+++ b/spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe Gitlab::JiraImport::Stage::ImportLabelsWorker do
+ include JiraServiceHelper
+
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, import_type: 'jira') }
@@ -36,6 +38,8 @@ describe Gitlab::JiraImport::Stage::ImportLabelsWorker do
let!(:jira_service) { create(:jira_service, project: project) }
before do
+ stub_jira_service_test
+
jira_import.start!
WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/label?maxResults=500&startAt=0')