提交 27b43bd4 编写于 作者: G GitLab Bot

Add latest changes from gitlab-org/gitlab@master

上级 6b8e9712
......@@ -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,
......
......@@ -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
......@@ -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
......
---
title: Remove namespaces.plan_id column
merge_request: 30351
author:
type: other
---
title: Add jira imports to usage data
merge_request: 29925
author:
type: added
---
title: Test Jira connection before running import
merge_request: 29926
author:
type: changed
# 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
......@@ -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
......
# 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\[.*\]: .*'
......@@ -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
......
......@@ -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
......
此差异已折叠。
......@@ -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!
......
......@@ -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": [
],
......
......@@ -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 |
......
......@@ -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]
```
......
......@@ -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.
......
......@@ -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,
......
......@@ -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:
......
......@@ -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. |
......
......@@ -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:
......
......@@ -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
......
......@@ -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 ""
......
......@@ -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
......
......@@ -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)
......
......@@ -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.')
......
......@@ -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
......
......@@ -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
......
......@@ -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)
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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)
......
......@@ -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
......
......@@ -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')
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册