Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-05-10 03:10:37 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-05-10 03:10:37 +0300
commit06d5641a544be4c5605ef2b7dcad43d841386ede (patch)
tree21856b2215a85a171977f9f9e1e4ded12a6ba4af
parent2051d3c9cece72167a237002c309c720924c88cf (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/helpers/preferences_helper.rb18
-rw-r--r--app/models/clusters/applications/prometheus.rb26
-rw-r--r--app/models/clusters/integrations/prometheus.rb38
-rw-r--r--app/models/user.rb2
-rw-r--r--app/services/clusters/applications/prometheus_config_service.rb2
-rw-r--r--app/services/projects/prometheus/alerts/notify_service.rb18
-rw-r--r--app/workers/email_receiver_worker.rb75
-rw-r--r--app/workers/service_desk_email_receiver_worker.rb12
-rw-r--r--changelogs/unreleased/add-alert-manager-token-to-prometheus-cluster-integration.yml5
-rw-r--r--changelogs/unreleased/kassio-add-translation-percentage-level-to-ui.yml5
-rw-r--r--changelogs/unreleased/sh-improve-email-receiver-logging.yml5
-rw-r--r--db/migrate/20210430034712_add_alert_manager_token_to_clusters_integration_prometheus.rb10
-rw-r--r--db/schema_migrations/202104300347121
-rw-r--r--db/structure.sql4
-rw-r--r--doc/development/i18n/merging_translations.md7
-rw-r--r--doc/user/project/import/bitbucket.md35
-rw-r--r--doc/user/project/import/bitbucket_server.md44
-rw-r--r--doc/user/project/import/fogbugz.md16
-rw-r--r--doc/user/project/import/gitea.md28
-rw-r--r--doc/user/project/import/github.md18
-rw-r--r--doc/user/project/import/jira.md4
-rw-r--r--doc/user/project/import/manifest.md4
-rw-r--r--doc/user/project/import/phabricator.md4
-rw-r--r--doc/user/project/import/svn.md16
-rw-r--r--doc/user/project/import/tfvc.md10
-rw-r--r--lib/gitlab/email/receiver.rb84
-rw-r--r--lib/gitlab/email/service_desk_receiver.rb15
-rw-r--r--lib/gitlab/i18n.rb56
-rw-r--r--lib/gitlab/prometheus/adapter.rb8
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/deprecation_toolkit_env.rb1
-rw-r--r--spec/features/profiles/user_edit_preferences_spec.rb19
-rw-r--r--spec/helpers/preferences_helper_spec.rb14
-rw-r--r--spec/lib/gitlab/email/receiver_spec.rb15
-rw-r--r--spec/lib/gitlab/i18n_spec.rb15
-rw-r--r--spec/lib/gitlab/prometheus/adapter_spec.rb4
-rw-r--r--spec/models/clusters/applications/prometheus_spec.rb67
-rw-r--r--spec/models/clusters/integrations/prometheus_spec.rb56
-rw-r--r--spec/services/projects/prometheus/alerts/notify_service_spec.rb36
-rw-r--r--spec/support/stub_languages_translation_percentage.rb19
-rw-r--r--spec/workers/email_receiver_worker_spec.rb21
-rw-r--r--spec/workers/service_desk_email_receiver_worker_spec.rb6
42 files changed, 577 insertions, 269 deletions
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index add6e1eaf6f..6fc2dfb597b 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -4,8 +4,8 @@
module PreferencesHelper
def layout_choices
[
- ['Fixed', :fixed],
- ['Fluid', :fluid]
+ ['Fixed', :fixed],
+ ['Fluid', :fluid]
]
end
@@ -76,7 +76,7 @@ module PreferencesHelper
def language_choices
options_for_select(
- Gitlab::I18n.selectable_locales.map(&:reverse).sort,
+ selectable_locales_with_translation_level.sort,
current_user.preferred_language
)
end
@@ -107,6 +107,18 @@ module PreferencesHelper
def default_first_day_of_week
first_day_of_week_choices.rassoc(Gitlab::CurrentSettings.first_day_of_week).first
end
+
+ def selectable_locales_with_translation_level
+ Gitlab::I18n.selectable_locales.map do |code, language|
+ [
+ s_("i18n|%{language} (%{percent_translated}%% translated)") % {
+ language: language,
+ percent_translated: Gitlab::I18n.percentage_translated_for(code)
+ },
+ code
+ ]
+ end
+ end
end
PreferencesHelper.prepend_if_ee('EE::PreferencesHelper')
diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb
index 2b5390b981f..21f7e410843 100644
--- a/app/models/clusters/applications/prometheus.rb
+++ b/app/models/clusters/applications/prometheus.rb
@@ -25,18 +25,15 @@ module Clusters
key: Settings.attr_encrypted_db_key_base_32,
algorithm: 'aes-256-gcm'
+ default_value_for(:alert_manager_token) { SecureRandom.hex }
+
after_destroy do
- run_after_commit do
- disable_prometheus_integration
- end
+ cluster.find_or_build_integration_prometheus.destroy
end
state_machine :status do
after_transition any => [:installed, :externally_installed] do |application|
- application.run_after_commit do
- Clusters::Applications::ActivateServiceWorker
- .perform_async(application.cluster_id, ::PrometheusService.to_param) # rubocop:disable CodeReuse/ServiceClass
- end
+ application.cluster.find_or_build_integration_prometheus.update(enabled: true, alert_manager_token: application.alert_manager_token)
end
after_transition any => :updating do |application|
@@ -103,23 +100,8 @@ module Clusters
files.merge('values.yaml': replaced_values)
end
- def generate_alert_manager_token!
- unless alert_manager_token.present?
- update!(alert_manager_token: generate_token)
- end
- end
-
private
- def generate_token
- SecureRandom.hex
- end
-
- def disable_prometheus_integration
- ::Clusters::Applications::DeactivateServiceWorker
- .perform_async(cluster_id, ::PrometheusService.to_param) # rubocop:disable CodeReuse/ServiceClass
- end
-
def install_knative_metrics
return [] unless cluster.application_knative_available?
diff --git a/app/models/clusters/integrations/prometheus.rb b/app/models/clusters/integrations/prometheus.rb
index 1496d8ff1dd..0a01ac5d1ce 100644
--- a/app/models/clusters/integrations/prometheus.rb
+++ b/app/models/clusters/integrations/prometheus.rb
@@ -4,6 +4,7 @@ module Clusters
module Integrations
class Prometheus < ApplicationRecord
include ::Clusters::Concerns::PrometheusClient
+ include AfterCommitQueue
self.table_name = 'clusters_integration_prometheus'
self.primary_key = :cluster_id
@@ -13,9 +14,46 @@ module Clusters
validates :cluster, presence: true
validates :enabled, inclusion: { in: [true, false] }
+ attr_encrypted :alert_manager_token,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_32,
+ algorithm: 'aes-256-gcm'
+
+ default_value_for(:alert_manager_token) { SecureRandom.hex }
+
+ after_destroy do
+ run_after_commit do
+ deactivate_project_services
+ end
+ end
+
+ after_save do
+ next unless enabled_before_last_save != enabled
+
+ run_after_commit do
+ if enabled
+ activate_project_services
+ else
+ deactivate_project_services
+ end
+ end
+ end
+
def available?
enabled?
end
+
+ private
+
+ def activate_project_services
+ ::Clusters::Applications::ActivateServiceWorker
+ .perform_async(cluster_id, ::PrometheusService.to_param) # rubocop:disable CodeReuse/ServiceClass
+ end
+
+ def deactivate_project_services
+ ::Clusters::Applications::DeactivateServiceWorker
+ .perform_async(cluster_id, ::PrometheusService.to_param) # rubocop:disable CodeReuse/ServiceClass
+ end
end
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 581a1bd893b..c7ad4dcff8a 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -433,7 +433,7 @@ class User < ApplicationRecord
def preferred_language
read_attribute('preferred_language') ||
- I18n.default_locale.to_s.presence_in(Gitlab::I18n::AVAILABLE_LANGUAGES.keys) ||
+ I18n.default_locale.to_s.presence_in(Gitlab::I18n.available_locales) ||
'en'
end
diff --git a/app/services/clusters/applications/prometheus_config_service.rb b/app/services/clusters/applications/prometheus_config_service.rb
index 50c4e26b0d0..d39d63c874f 100644
--- a/app/services/clusters/applications/prometheus_config_service.rb
+++ b/app/services/clusters/applications/prometheus_config_service.rb
@@ -96,8 +96,6 @@ module Clusters
end
def alert_manager_token
- app.generate_alert_manager_token!
-
app.alert_manager_token
end
diff --git a/app/services/projects/prometheus/alerts/notify_service.rb b/app/services/projects/prometheus/alerts/notify_service.rb
index 93165a58470..db640a54745 100644
--- a/app/services/projects/prometheus/alerts/notify_service.rb
+++ b/app/services/projects/prometheus/alerts/notify_service.rb
@@ -63,7 +63,7 @@ module Projects
def valid_alert_manager_token?(token, integration)
valid_for_manual?(token) ||
valid_for_alerts_endpoint?(token, integration) ||
- valid_for_managed?(token)
+ valid_for_cluster?(token)
end
def valid_for_manual?(token)
@@ -83,18 +83,20 @@ module Projects
compare_token(token, integration.token)
end
- def valid_for_managed?(token)
- prometheus_application = available_prometheus_application(project)
- return false unless prometheus_application
+ def valid_for_cluster?(token)
+ cluster_integration = find_cluster_integration(project)
+ return false unless cluster_integration
+
+ cluster_integration_token = cluster_integration.alert_manager_token
if token
- compare_token(token, prometheus_application.alert_manager_token)
+ compare_token(token, cluster_integration_token)
else
- prometheus_application.alert_manager_token.nil?
+ cluster_integration_token.nil?
end
end
- def available_prometheus_application(project)
+ def find_cluster_integration(project)
alert_id = gitlab_alert_id
return unless alert_id
@@ -105,7 +107,7 @@ module Projects
return unless cluster&.enabled?
return unless cluster.application_prometheus_available?
- cluster.application_prometheus
+ cluster.application_prometheus || cluster.integration_prometheus
end
def find_alert(project, metric)
diff --git a/app/workers/email_receiver_worker.rb b/app/workers/email_receiver_worker.rb
index 618054e8350..37ed1001c9d 100644
--- a/app/workers/email_receiver_worker.rb
+++ b/app/workers/email_receiver_worker.rb
@@ -9,21 +9,80 @@ class EmailReceiverWorker # rubocop:disable Scalability/IdempotentWorker
urgency :high
weight 2
+ attr_accessor :raw
+
def perform(raw)
- return unless Gitlab::IncomingEmail.enabled?
+ return unless should_perform?
- begin
- Gitlab::Email::Receiver.new(raw).execute
- rescue StandardError => e
- handle_failure(raw, e)
- end
+ @raw = raw
+ execute_receiver
+ end
+
+ def should_perform?
+ Gitlab::IncomingEmail.enabled?
end
private
- def handle_failure(raw, error)
- Gitlab::AppLogger.warn("Email can not be processed: #{error}\n\n#{raw}")
+ def execute_receiver
+ receiver.execute
+ log_success
+ rescue StandardError => e
+ log_error(e)
+ handle_failure(e)
+ end
+
+ def receiver
+ @receiver ||= Gitlab::Email::Receiver.new(raw)
+ end
+
+ def logger
+ Sidekiq.logger
+ end
+
+ def log_success
+ logger.info(build_message('Successfully processed message', receiver.mail_metadata))
+ end
+
+ def log_error(error)
+ payload =
+ case error
+ # Unparsable e-mails don't have metadata we can use
+ when Gitlab::Email::EmailUnparsableError, Gitlab::Email::EmptyEmailError
+ {}
+ else
+ mail_metadata
+ end
+
+ # We don't need the backtrace and more details if the e-mail couldn't be processed
+ if error.is_a?(Gitlab::Email::ProcessingError)
+ payload['exception.class'] = error.class.name
+ else
+ Gitlab::ExceptionLogFormatter.format!(error, payload)
+ Gitlab::ErrorTracking.track_exception(error)
+ end
+
+ logger.error(build_message('Error processing message', payload))
+ end
+
+ def build_message(message, params = {})
+ {
+ class: self.class.name,
+ Labkit::Correlation::CorrelationId::LOG_KEY => Labkit::Correlation::CorrelationId.current_id,
+ message: message
+ }.merge(params)
+ end
+
+ def mail_metadata
+ receiver.mail_metadata
+ rescue StandardError => e
+ # We should never get here as long as we check EmailUnparsableError, but
+ # let's be defensive in case we did something wrong.
+ Gitlab::ErrorTracking.track_exception(e)
+ {}
+ end
+ def handle_failure(error)
return unless raw.present?
can_retry = false
diff --git a/app/workers/service_desk_email_receiver_worker.rb b/app/workers/service_desk_email_receiver_worker.rb
index 6e1609d6376..e1ef9adc24c 100644
--- a/app/workers/service_desk_email_receiver_worker.rb
+++ b/app/workers/service_desk_email_receiver_worker.rb
@@ -5,13 +5,11 @@ class ServiceDeskEmailReceiverWorker < EmailReceiverWorker # rubocop:disable Sca
sidekiq_options retry: 3
- def perform(raw)
- return unless ::Gitlab::ServiceDeskEmail.enabled?
+ def should_perform?
+ ::Gitlab::ServiceDeskEmail.enabled?
+ end
- begin
- Gitlab::Email::ServiceDeskReceiver.new(raw).execute
- rescue StandardError => e
- handle_failure(raw, e)
- end
+ def receiver
+ @receiver ||= Gitlab::Email::ServiceDeskReceiver.new(raw)
end
end
diff --git a/changelogs/unreleased/add-alert-manager-token-to-prometheus-cluster-integration.yml b/changelogs/unreleased/add-alert-manager-token-to-prometheus-cluster-integration.yml
new file mode 100644
index 00000000000..d6e6892540b
--- /dev/null
+++ b/changelogs/unreleased/add-alert-manager-token-to-prometheus-cluster-integration.yml
@@ -0,0 +1,5 @@
+---
+title: Keep new prometheus cluster integration in sync with old cluster application
+merge_request: 60877
+author:
+type: changed
diff --git a/changelogs/unreleased/kassio-add-translation-percentage-level-to-ui.yml b/changelogs/unreleased/kassio-add-translation-percentage-level-to-ui.yml
new file mode 100644
index 00000000000..545bac66c9b
--- /dev/null
+++ b/changelogs/unreleased/kassio-add-translation-percentage-level-to-ui.yml
@@ -0,0 +1,5 @@
+---
+title: 'i18n: Show translation levels for each language in the UI'
+merge_request: 60905
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-improve-email-receiver-logging.yml b/changelogs/unreleased/sh-improve-email-receiver-logging.yml
new file mode 100644
index 00000000000..4394b76be4d
--- /dev/null
+++ b/changelogs/unreleased/sh-improve-email-receiver-logging.yml
@@ -0,0 +1,5 @@
+---
+title: Improve logging in e-mail receiver processing
+merge_request: 60692
+author:
+type: added
diff --git a/db/migrate/20210430034712_add_alert_manager_token_to_clusters_integration_prometheus.rb b/db/migrate/20210430034712_add_alert_manager_token_to_clusters_integration_prometheus.rb
new file mode 100644
index 00000000000..48ab860a63b
--- /dev/null
+++ b/db/migrate/20210430034712_add_alert_manager_token_to_clusters_integration_prometheus.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class AddAlertManagerTokenToClustersIntegrationPrometheus < ActiveRecord::Migration[6.0]
+ def change
+ change_table :clusters_integration_prometheus do |t|
+ t.text :encrypted_alert_manager_token
+ t.text :encrypted_alert_manager_token_iv
+ end
+ end
+end
diff --git a/db/schema_migrations/20210430034712 b/db/schema_migrations/20210430034712
new file mode 100644
index 00000000000..df9fe0755cf
--- /dev/null
+++ b/db/schema_migrations/20210430034712
@@ -0,0 +1 @@
+6b7436d7712e31ca116204d37270435ccc059ca75a128750e5c39fdddfa020e3 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 976ac394aae..332682b9eb9 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -11701,7 +11701,9 @@ CREATE TABLE clusters_integration_prometheus (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
cluster_id bigint NOT NULL,
- enabled boolean DEFAULT false NOT NULL
+ enabled boolean DEFAULT false NOT NULL,
+ encrypted_alert_manager_token text,
+ encrypted_alert_manager_token_iv text
);
CREATE TABLE clusters_kubernetes_namespaces (
diff --git a/doc/development/i18n/merging_translations.md b/doc/development/i18n/merging_translations.md
index 553820733e7..48474a68d16 100644
--- a/doc/development/i18n/merging_translations.md
+++ b/doc/development/i18n/merging_translations.md
@@ -78,3 +78,10 @@ recreate it with the following steps:
1. Select the `gitlab-org/gitlab` repository.
1. In `Select Branches for Translation`, select `master`.
1. Ensure the `Service Branch Name` is `master-i18n`.
+
+## Manually update the translation levels
+
+There's no automated way to pull the translation levels from CrowdIn, to display
+this information in the language selection dropdown. Therefore, the translation
+levels are hard-coded in the `TRANSLATION_LEVELS` constant in [`i18n.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/i18n.rb),
+and must be regularly updated.
diff --git a/doc/user/project/import/bitbucket.md b/doc/user/project/import/bitbucket.md
index 6f274dd12a2..e77932c6427 100644
--- a/doc/user/project/import/bitbucket.md
+++ b/doc/user/project/import/bitbucket.md
@@ -14,26 +14,27 @@ Server (aka Stash). If you are trying to import projects from Bitbucket Server,
Import your projects from Bitbucket Cloud to GitLab with minimal effort.
-## Overview
-
-- At its current state, the Bitbucket importer can import:
- - the repository description (GitLab 7.7+)
- - the Git repository data (GitLab 7.7+)
- - the issues (GitLab 7.7+)
- - the issue comments (GitLab 8.15+)
- - the pull requests (GitLab 8.4+)
- - the pull request comments (GitLab 8.15+)
- - the milestones (GitLab 8.15+)
- - the wiki (GitLab 8.15+)
-- References to pull requests and issues are preserved (GitLab 8.7+)
-- Repository public access is retained. If a repository is private in Bitbucket
- it will be created as private in GitLab as well.
+The Bitbucket importer can import:
+
+- Repository description (GitLab 7.7+)
+- Git repository data (GitLab 7.7+)
+- Issues (GitLab 7.7+)
+- Issue comments (GitLab 8.15+)
+- Pull requests (GitLab 8.4+)
+- Pull request comments (GitLab 8.15+)
+- Milestones (GitLab 8.15+)
+- Wiki (GitLab 8.15+)
+
+When importing:
+
+- References to pull requests and issues are preserved (GitLab 8.7+).
+- Repository public access is retained. If a repository is private in Bitbucket, it's created as
+ private in GitLab as well.
## Requirements
-The [Bitbucket Cloud integration](../../../integration/bitbucket.md) must be first enabled in order to be
-able to import your projects from Bitbucket Cloud. Ask your GitLab administrator
-to enable this if not already.
+To import your projects from Bitbucket Cloud, the [Bitbucket Cloud integration](../../../integration/bitbucket.md)
+must be enabled. Ask your GitLab administrator to enable this if it isn't already enabled.
## How it works
diff --git a/doc/user/project/import/bitbucket_server.md b/doc/user/project/import/bitbucket_server.md
index 9e0d30f4f76..330ed0cb774 100644
--- a/doc/user/project/import/bitbucket_server.md
+++ b/doc/user/project/import/bitbucket_server.md
@@ -15,31 +15,31 @@ Use the [Bitbucket Cloud importer](bitbucket.md) for that.
Import your projects from Bitbucket Server to GitLab with minimal effort.
-## Overview
+The Bitbucket importer can import:
-- In its current state, the Bitbucket importer can import:
- - the repository description (GitLab 11.2+)
- - the Git repository data (GitLab 11.2+)
- - the pull requests (GitLab 11.2+)
- - the pull request comments (GitLab 11.2+)
-- Repository public access is retained. If a repository is private in Bitbucket
- it will be created as private in GitLab as well.
+- Repository description (GitLab 11.2+)
+- Git repository data (GitLab 11.2+)
+- Pull requests (GitLab 11.2+)
+- Pull request comments (GitLab 11.2+)
+
+When importing:
+
+- Repository public access is retained. If a repository is private in Bitbucket, it's created as
+ private in GitLab as well.
## Limitations
-1. Currently GitLab doesn't allow comments on arbitrary lines of code, so any
- Bitbucket comments out of bounds are inserted as comments in the merge
- request.
-1. Bitbucket Server allows multiple levels of threading. GitLab import
- collapses this into one thread and quote part of the original comment.
-1. Declined pull requests have unreachable commits, which prevents the GitLab
- importer from generating a proper diff. These pull requests show up as
- empty changes.
-1. Attachments in Markdown are currently not imported.
-1. Task lists are not imported.
-1. Emoji reactions are not imported
-1. Project filtering does not support fuzzy search (only `starts with` or `full
- match strings` are currently supported)
+- GitLab doesn't allow comments on arbitrary lines of code, so any Bitbucket comments out of bounds
+ are inserted as comments in the merge request.
+- Bitbucket Server allows multiple levels of threading. GitLab import collapses this into one thread
+ and quote part of the original comment.
+- Declined pull requests have unreachable commits, which prevents the GitLab importer from
+ generating a proper diff. These pull requests show up as empty changes.
+- Attachments in Markdown are not imported.
+- Task lists are not imported.
+- Emoji reactions are not imported.
+- Project filtering does not support fuzzy search (only `starts with` or `full match strings` are
+ supported).
## How it works
@@ -104,7 +104,7 @@ To disable it:
Feature.disable(:bitbucket_server_user_mapping_by_username)
```
-## Importing your Bitbucket repositories
+## Import your Bitbucket repositories
1. Sign in to GitLab and go to your dashboard.
1. Click on **New project**.
diff --git a/doc/user/project/import/fogbugz.md b/doc/user/project/import/fogbugz.md
index 1371ca57bc9..09505d94a8c 100644
--- a/doc/user/project/import/fogbugz.md
+++ b/doc/user/project/import/fogbugz.md
@@ -8,12 +8,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Import your project from FogBugz to GitLab
It only takes a few simple steps to import your project from FogBugz.
-The importer will import all of your cases and comments with original case
-numbers and timestamps. You will also have the opportunity to map FogBugz
-users to GitLab users.
+The importer imports all your cases and comments with original case
+numbers and timestamps. You can also map FogBugz users to GitLab users.
-1. From your GitLab dashboard click 'New project'
-1. Click on the 'FogBugz' button
+Follow these steps to import your project from FogBugz:
+
+1. From your GitLab dashboard, select **New project**.
+
+1. Select the **FogBugz** button.
![FogBugz](img/fogbugz_import_select_fogbogz.png)
@@ -25,11 +27,11 @@ users to GitLab users.
![User Map](img/fogbugz_import_user_map.png)
-1. Select the projects you wish to import by clicking the Import buttons
+1. Select the projects you wish to import by selecting the **Import** buttons.
![Import Project](img/fogbugz_import_select_project.png)
-1. Once the import has finished click the link to take you to the project
+1. Once the import finishes, click the link to go to the project
dashboard. Follow the directions to push your existing repository.
![Finished](img/fogbugz_import_finished.png)
diff --git a/doc/user/project/import/gitea.md b/doc/user/project/import/gitea.md
index 5a69a9ff977..255d083be6f 100644
--- a/doc/user/project/import/gitea.md
+++ b/doc/user/project/import/gitea.md
@@ -9,20 +9,22 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Import your projects from Gitea to GitLab with minimal effort.
-## Overview
-
NOTE:
This requires Gitea `v1.0.0` or newer.
-- At its current state, Gitea importer can import:
- - the repository description (GitLab 8.15+)
- - the Git repository data (GitLab 8.15+)
- - the issues (GitLab 8.15+)
- - the pull requests (GitLab 8.15+)
- - the milestones (GitLab 8.15+)
- - the labels (GitLab 8.15+)
-- Repository public access is retained. If a repository is private in Gitea
- it will be created as private in GitLab as well.
+The Gitea importer can import:
+
+- Repository description (GitLab 8.15+)
+- Git repository data (GitLab 8.15+)
+- Issues (GitLab 8.15+)
+- Pull requests (GitLab 8.15+)
+- Milestones (GitLab 8.15+)
+- Labels (GitLab 8.15+)
+
+When importing:
+
+- Repository public access is retained. If a repository is private in Gitea it's created as private
+ in GitLab as well.
## How it works
@@ -35,13 +37,13 @@ The importer creates any new namespaces (groups) if they don't exist or in
the case the namespace is taken, the repository is imported under the user's
namespace that started the import process.
-## Importing your Gitea repositories
+## Import your Gitea repositories
The importer page is visible when you create a new project.
![New project page on GitLab](img/import_projects_from_new_project_page.png)
-Click on the **Gitea** link and the import authorization process starts.
+Click the **Gitea** link and the import authorization process starts.
![New Gitea project import](img/import_projects_from_gitea_new_import.png)
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index b5b461b16c1..c8b973b673e 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -10,8 +10,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Using the importer, you can import your GitHub repositories to GitLab.com or to
your self-managed GitLab instance.
-## Overview
-
The following aspects of a project are imported:
- Repository description (GitLab.com & 7.7+)
@@ -37,12 +35,12 @@ The namespace is a user or group in GitLab, such as `gitlab.com/janedoe` or `git
This process does not migrate or import any types of groups or organizations from GitHub to GitLab.
-### Use cases
+## Use cases
The steps you take depend on whether you are importing from GitHub.com or GitHub Enterprise, as well as whether you are importing to GitLab.com or self-managed GitLab instance.
- If you're importing to GitLab.com, you can alternatively import GitHub repositories
- using a [personal access token](#using-a-github-token). We do not recommend
+ using a [personal access token](#use-a-github-token). We do not recommend
this method, as it does not associate all user activity (such as issues and
pull requests) with matching GitLab users.
- If you're importing to a self-managed GitLab instance, you can alternatively use the
@@ -93,7 +91,7 @@ For an overview of the import process, see the video [Migrating from GitHub to G
## Import your GitHub repository into GitLab
-### Using the GitHub integration
+### Use the GitHub integration
Before you begin, ensure that any GitHub users who you want to map to GitLab users have either:
@@ -112,9 +110,9 @@ If you are using a self-managed GitLab instance or if you are importing from Git
1. Select the **Import project** tab and then select **GitHub**.
1. Select the first button to **List your GitHub repositories**. You are redirected to a page on [GitHub](https://github.com) to authorize the GitLab application.
1. Click **Authorize GitlabHQ**. You are redirected back to the GitLab Import page and all of your GitHub repositories are listed.
-1. Continue on to [selecting which repositories to import](#selecting-which-repositories-to-import).
+1. Continue on to [selecting which repositories to import](#select-which-repositories-to-import).
-### Using a GitHub token
+### Use a GitHub token
NOTE:
Using a personal access token to import projects is not recommended. If you are a GitLab.com user,
@@ -122,7 +120,7 @@ you can use a personal access token to import your project from GitHub, but this
associate all user activity (such as issues and pull requests) with matching GitLab users.
If you are an administrator of a self-managed GitLab instance or if you are importing from
GitHub Enterprise, you cannot use a personal access token.
-The [GitHub integration method (above)](#using-the-github-integration) is recommended for all users.
+The [GitHub integration method (above)](#use-the-github-integration) is recommended for all users.
Read more in the [How it works](#how-it-works) section.
If you are not using the GitHub integration, you can still perform an authorization with GitHub to grant GitLab access your repositories:
@@ -136,7 +134,7 @@ If you are not using the GitHub integration, you can still perform an authorizat
1. Hit the **List Your GitHub Repositories** button and wait while GitLab reads your repositories' information.
Once done, you'll be taken to the importer page to select the repositories to import.
-### Selecting which repositories to import
+### Select which repositories to import
After you have authorized access to your GitHub repositories, you are redirected to the GitHub importer page and
your GitHub repositories are listed.
@@ -162,7 +160,7 @@ Additionally, you can configure GitLab to send pipeline status updates back GitH
If you import your project using [CI/CD for external repository](../../../ci/ci_cd_for_external_repos/index.md), then both
of the above are automatically configured. **(PREMIUM)**
-## Improving the speed of imports on self-managed instances
+## Improve the speed of imports on self-managed instances
NOTE:
Administrator access to the GitLab server is required.
diff --git a/doc/user/project/import/jira.md b/doc/user/project/import/jira.md
index 5fb737cf74a..6b8c34fada6 100644
--- a/doc/user/project/import/jira.md
+++ b/doc/user/project/import/jira.md
@@ -54,13 +54,13 @@ Make sure you have the integration set up before trying to import Jira issues.
> New import form [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216145) in GitLab 13.2.
-To import Jira issues to a GitLab project, follow the steps below.
-
NOTE:
Importing Jira issues is done as an asynchronous background job, which
may result in delays based on import queues load, system load, or other factors.
Importing large projects may take several minutes depending on the size of the import.
+To import Jira issues to a GitLab project, follow these steps:
+
1. On the **{issues}** **Issues** page, click **Import Issues** (**{import}**) **> Import from Jira**.
![Import issues from Jira button](img/jira/import_issues_from_jira_button_v12_10.png)
diff --git a/doc/user/project/import/manifest.md b/doc/user/project/import/manifest.md
index a116cc83a8e..0c383a8baec 100644
--- a/doc/user/project/import/manifest.md
+++ b/doc/user/project/import/manifest.md
@@ -49,9 +49,9 @@ As a result, the following projects are created:
| `https://gitlab.com/YOUR_GROUP/build/make` | <https://android.googlesource.com/platform/build> |
| `https://gitlab.com/YOUR_GROUP/build/blueprint` | <https://android.googlesource.com/platform/build/blueprint> |
-## Importing the repositories
+## Import the repositories
-You can start the import with:
+Follow these steps to start the import:
1. From your GitLab dashboard click **New project**
1. Switch to the **Import project** tab
diff --git a/doc/user/project/import/phabricator.md b/doc/user/project/import/phabricator.md
index 91fd7b8928b..30a63a72cf9 100644
--- a/doc/user/project/import/phabricator.md
+++ b/doc/user/project/import/phabricator.md
@@ -20,7 +20,7 @@ GitLab allows you to import all tasks from a Phabricator instance into
GitLab issues. The import creates a single project with the
repository disabled.
-Currently, only the following basic fields are imported:
+Only the following basic fields are imported:
- Title
- Description
@@ -34,6 +34,6 @@ The assignee and author of a user are deducted from a Task's owner and
author: If a user with the same username has access to the namespace
of the project being imported into, then the user will be linked.
-## Enabling this feature
+## Enable this feature
Enable Phabricator as an [import source](../../admin_area/settings/visibility_and_access_controls.md#import-sources) in the Admin Area.
diff --git a/doc/user/project/import/svn.md b/doc/user/project/import/svn.md
index 8be69cdeb79..2a58a52ce2c 100644
--- a/doc/user/project/import/svn.md
+++ b/doc/user/project/import/svn.md
@@ -11,18 +11,16 @@ Subversion (SVN) is a central version control system (VCS) while
Git is a distributed version control system. There are some major differences
between the two, for more information consult your favorite search engine.
-## Overview
-
There are two approaches to SVN to Git migration:
-1. [Git/SVN Mirror](#smooth-migration-with-a-gitsvn-mirror-using-subgit) which:
- - Makes the GitLab repository to mirror the SVN project.
- - Git and SVN repositories are kept in sync; you can use either one.
- - Smoothens the migration process and allows to manage migration risks.
+- [Git/SVN Mirror](#smooth-migration-with-a-gitsvn-mirror-using-subgit) which:
+ - Makes the GitLab repository to mirror the SVN project.
+ - Git and SVN repositories are kept in sync; you can use either one.
+ - Smoothens the migration process and allows to manage migration risks.
-1. [Cut over migration](#cut-over-migration-with-svn2git) which:
- - Translates and imports the existing data and history from SVN to Git.
- - Is a fire and forget approach, good for smaller teams.
+- [Cut over migration](#cut-over-migration-with-svn2git) which:
+ - Translates and imports the existing data and history from SVN to Git.
+ - Is a fire and forget approach, good for smaller teams.
## Smooth migration with a Git/SVN mirror using SubGit
diff --git a/doc/user/project/import/tfvc.md b/doc/user/project/import/tfvc.md
index 0d347a16697..ef44989d7f2 100644
--- a/doc/user/project/import/tfvc.md
+++ b/doc/user/project/import/tfvc.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: concepts
---
-# Migrating from TFVC to Git
+# Migrate from TFVC to Git
Team Foundation Server (TFS), renamed [Azure DevOps Server](https://azure.microsoft.com/en-us/services/devops/server/)
in 2019, is a set of tools developed by Microsoft which also includes
@@ -48,10 +48,10 @@ Migration options from TFVC to Git depend on your operating system.
- If you're migrating on Microsoft Windows:
- Use the [`git-tfs`](https://github.com/git-tfs/git-tfs)
-tool.
- Read the [Migrate TFS to Git](https://github.com/git-tfs/git-tfs/blob/master/doc/usecases/migrate_tfs_to_git.md) guide for details.
+ - Use the [`git-tfs`](https://github.com/git-tfs/git-tfs)
+ tool. See [Migrate TFS to Git](https://github.com/git-tfs/git-tfs/blob/master/doc/usecases/migrate_tfs_to_git.md)
+ for details.
- If you're on a Unix-based system:
- Follow the procedures described with this [TFVC to Git migration tool](https://github.com/turbo/gtfotfs).
+ - Follow the procedures described with this [TFVC to Git migration tool](https://github.com/turbo/gtfotfs).
diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb
index f5e47b43a9a..71db8ab6067 100644
--- a/lib/gitlab/email/receiver.rb
+++ b/lib/gitlab/email/receiver.rb
@@ -6,6 +6,8 @@ require_dependency 'gitlab/email/handler'
module Gitlab
module Email
class Receiver
+ include Gitlab::Utils::StrongMemoize
+
def initialize(raw)
@raw = raw
end
@@ -13,11 +15,7 @@ module Gitlab
def execute
raise EmptyEmailError if @raw.blank?
- mail = build_mail
-
- ignore_auto_reply!(mail)
-
- handler = find_handler(mail)
+ ignore_auto_reply!
raise UnknownIncomingEmail unless handler
@@ -26,13 +24,33 @@ module Gitlab
end
end
+ def mail_metadata
+ {
+ mail_uid: mail.message_id,
+ from_address: mail.from,
+ to_address: mail.to,
+ mail_key: mail_key,
+ references: Array(mail.references),
+ delivered_to: delivered_to.map(&:value),
+ envelope_to: envelope_to.map(&:value),
+ x_envelope_to: x_envelope_to.map(&:value)
+ }
+ end
+
private
- def find_handler(mail)
- mail_key = extract_mail_key(mail)
+ def handler
+ strong_memoize(:handler) { find_handler }
+ end
+
+ def find_handler
Handler.for(mail, mail_key)
end
+ def mail
+ strong_memoize(:mail) { build_mail }
+ end
+
def build_mail
Mail::Message.new(@raw)
rescue Encoding::UndefinedConversionError,
@@ -40,22 +58,24 @@ module Gitlab
raise EmailUnparsableError, e
end
- def extract_mail_key(mail)
- key_from_to_header(mail) || key_from_additional_headers(mail)
+ def mail_key
+ strong_memoize(:mail_key) do
+ key_from_to_header || key_from_additional_headers
+ end
end
- def key_from_to_header(mail)
+ def key_from_to_header
mail.to.find do |address|
key = Gitlab::IncomingEmail.key_from_address(address)
break key if key
end
end
- def key_from_additional_headers(mail)
- find_key_from_references(mail) ||
- find_key_from_delivered_to_header(mail) ||
- find_key_from_envelope_to_header(mail) ||
- find_key_from_x_envelope_to_header(mail)
+ def key_from_additional_headers
+ find_key_from_references ||
+ find_key_from_delivered_to_header ||
+ find_key_from_envelope_to_header ||
+ find_key_from_x_envelope_to_header
end
def ensure_references_array(references)
@@ -71,41 +91,53 @@ module Gitlab
end
end
- def find_key_from_references(mail)
+ def find_key_from_references
ensure_references_array(mail.references).find do |mail_id|
key = Gitlab::IncomingEmail.key_from_fallback_message_id(mail_id)
break key if key
end
end
- def find_key_from_delivered_to_header(mail)
- Array(mail[:delivered_to]).find do |header|
+ def delivered_to
+ Array(mail[:delivered_to])
+ end
+
+ def envelope_to
+ Array(mail[:envelope_to])
+ end
+
+ def x_envelope_to
+ Array(mail[:x_envelope_to])
+ end
+
+ def find_key_from_delivered_to_header
+ delivered_to.find do |header|
key = Gitlab::IncomingEmail.key_from_address(header.value)
break key if key
end
end
- def find_key_from_envelope_to_header(mail)
- Array(mail[:envelope_to]).find do |header|
+ def find_key_from_envelope_to_header
+ envelope_to.find do |header|
key = Gitlab::IncomingEmail.key_from_address(header.value)
break key if key
end
end
- def find_key_from_x_envelope_to_header(mail)
- Array(mail[:x_envelope_to]).find do |header|
+ def find_key_from_x_envelope_to_header
+ x_envelope_to.find do |header|
key = Gitlab::IncomingEmail.key_from_address(header.value)
break key if key
end
end
- def ignore_auto_reply!(mail)
- if auto_submitted?(mail) || auto_replied?(mail)
+ def ignore_auto_reply!
+ if auto_submitted? || auto_replied?
raise AutoGeneratedEmailError
end
end
- def auto_submitted?(mail)
+ def auto_submitted?
# Mail::Header#[] is case-insensitive
auto_submitted = mail.header['Auto-Submitted']&.value
@@ -114,7 +146,7 @@ module Gitlab
auto_submitted && auto_submitted != 'no'
end
- def auto_replied?(mail)
+ def auto_replied?
autoreply = mail.header['X-Autoreply']&.value
autoreply && autoreply == 'yes'
diff --git a/lib/gitlab/email/service_desk_receiver.rb b/lib/gitlab/email/service_desk_receiver.rb
index 1ee5c10097b..133c4ee4b45 100644
--- a/lib/gitlab/email/service_desk_receiver.rb
+++ b/lib/gitlab/email/service_desk_receiver.rb
@@ -5,14 +5,19 @@ module Gitlab
class ServiceDeskReceiver < Receiver
private
- def find_handler(mail)
- key = service_desk_key(mail)
- return unless key
+ def find_handler
+ return unless service_desk_key
- Gitlab::Email::Handler::ServiceDeskHandler.new(mail, nil, service_desk_key: key)
+ Gitlab::Email::Handler::ServiceDeskHandler.new(mail, nil, service_desk_key: service_desk_key)
end
- def service_desk_key(mail)
+ def service_desk_key
+ strong_memoize(:service_desk_key) do
+ find_service_desk_key
+ end
+ end
+
+ def find_service_desk_key
mail.to.find do |address|
key = ::Gitlab::ServiceDeskEmail.key_from_address(address)
break key if key
diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb
index 3b19ae3d7ff..a2c1c96815c 100644
--- a/lib/gitlab/i18n.rb
+++ b/lib/gitlab/i18n.rb
@@ -4,20 +4,6 @@ module Gitlab
module I18n
extend self
- # Languages with less then 2% of available translations will not
- # be available in the UI.
- # https://gitlab.com/gitlab-org/gitlab/-/issues/221012
- NOT_AVAILABLE_IN_UI = %w[
- fil_PH
- pl_PL
- nl_NL
- id_ID
- cs_CZ
- bg
- eo
- gl_ES
- ].freeze
-
AVAILABLE_LANGUAGES = {
'bg' => 'Bulgarian - български',
'cs_CZ' => 'Czech - čeština',
@@ -42,9 +28,49 @@ module Gitlab
'zh_HK' => 'Chinese, Traditional (Hong Kong) - 繁體中文 (香港)',
'zh_TW' => 'Chinese, Traditional (Taiwan) - 繁體中文 (台灣)'
}.freeze
+ private_constant :AVAILABLE_LANGUAGES
+
+ # Languages with less then MINIMUM_TRANSLATION_LEVEL% of available translations will not
+ # be available in the UI.
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/221012
+ MINIMUM_TRANSLATION_LEVEL = 2
+
+ # Currently monthly updated manually by ~group::import PM.
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/18923
+ TRANSLATION_LEVELS = {
+ 'bg' => 1,
+ 'cs_CZ' => 1,
+ 'de' => 20,
+ 'en' => 100,
+ 'eo' => 1,
+ 'es' => 44,
+ 'fil_PH' => 1,
+ 'fr' => 14,
+ 'gl_ES' => 1,
+ 'id_ID' => 0,
+ 'it' => 3,
+ 'ja' => 49,
+ 'ko' => 15,
+ 'nl_NL' => 1,
+ 'pl_PL' => 1,
+ 'pt_BR' => 23,
+ 'ru' => 34,
+ 'tr_TR' => 18,
+ 'uk' => 46,
+ 'zh_CN' => 78,
+ 'zh_HK' => 3,
+ 'zh_TW' => 4
+ }.freeze
+ private_constant :TRANSLATION_LEVELS
def selectable_locales
- AVAILABLE_LANGUAGES.reject { |key, _value| NOT_AVAILABLE_IN_UI.include? key }
+ AVAILABLE_LANGUAGES.reject do |code, _name|
+ percentage_translated_for(code) < MINIMUM_TRANSLATION_LEVEL
+ end
+ end
+
+ def percentage_translated_for(code)
+ TRANSLATION_LEVELS.fetch(code, 0)
end
def available_locales
diff --git a/lib/gitlab/prometheus/adapter.rb b/lib/gitlab/prometheus/adapter.rb
index 76e65d29c7a..45438d9bf7c 100644
--- a/lib/gitlab/prometheus/adapter.rb
+++ b/lib/gitlab/prometheus/adapter.rb
@@ -19,13 +19,11 @@ module Gitlab
end
def cluster_prometheus_adapter
- if cluster&.integration_prometheus
- return cluster.integration_prometheus
- end
-
application = cluster&.application_prometheus
+ return application if application&.available?
- application if application&.available?
+ integration = cluster&.integration_prometheus
+ integration if integration&.available?
end
private
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 55356dba1b6..557cf5525b6 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -38107,6 +38107,9 @@ msgstr ""
msgid "https://your-bitbucket-server"
msgstr ""
+msgid "i18n|%{language} (%{percent_translated}%% translated)"
+msgstr ""
+
msgid "image diff"
msgstr ""
diff --git a/spec/deprecation_toolkit_env.rb b/spec/deprecation_toolkit_env.rb
index 2359765fedd..57d32b5423c 100644
--- a/spec/deprecation_toolkit_env.rb
+++ b/spec/deprecation_toolkit_env.rb
@@ -59,6 +59,7 @@ module DeprecationToolkitEnv
activesupport-6.0.3.6/lib/active_support/cache.rb
activerecord-6.0.3.6/lib/active_record/relation.rb
asciidoctor-2.0.12/lib/asciidoctor/extensions.rb
+ attr_encrypted-3.1.0/lib/attr_encrypted/adapters/active_record.rb
]
end
diff --git a/spec/features/profiles/user_edit_preferences_spec.rb b/spec/features/profiles/user_edit_preferences_spec.rb
index 3129e4bd952..c724de04043 100644
--- a/spec/features/profiles/user_edit_preferences_spec.rb
+++ b/spec/features/profiles/user_edit_preferences_spec.rb
@@ -1,10 +1,16 @@
# frozen_string_literal: true
+
require 'spec_helper'
RSpec.describe 'User edit preferences profile', :js do
+ include StubLanguagesTranslationPercentage
+
+ # Empty value doesn't change the levels
+ let(:language_percentage_levels) { nil }
let(:user) { create(:user) }
before do
+ stub_languages_translation_percentage(language_percentage_levels)
stub_feature_flags(user_time_settings: true)
sign_in(user)
visit(profile_preferences_path)
@@ -63,17 +69,4 @@ RSpec.describe 'User edit preferences profile', :js do
expect(page).to have_content('Failed to save preferences.')
end
end
-
- describe 'User language' do
- let(:user) { create(:user, preferred_language: :es) }
-
- it 'shows the user preferred language by default' do
- expect(page).to have_select(
- 'user[preferred_language]',
- selected: 'Spanish - español',
- options: Gitlab::I18n.selectable_locales.values,
- visible: :all
- )
- end
- end
end
diff --git a/spec/helpers/preferences_helper_spec.rb b/spec/helpers/preferences_helper_spec.rb
index 4d7083c4ca7..6be6d3670d4 100644
--- a/spec/helpers/preferences_helper_spec.rb
+++ b/spec/helpers/preferences_helper_spec.rb
@@ -121,6 +121,20 @@ RSpec.describe PreferencesHelper do
end
end
+ describe '#language_choices' do
+ include StubLanguagesTranslationPercentage
+
+ it 'lists all the selectable language options with their translation percent' do
+ stub_languages_translation_percentage(en: 100, es: 65)
+ stub_user(preferred_language: :en)
+
+ expect(helper.language_choices).to eq([
+ '<option selected="selected" value="en">English (100% translated)</option>',
+ '<option value="es">Spanish - español (65% translated)</option>'
+ ].join("\n"))
+ end
+ end
+
def stub_user(messages = {})
if messages.empty?
allow(helper).to receive(:current_user).and_return(nil)
diff --git a/spec/lib/gitlab/email/receiver_spec.rb b/spec/lib/gitlab/email/receiver_spec.rb
index ccff902d290..9b05c12ef57 100644
--- a/spec/lib/gitlab/email/receiver_spec.rb
+++ b/spec/lib/gitlab/email/receiver_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe Gitlab::Email::Receiver do
context 'when the email contains a valid email address in a header' do
let(:handler) { double(:handler) }
+ let(:metadata) { receiver.mail_metadata }
before do
allow(handler).to receive(:execute)
@@ -22,24 +23,38 @@ RSpec.describe Gitlab::Email::Receiver do
allow(handler).to receive(:metrics_event)
stub_incoming_email_setting(enabled: true, address: "incoming+%{key}@appmail.example.com")
+
+ expect(receiver.mail_metadata.keys).to match_array(%i(mail_uid from_address to_address mail_key references delivered_to envelope_to x_envelope_to))
end
context 'when in a Delivered-To header' do
let(:email_raw) { fixture_file('emails/forwarded_new_issue.eml') }
it_behaves_like 'correctly finds the mail key'
+
+ it 'parses the metadata' do
+ expect(metadata[:delivered_to]). to eq(["incoming+gitlabhq/gitlabhq+auth_token@appmail.example.com", "support@example.com"])
+ end
end
context 'when in an Envelope-To header' do
let(:email_raw) { fixture_file('emails/envelope_to_header.eml') }
it_behaves_like 'correctly finds the mail key'
+
+ it 'parses the metadata' do
+ expect(metadata[:envelope_to]). to eq(["incoming+gitlabhq/gitlabhq+auth_token@appmail.example.com"])
+ end
end
context 'when in an X-Envelope-To header' do
let(:email_raw) { fixture_file('emails/x_envelope_to_header.eml') }
it_behaves_like 'correctly finds the mail key'
+
+ it 'parses the metadata' do
+ expect(metadata[:x_envelope_to]). to eq(["incoming+gitlabhq/gitlabhq+auth_token@appmail.example.com"])
+ end
end
context 'when enclosed with angle brackets in an Envelope-To header' do
diff --git a/spec/lib/gitlab/i18n_spec.rb b/spec/lib/gitlab/i18n_spec.rb
index ee10739195a..aae4a13bd73 100644
--- a/spec/lib/gitlab/i18n_spec.rb
+++ b/spec/lib/gitlab/i18n_spec.rb
@@ -3,13 +3,18 @@
require 'spec_helper'
RSpec.describe Gitlab::I18n do
- let(:user) { create(:user, preferred_language: 'es') }
+ let(:user) { create(:user, preferred_language: :es) }
describe '.selectable_locales' do
- it 'does not return languages that should not be available in the UI' do
- Gitlab::I18n::NOT_AVAILABLE_IN_UI.each do |language|
- expect(described_class.selectable_locales).not_to include(language)
- end
+ include StubLanguagesTranslationPercentage
+
+ it 'does not return languages with low translation levels' do
+ stub_languages_translation_percentage(pt_BR: 0, en: 100, es: 65)
+
+ expect(described_class.selectable_locales).to eq({
+ 'en' => 'English',
+ 'es' => 'Spanish - español'
+ })
end
end
diff --git a/spec/lib/gitlab/prometheus/adapter_spec.rb b/spec/lib/gitlab/prometheus/adapter_spec.rb
index 9d4806ea73b..259202178a2 100644
--- a/spec/lib/gitlab/prometheus/adapter_spec.rb
+++ b/spec/lib/gitlab/prometheus/adapter_spec.rb
@@ -58,8 +58,8 @@ RSpec.describe Gitlab::Prometheus::Adapter do
context 'with cluster with prometheus integration' do
let!(:prometheus_integration) { create(:clusters_integrations_prometheus, cluster: cluster) }
- it 'returns the integration instead' do
- expect(subject.prometheus_adapter).to eq(prometheus_integration)
+ it 'returns the application' do
+ expect(subject.prometheus_adapter).to eq(prometheus)
end
end
end
diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb
index f74a89eaec5..549a273e2d7 100644
--- a/spec/models/clusters/applications/prometheus_spec.rb
+++ b/spec/models/clusters/applications/prometheus_spec.rb
@@ -13,16 +13,13 @@ RSpec.describe Clusters::Applications::Prometheus do
include_examples 'cluster application initial status specs'
describe 'after_destroy' do
- context 'cluster type is project' do
- let(:cluster) { create(:cluster, :with_installed_helm) }
- let(:application) { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
+ let(:cluster) { create(:cluster, :with_installed_helm) }
+ let(:application) { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
- it 'deactivates prometheus_service after destroy' do
- expect(Clusters::Applications::DeactivateServiceWorker)
- .to receive(:perform_async).with(cluster.id, 'prometheus')
+ it 'disables the corresponding integration' do
+ application.destroy!
- application.destroy!
- end
+ expect(cluster.integration_prometheus).not_to be_enabled
end
end
@@ -31,11 +28,10 @@ RSpec.describe Clusters::Applications::Prometheus do
let(:cluster) { create(:cluster, :with_installed_helm) }
let(:application) { create(:clusters_applications_prometheus, :installing, cluster: cluster) }
- it 'schedules post installation job' do
- expect(Clusters::Applications::ActivateServiceWorker)
- .to receive(:perform_async).with(cluster.id, 'prometheus')
-
+ it 'enables the corresponding integration' do
application.make_installed
+
+ expect(cluster.integration_prometheus).to be_enabled
end
end
@@ -44,11 +40,10 @@ RSpec.describe Clusters::Applications::Prometheus do
let(:cluster) { create(:cluster, :with_installed_helm) }
let(:application) { create(:clusters_applications_prometheus, :installing, cluster: cluster) }
- it 'schedules post installation job' do
- expect(Clusters::Applications::ActivateServiceWorker)
- .to receive(:perform_async).with(cluster.id, 'prometheus')
-
+ it 'enables the corresponding integration' do
application.make_externally_installed!
+
+ expect(cluster.integration_prometheus).to be_enabled
end
end
@@ -338,42 +333,10 @@ RSpec.describe Clusters::Applications::Prometheus do
describe 'alert manager token' do
subject { create(:clusters_applications_prometheus) }
- context 'when not set' do
- it 'is empty by default' do
- expect(subject.alert_manager_token).to be_nil
- expect(subject.encrypted_alert_manager_token).to be_nil
- expect(subject.encrypted_alert_manager_token_iv).to be_nil
- end
-
- describe '#generate_alert_manager_token!' do
- it 'generates a token' do
- subject.generate_alert_manager_token!
-
- expect(subject.alert_manager_token).to match(/\A\h{32}\z/)
- end
- end
- end
-
- context 'when set' do
- let(:token) { SecureRandom.hex }
-
- before do
- subject.update!(alert_manager_token: token)
- end
-
- it 'reads the token' do
- expect(subject.alert_manager_token).to eq(token)
- expect(subject.encrypted_alert_manager_token).not_to be_nil
- expect(subject.encrypted_alert_manager_token_iv).not_to be_nil
- end
-
- describe '#generate_alert_manager_token!' do
- it 'does not re-generate the token' do
- subject.generate_alert_manager_token!
-
- expect(subject.alert_manager_token).to eq(token)
- end
- end
+ it 'is autogenerated on creation' do
+ expect(subject.alert_manager_token).to match(/\A\h{32}\z/)
+ expect(subject.encrypted_alert_manager_token).not_to be_nil
+ expect(subject.encrypted_alert_manager_token_iv).not_to be_nil
end
end
end
diff --git a/spec/models/clusters/integrations/prometheus_spec.rb b/spec/models/clusters/integrations/prometheus_spec.rb
index a7be1673ce2..680786189ad 100644
--- a/spec/models/clusters/integrations/prometheus_spec.rb
+++ b/spec/models/clusters/integrations/prometheus_spec.rb
@@ -15,6 +15,62 @@ RSpec.describe Clusters::Integrations::Prometheus do
it { is_expected.not_to allow_value(nil).for(:enabled) }
end
+ describe 'after_destroy' do
+ subject(:integration) { create(:clusters_integrations_prometheus, cluster: cluster, enabled: true) }
+
+ let(:cluster) { create(:cluster, :with_installed_helm) }
+
+ it 'deactivates prometheus_service' do
+ expect(Clusters::Applications::DeactivateServiceWorker)
+ .to receive(:perform_async).with(cluster.id, 'prometheus')
+
+ integration.destroy!
+ end
+ end
+
+ describe 'after_save' do
+ subject(:integration) { create(:clusters_integrations_prometheus, cluster: cluster, enabled: enabled) }
+
+ let(:cluster) { create(:cluster, :with_installed_helm) }
+ let(:enabled) { true }
+
+ context 'when no change to enabled status' do
+ it 'does not touch project services' do
+ integration # ensure integration exists before we set the expectations
+
+ expect(Clusters::Applications::DeactivateServiceWorker)
+ .not_to receive(:perform_async)
+
+ expect(Clusters::Applications::ActivateServiceWorker)
+ .not_to receive(:perform_async)
+
+ integration.update!(enabled: enabled)
+ end
+ end
+
+ context 'when enabling' do
+ let(:enabled) { false }
+
+ it 'deactivates prometheus_service' do
+ expect(Clusters::Applications::ActivateServiceWorker)
+ .to receive(:perform_async).with(cluster.id, 'prometheus')
+
+ integration.update!(enabled: true)
+ end
+ end
+
+ context 'when disabling' do
+ let(:enabled) { true }
+
+ it 'activates prometheus_service' do
+ expect(Clusters::Applications::DeactivateServiceWorker)
+ .to receive(:perform_async).with(cluster.id, 'prometheus')
+
+ integration.update!(enabled: false)
+ end
+ end
+ end
+
describe '#prometheus_client' do
include_examples '#prometheus_client shared' do
let(:factory) { :clusters_integrations_prometheus }
diff --git a/spec/services/projects/prometheus/alerts/notify_service_spec.rb b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
index 26d8d3afd10..bfc8225b654 100644
--- a/spec/services/projects/prometheus/alerts/notify_service_spec.rb
+++ b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
@@ -62,7 +62,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
end
end
- context 'with project specific cluster' do
+ context 'with project specific cluster using prometheus application' do
where(:cluster_enabled, :status, :configured_token, :token_input, :result) do
true | :installed | token | token | :success
true | :installed | nil | nil | :success
@@ -97,6 +97,40 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
end
end
+ context 'with project specific cluster using prometheus integration' do
+ where(:cluster_enabled, :integration_enabled, :configured_token, :token_input, :result) do
+ true | true | token | token | :success
+ true | true | nil | nil | :success
+ true | true | token | 'x' | :failure
+ true | true | token | nil | :failure
+ true | false | token | token | :failure
+ false | true | token | token | :failure
+ false | nil | nil | token | :failure
+ end
+
+ with_them do
+ before do
+ cluster.update!(enabled: cluster_enabled)
+
+ unless integration_enabled.nil?
+ create(:clusters_integrations_prometheus,
+ cluster: cluster,
+ enabled: integration_enabled,
+ alert_manager_token: configured_token)
+ end
+ end
+
+ case result = params[:result]
+ when :success
+ include_examples 'processes one firing and one resolved prometheus alerts'
+ when :failure
+ it_behaves_like 'alerts service responds with an error and takes no actions', :unauthorized
+ else
+ raise "invalid result: #{result.inspect}"
+ end
+ end
+ end
+
context 'without project specific cluster' do
let_it_be(:cluster) { create(:cluster, enabled: true) }
diff --git a/spec/support/stub_languages_translation_percentage.rb b/spec/support/stub_languages_translation_percentage.rb
new file mode 100644
index 00000000000..a93316288b9
--- /dev/null
+++ b/spec/support/stub_languages_translation_percentage.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module StubLanguagesTranslationPercentage
+ # Stubs the translation percentage of the i18n languages
+ # - When a `blank?` list is given no stubbing is done;
+ # - When the list is not empty, the languages in the list
+ # are stubbed with the given values, any other language
+ # will have the translation percent set to 0;
+ def stub_languages_translation_percentage(list = {})
+ return if list.blank?
+
+ expect(Gitlab::I18n)
+ .to receive(:percentage_translated_for)
+ .at_least(:once)
+ .and_wrap_original do |_original, code|
+ list.with_indifferent_access[code].to_i
+ end
+ end
+end
diff --git a/spec/workers/email_receiver_worker_spec.rb b/spec/workers/email_receiver_worker_spec.rb
index 8bf7f3f552d..d26c08fb221 100644
--- a/spec/workers/email_receiver_worker_spec.rb
+++ b/spec/workers/email_receiver_worker_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe EmailReceiverWorker, :mailer do
it "calls the email receiver" do
expect(Gitlab::Email::Receiver).to receive(:new).with(raw_message).and_call_original
expect_any_instance_of(Gitlab::Email::Receiver).to receive(:execute)
+ expect(Sidekiq.logger).to receive(:info).with(hash_including(message: "Successfully processed message")).and_call_original
described_class.new.perform(raw_message)
end
@@ -20,10 +21,11 @@ RSpec.describe EmailReceiverWorker, :mailer do
context "when an error occurs" do
before do
allow_any_instance_of(Gitlab::Email::Receiver).to receive(:execute).and_raise(error)
+ expect(Sidekiq.logger).to receive(:error).with(hash_including('exception.class' => error.class.name)).and_call_original
end
context 'when the error is Gitlab::Email::EmptyEmailError' do
- let(:error) { Gitlab::Email::EmptyEmailError }
+ let(:error) { Gitlab::Email::EmptyEmailError.new }
it 'sends out a rejection email' do
perform_enqueued_jobs do
@@ -38,7 +40,7 @@ RSpec.describe EmailReceiverWorker, :mailer do
end
context 'when the error is Gitlab::Email::AutoGeneratedEmailError' do
- let(:error) { Gitlab::Email::AutoGeneratedEmailError }
+ let(:error) { Gitlab::Email::AutoGeneratedEmailError.new }
it 'does not send out any rejection email' do
perform_enqueued_jobs do
@@ -63,6 +65,21 @@ RSpec.describe EmailReceiverWorker, :mailer do
expect(email.body.parts.last.to_s).to include("Could not deal with that")
end
end
+
+ context 'when the error is ActiveRecord::StatementTimeout' do
+ let(:error) { ActiveRecord::StatementTimeout.new("Statement timeout") }
+
+ it 'does not report the error to the sender' do
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(error).and_call_original
+
+ perform_enqueued_jobs do
+ described_class.new.perform(raw_message)
+ end
+
+ email = ActionMailer::Base.deliveries.last
+ expect(email).to be_nil
+ end
+ end
end
end
diff --git a/spec/workers/service_desk_email_receiver_worker_spec.rb b/spec/workers/service_desk_email_receiver_worker_spec.rb
index d3bfa51348e..60fc951f627 100644
--- a/spec/workers/service_desk_email_receiver_worker_spec.rb
+++ b/spec/workers/service_desk_email_receiver_worker_spec.rb
@@ -9,11 +9,12 @@ RSpec.describe ServiceDeskEmailReceiverWorker, :mailer do
context 'when service_desk_email config is enabled' do
before do
- stub_service_desk_email_setting(enabled: true, address: 'foo')
+ stub_service_desk_email_setting(enabled: true, address: 'support+%{key}@example.com')
end
it 'does not ignore the email' do
- expect(Gitlab::Email::ServiceDeskReceiver).to receive(:new)
+ expect(Gitlab::Email::ServiceDeskReceiver).to receive(:new).and_call_original
+ expect(Sidekiq.logger).to receive(:error).with(hash_including('exception.class' => Gitlab::Email::ProjectNotFound.to_s)).and_call_original
worker.perform(email)
end
@@ -23,6 +24,7 @@ RSpec.describe ServiceDeskEmailReceiverWorker, :mailer do
allow_next_instance_of(Gitlab::Email::ServiceDeskReceiver) do |receiver|
allow(receiver).to receive(:find_handler).and_return(nil)
end
+ expect(Sidekiq.logger).to receive(:error).with(hash_including('exception.class' => Gitlab::Email::UnknownIncomingEmail.to_s)).and_call_original
end
it 'sends a rejection email' do