summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-10-03 21:07:29 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-10-03 21:07:29 +0000
commit1da3754b25657f49afdcb0b942506d365b1ee89d (patch)
tree9f4bfa94fdd1762ef99e6a61bf180ac8cd7b5616
parent25521def84a6987fe9d4265b560e930bfb32c195 (diff)
downloadgitlab-ce-1da3754b25657f49afdcb0b942506d365b1ee89d.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/monitoring/utils.js8
-rw-r--r--app/assets/javascripts/reports/store/utils.js2
-rw-r--r--app/controllers/health_controller.rb41
-rw-r--r--app/controllers/projects/settings/operations_controller.rb4
-rw-r--r--app/helpers/groups_helper.rb3
-rw-r--r--app/helpers/projects_helper.rb10
-rw-r--r--app/models/grafana_integration.rb16
-rw-r--r--app/models/namespace.rb2
-rw-r--r--app/models/project.rb4
-rw-r--r--app/models/storage/hashed_project.rb6
-rw-r--r--app/models/storage/legacy_project.rb6
-rw-r--r--app/services/projects/operations/update_service.rb12
-rw-r--r--changelogs/unreleased/30186-mirror-pull-api-no-unpause.yml5
-rw-r--r--changelogs/unreleased/33158-time-window-filter-dropdown-doesn-t-retain-previously-selected-wind.yml5
-rw-r--r--changelogs/unreleased/eb-support-test-report-error-key.yml5
-rw-r--r--changelogs/unreleased/sy-grafana-auth-be.yml5
-rw-r--r--config/light_settings.rb2
-rw-r--r--config/locales/en.yml3
-rw-r--r--db/migrate/20190918102042_create_grafana_integrations.rb15
-rw-r--r--db/schema.rb11
-rw-r--r--lib/gitlab/ci/parsers/test/junit.rb6
-rw-r--r--lib/gitlab/health_checks/checks.rb14
-rw-r--r--lib/gitlab/health_checks/gitaly_check.rb8
-rw-r--r--lib/gitlab/health_checks/metric.rb6
-rw-r--r--lib/gitlab/health_checks/prometheus_text_format.rb42
-rw-r--r--lib/gitlab/health_checks/result.rb14
-rw-r--r--lib/gitlab/health_checks/simple_abstract_check.rb8
-rw-r--r--lib/gitlab/shell.rb5
-rw-r--r--lib/gitlab/url_blocker.rb5
-rw-r--r--locale/gitlab.pot4
-rw-r--r--spec/controllers/health_controller_spec.rb3
-rw-r--r--spec/controllers/projects/settings/operations_controller_spec.rb15
-rw-r--r--spec/factories/grafana_integrations.rb9
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb14
-rw-r--r--spec/frontend/reports/store/utils_spec.js14
-rw-r--r--spec/helpers/projects_helper_spec.rb36
-rw-r--r--spec/javascripts/monitoring/components/dashboard_spec.js4
-rw-r--r--spec/javascripts/monitoring/utils_spec.js53
-rw-r--r--spec/javascripts/reports/components/grouped_test_reports_app_spec.js10
-rw-r--r--spec/lib/backup/repository_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/parsers/test/junit_spec.rb68
-rw-r--r--spec/lib/gitlab/health_checks/gitaly_check_spec.rb4
-rw-r--r--spec/lib/gitlab/health_checks/prometheus_text_format_spec.rb41
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/lib/gitlab/url_blocker_spec.rb8
-rw-r--r--spec/models/grafana_integration_spec.rb38
-rw-r--r--spec/models/namespace_spec.rb26
-rw-r--r--spec/models/project_spec.rb41
-rw-r--r--spec/services/groups/destroy_service_spec.rb2
-rw-r--r--spec/services/projects/operations/update_service_spec.rb56
-rw-r--r--spec/workers/repository_check/dispatch_worker_spec.rb4
51 files changed, 472 insertions, 253 deletions
diff --git a/app/assets/javascripts/monitoring/utils.js b/app/assets/javascripts/monitoring/utils.js
index 46b01f753f8..a134b4e3c33 100644
--- a/app/assets/javascripts/monitoring/utils.js
+++ b/app/assets/javascripts/monitoring/utils.js
@@ -1,19 +1,21 @@
import { secondsIn, timeWindowsKeyNames } from './constants';
+const secondsToMilliseconds = seconds => seconds * 1000;
+
export const getTimeDiff = timeWindow => {
const end = Math.floor(Date.now() / 1000); // convert milliseconds to seconds
const difference = secondsIn[timeWindow] || secondsIn.eightHours;
const start = end - difference;
return {
- start: new Date(start * 1000).toISOString(),
- end: new Date(end * 1000).toISOString(),
+ start: new Date(secondsToMilliseconds(start)).toISOString(),
+ end: new Date(secondsToMilliseconds(end)).toISOString(),
};
};
export const getTimeWindow = ({ start, end }) =>
Object.entries(secondsIn).reduce((acc, [timeRange, value]) => {
- if (end - start === value) {
+ if (new Date(end) - new Date(start) === secondsToMilliseconds(value)) {
return timeRange;
}
return acc;
diff --git a/app/assets/javascripts/reports/store/utils.js b/app/assets/javascripts/reports/store/utils.js
index 10560d0ae8e..7381f038eaf 100644
--- a/app/assets/javascripts/reports/store/utils.js
+++ b/app/assets/javascripts/reports/store/utils.js
@@ -11,7 +11,7 @@ const textBuilder = results => {
const { failed, resolved, total } = results;
const failedString = failed
- ? n__('%d failed test result', '%d failed test results', failed)
+ ? n__('%d failed/error test result', '%d failed/error test results', failed)
: null;
const resolvedString = resolved
? n__('%d fixed test result', '%d fixed test results', resolved)
diff --git a/app/controllers/health_controller.rb b/app/controllers/health_controller.rb
index 84b4932ba7a..99840e40af1 100644
--- a/app/controllers/health_controller.rb
+++ b/app/controllers/health_controller.rb
@@ -4,19 +4,15 @@ class HealthController < ActionController::Base
protect_from_forgery with: :exception, prepend: true
include RequiresWhitelistedMonitoringClient
- CHECKS = [
- Gitlab::HealthChecks::DbCheck,
- Gitlab::HealthChecks::Redis::RedisCheck,
- Gitlab::HealthChecks::Redis::CacheCheck,
- Gitlab::HealthChecks::Redis::QueuesCheck,
- Gitlab::HealthChecks::Redis::SharedStateCheck,
- Gitlab::HealthChecks::GitalyCheck
- ].freeze
-
def readiness
- results = CHECKS.map { |check| [check.name, check.readiness] }
+ results = checks.flat_map(&:readiness)
+ success = results.all?(&:success)
- render_check_results(results)
+ # disable static error pages at the gitlab-workhorse level, we want to see this error response even in production
+ headers["X-GitLab-Custom-Error"] = 1 unless success
+
+ response = results.map { |result| [result.name, result.payload] }.to_h
+ render json: response, status: success ? :ok : :service_unavailable
end
def liveness
@@ -25,26 +21,7 @@ class HealthController < ActionController::Base
private
- def render_check_results(results)
- flattened = results.flat_map do |name, result|
- if result.is_a?(Gitlab::HealthChecks::Result)
- [[name, result]]
- else
- result.map { |r| [name, r] }
- end
- end
- success = flattened.all? { |name, r| r.success }
-
- response = flattened.map do |name, r|
- info = { status: r.success ? 'ok' : 'failed' }
- info['message'] = r.message if r.message
- info[:labels] = r.labels if r.labels
- [name, info]
- end
-
- # disable static error pages at the gitlab-workhorse level, we want to see this error response even in production
- headers["X-GitLab-Custom-Error"] = 1 unless success
-
- render json: response.to_h, status: success ? :ok : :service_unavailable
+ def checks
+ ::Gitlab::HealthChecks::CHECKS
end
end
diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb
index 7c71486a765..6110a7759ad 100644
--- a/app/controllers/projects/settings/operations_controller.rb
+++ b/app/controllers/projects/settings/operations_controller.rb
@@ -63,7 +63,9 @@ module Projects
:api_host,
:token,
project: [:slug, :name, :organization_slug, :organization_name]
- ]
+ ],
+
+ grafana_integration_attributes: [:token, :grafana_url]
}
end
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 601560cca92..9cba87ac444 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -32,8 +32,7 @@ module GroupsHelper
end
def can_disable_group_emails?(group)
- Feature.enabled?(:emails_disabled, group, default_enabled: true) &&
- can?(current_user, :set_emails_disabled, group) && !group.parent&.emails_disabled?
+ can?(current_user, :set_emails_disabled, group) && !group.parent&.emails_disabled?
end
def group_issues_count(state:)
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 177778a7278..4b00c11b27c 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -160,7 +160,7 @@ module ProjectsHelper
def can_disable_emails?(project, current_user)
return false if project.group&.emails_disabled?
- can?(current_user, :set_emails_disabled, project) && Feature.enabled?(:emails_disabled, project, default_enabled: true)
+ can?(current_user, :set_emails_disabled, project)
end
def last_push_event
@@ -354,6 +354,14 @@ module ProjectsHelper
@project.metrics_setting_external_dashboard_url
end
+ def grafana_integration_url
+ @project.grafana_integration&.grafana_url
+ end
+
+ def grafana_integration_token
+ @project.grafana_integration&.token
+ end
+
private
def get_project_nav_tabs(project, current_user)
diff --git a/app/models/grafana_integration.rb b/app/models/grafana_integration.rb
new file mode 100644
index 00000000000..668b9dafd7d
--- /dev/null
+++ b/app/models/grafana_integration.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class GrafanaIntegration < ApplicationRecord
+ belongs_to :project
+
+ attr_encrypted :token,
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm',
+ key: Settings.attr_encrypted_db_key_base_32
+
+ validates :grafana_url,
+ length: { maximum: 1024 },
+ addressable_url: { enforce_sanitization: true, ascii_only: true }
+
+ validates :token, :project, presence: true
+end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 2fe691bd959..0e6059f8715 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -182,7 +182,7 @@ class Namespace < ApplicationRecord
# any ancestor can disable emails for all descendants
def emails_disabled?
strong_memoize(:emails_disabled) do
- Feature.enabled?(:emails_disabled, self, default_enabled: true) && self_and_ancestors.where(emails_disabled: true).exists?
+ self_and_ancestors.where(emails_disabled: true).exists?
end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 512734e9b3f..6b8067ddd7d 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -195,6 +195,7 @@ class Project < ApplicationRecord
has_one :project_repository, inverse_of: :project
has_one :error_tracking_setting, inverse_of: :project, class_name: 'ErrorTracking::ProjectErrorTrackingSetting'
has_one :metrics_setting, inverse_of: :project, class_name: 'ProjectMetricsSetting'
+ has_one :grafana_integration, inverse_of: :project
# Merge Requests for target project should be removed with it
has_many :merge_requests, foreign_key: 'target_project_id', inverse_of: :target_project
@@ -311,6 +312,7 @@ class Project < ApplicationRecord
accepts_nested_attributes_for :error_tracking_setting, update_only: true
accepts_nested_attributes_for :metrics_setting, update_only: true, allow_destroy: true
+ accepts_nested_attributes_for :grafana_integration, update_only: true, allow_destroy: true
delegate :name, to: :owner, allow_nil: true, prefix: true
delegate :members, to: :team, prefix: true
@@ -664,7 +666,7 @@ class Project < ApplicationRecord
def emails_disabled?
strong_memoize(:emails_disabled) do
# disabling in the namespace overrides the project setting
- Feature.enabled?(:emails_disabled, self, default_enabled: true) && (super || namespace.emails_disabled?)
+ super || namespace.emails_disabled?
end
end
diff --git a/app/models/storage/hashed_project.rb b/app/models/storage/hashed_project.rb
index f5d0d6fab3b..519d91434ad 100644
--- a/app/models/storage/hashed_project.rb
+++ b/app/models/storage/hashed_project.rb
@@ -27,8 +27,12 @@ module Storage
"#{base_dir}/#{disk_hash}" if disk_hash
end
+ # TODO: remove this method entirely after 12.4 https://gitlab.com/gitlab-org/gitlab/issues/33244
+ # we no longer need ensure_storage_path_exists to call add_namespace since both creating and moving
+ # repositories will be preceded by a mkdir -p in gitaly to ensure the parent of the destination directory
+ # exists.
def ensure_storage_path_exists
- gitlab_shell.add_namespace(repository_storage, base_dir)
+ true
end
def rename_repo(old_full_path: nil, new_full_path: nil)
diff --git a/app/models/storage/legacy_project.rb b/app/models/storage/legacy_project.rb
index 928c773c307..1d0124e8321 100644
--- a/app/models/storage/legacy_project.rb
+++ b/app/models/storage/legacy_project.rb
@@ -23,10 +23,14 @@ module Storage
project.full_path
end
+ # TODO: remove this method entirely after 12.4 https://gitlab.com/gitlab-org/gitlab/issues/33244
+ # we no longer need ensure_storage_path_exists to call add_namespace since both creating and moving
+ # repositories will be preceded by a mkdir -p in gitaly to ensure the parent of the destination directory
+ # exists.
def ensure_storage_path_exists
return unless namespace
- gitlab_shell.add_namespace(repository_storage, base_dir)
+ true
end
def rename_repo(old_full_path: nil, new_full_path: nil)
diff --git a/app/services/projects/operations/update_service.rb b/app/services/projects/operations/update_service.rb
index dd72c2844c2..64519501ff4 100644
--- a/app/services/projects/operations/update_service.rb
+++ b/app/services/projects/operations/update_service.rb
@@ -12,7 +12,9 @@ module Projects
private
def project_update_params
- error_tracking_params.merge(metrics_setting_params)
+ error_tracking_params
+ .merge(metrics_setting_params)
+ .merge(grafana_integration_params)
end
def metrics_setting_params
@@ -44,6 +46,14 @@ module Projects
}
}
end
+
+ def grafana_integration_params
+ return {} unless attrs = params[:grafana_integration_attributes]
+
+ destroy = attrs[:grafana_url].blank? && attrs[:token].blank?
+
+ { grafana_integration_attributes: attrs.merge(_destroy: destroy) }
+ end
end
end
end
diff --git a/changelogs/unreleased/30186-mirror-pull-api-no-unpause.yml b/changelogs/unreleased/30186-mirror-pull-api-no-unpause.yml
new file mode 100644
index 00000000000..dee4128051e
--- /dev/null
+++ b/changelogs/unreleased/30186-mirror-pull-api-no-unpause.yml
@@ -0,0 +1,5 @@
+---
+title: Do not start mirroring via API when paused
+merge_request: 17930
+author:
+type: changed
diff --git a/changelogs/unreleased/33158-time-window-filter-dropdown-doesn-t-retain-previously-selected-wind.yml b/changelogs/unreleased/33158-time-window-filter-dropdown-doesn-t-retain-previously-selected-wind.yml
new file mode 100644
index 00000000000..16951ac7051
--- /dev/null
+++ b/changelogs/unreleased/33158-time-window-filter-dropdown-doesn-t-retain-previously-selected-wind.yml
@@ -0,0 +1,5 @@
+---
+title: Time window filter in monitor dashboard gets reset
+merge_request: 17972
+author:
+type: fixed
diff --git a/changelogs/unreleased/eb-support-test-report-error-key.yml b/changelogs/unreleased/eb-support-test-report-error-key.yml
new file mode 100644
index 00000000000..304e9814529
--- /dev/null
+++ b/changelogs/unreleased/eb-support-test-report-error-key.yml
@@ -0,0 +1,5 @@
+---
+title: MR Test Summary now shows errors as failures.
+merge_request: 17039
+author:
+type: changed
diff --git a/changelogs/unreleased/sy-grafana-auth-be.yml b/changelogs/unreleased/sy-grafana-auth-be.yml
new file mode 100644
index 00000000000..3fbd53f9e98
--- /dev/null
+++ b/changelogs/unreleased/sy-grafana-auth-be.yml
@@ -0,0 +1,5 @@
+---
+title: Create table for grafana api token for metrics embeds
+merge_request: 17234
+author:
+type: added
diff --git a/config/light_settings.rb b/config/light_settings.rb
index aa0dd04b3fa..19343ba7de0 100644
--- a/config/light_settings.rb
+++ b/config/light_settings.rb
@@ -22,7 +22,7 @@ class LightSettings
end
def host
- config['gitlab']['host']
+ config.dig('gitlab', 'host') || ENV['GITLAB_HOST'] || 'localhost'
end
def gl_subdomain?
diff --git a/config/locales/en.yml b/config/locales/en.yml
index a60f86e1d80..eff015459e3 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -16,6 +16,9 @@ en:
api_url: "Sentry API URL"
project/metrics_setting:
external_dashboard_url: "External dashboard URL"
+ project/grafana_integration:
+ token: "Grafana HTTP API Token"
+ grafana_url: "Grafana API URL"
views:
pagination:
previous: "Prev"
diff --git a/db/migrate/20190918102042_create_grafana_integrations.rb b/db/migrate/20190918102042_create_grafana_integrations.rb
new file mode 100644
index 00000000000..aac27d129db
--- /dev/null
+++ b/db/migrate/20190918102042_create_grafana_integrations.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class CreateGrafanaIntegrations < ActiveRecord::Migration[5.2]
+ DOWNTIME = false
+
+ def change
+ create_table :grafana_integrations do |t|
+ t.references :project, index: true, foreign_key: { on_delete: :cascade }, unique: true, null: false
+ t.timestamps_with_timezone null: false
+ t.string :encrypted_token, limit: 255, null: false
+ t.string :encrypted_token_iv, limit: 255, null: false
+ t.string :grafana_url, null: false, limit: 1024
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 8c22fe80381..4ca75ece3f9 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -1704,6 +1704,16 @@ ActiveRecord::Schema.define(version: 2019_09_27_074328) do
t.index ["project_id"], name: "index_gpg_signatures_on_project_id"
end
+ create_table "grafana_integrations", force: :cascade do |t|
+ t.bigint "project_id", null: false
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.string "encrypted_token", limit: 255, null: false
+ t.string "encrypted_token_iv", limit: 255, null: false
+ t.string "grafana_url", limit: 1024, null: false
+ t.index ["project_id"], name: "index_grafana_integrations_on_project_id"
+ end
+
create_table "group_custom_attributes", id: :serial, force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
@@ -3997,6 +4007,7 @@ ActiveRecord::Schema.define(version: 2019_09_27_074328) do
add_foreign_key "gpg_signatures", "gpg_key_subkeys", on_delete: :nullify
add_foreign_key "gpg_signatures", "gpg_keys", on_delete: :nullify
add_foreign_key "gpg_signatures", "projects", on_delete: :cascade
+ add_foreign_key "grafana_integrations", "projects", on_delete: :cascade
add_foreign_key "group_custom_attributes", "namespaces", column: "group_id", on_delete: :cascade
add_foreign_key "identities", "saml_providers", name: "fk_aade90f0fc", on_delete: :cascade
add_foreign_key "import_export_uploads", "projects", on_delete: :cascade
diff --git a/lib/gitlab/ci/parsers/test/junit.rb b/lib/gitlab/ci/parsers/test/junit.rb
index dca60eabc1c..8f8cae0b5f2 100644
--- a/lib/gitlab/ci/parsers/test/junit.rb
+++ b/lib/gitlab/ci/parsers/test/junit.rb
@@ -49,6 +49,12 @@ module Gitlab
if data['failure']
status = ::Gitlab::Ci::Reports::TestCase::STATUS_FAILED
system_output = data['failure']
+ elsif data['error']
+ # For now, as an MVC, we are grouping error test cases together
+ # with failed ones. But we will improve this further on
+ # https://gitlab.com/gitlab-org/gitlab/issues/32046.
+ status = ::Gitlab::Ci::Reports::TestCase::STATUS_FAILED
+ system_output = data['error']
else
status = ::Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS
system_output = nil
diff --git a/lib/gitlab/health_checks/checks.rb b/lib/gitlab/health_checks/checks.rb
new file mode 100644
index 00000000000..c4016c5fffd
--- /dev/null
+++ b/lib/gitlab/health_checks/checks.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module HealthChecks
+ CHECKS = [
+ Gitlab::HealthChecks::DbCheck,
+ Gitlab::HealthChecks::Redis::RedisCheck,
+ Gitlab::HealthChecks::Redis::CacheCheck,
+ Gitlab::HealthChecks::Redis::QueuesCheck,
+ Gitlab::HealthChecks::Redis::SharedStateCheck,
+ Gitlab::HealthChecks::GitalyCheck
+ ].freeze
+ end
+end
diff --git a/lib/gitlab/health_checks/gitaly_check.rb b/lib/gitlab/health_checks/gitaly_check.rb
index e560f87bf98..f5f142c251f 100644
--- a/lib/gitlab/health_checks/gitaly_check.rb
+++ b/lib/gitlab/health_checks/gitaly_check.rb
@@ -29,7 +29,13 @@ module Gitlab
def check(storage_name)
serv = Gitlab::GitalyClient::HealthCheckService.new(storage_name)
result = serv.check
- HealthChecks::Result.new(result[:success], result[:message], shard: storage_name)
+
+ HealthChecks::Result.new(
+ name,
+ result[:success],
+ result[:message],
+ shard: storage_name
+ )
end
private
diff --git a/lib/gitlab/health_checks/metric.rb b/lib/gitlab/health_checks/metric.rb
index 184083de2bc..b697cb0d027 100644
--- a/lib/gitlab/health_checks/metric.rb
+++ b/lib/gitlab/health_checks/metric.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
-module Gitlab::HealthChecks
- Metric = Struct.new(:name, :value, :labels)
+module Gitlab
+ module HealthChecks
+ Metric = Struct.new(:name, :value, :labels)
+ end
end
diff --git a/lib/gitlab/health_checks/prometheus_text_format.rb b/lib/gitlab/health_checks/prometheus_text_format.rb
deleted file mode 100644
index 2a8f9d31cd5..00000000000
--- a/lib/gitlab/health_checks/prometheus_text_format.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module HealthChecks
- class PrometheusTextFormat
- def marshal(metrics)
- "#{metrics_with_type_declarations(metrics).join("\n")}\n"
- end
-
- private
-
- def metrics_with_type_declarations(metrics)
- type_declaration_added = {}
-
- metrics.flat_map do |metric|
- metric_lines = []
-
- unless type_declaration_added.key?(metric.name)
- type_declaration_added[metric.name] = true
- metric_lines << metric_type_declaration(metric)
- end
-
- metric_lines << metric_text(metric)
- end
- end
-
- def metric_type_declaration(metric)
- "# TYPE #{metric.name} gauge"
- end
-
- def metric_text(metric)
- labels = metric.labels&.map { |key, value| "#{key}=\"#{value}\"" }&.join(',') || ''
-
- if labels.empty?
- "#{metric.name} #{metric.value}"
- else
- "#{metric.name}{#{labels}} #{metric.value}"
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/health_checks/result.rb b/lib/gitlab/health_checks/result.rb
index 4586b1d94a7..38a36100ec7 100644
--- a/lib/gitlab/health_checks/result.rb
+++ b/lib/gitlab/health_checks/result.rb
@@ -1,5 +1,15 @@
# frozen_string_literal: true
-module Gitlab::HealthChecks
- Result = Struct.new(:success, :message, :labels)
+module Gitlab
+ module HealthChecks
+ Result = Struct.new(:name, :success, :message, :labels) do
+ def payload
+ {
+ status: success ? 'ok' : 'failed',
+ message: message,
+ labels: labels
+ }.compact
+ end
+ end
+ end
end
diff --git a/lib/gitlab/health_checks/simple_abstract_check.rb b/lib/gitlab/health_checks/simple_abstract_check.rb
index bc02f0da98d..959f28791c3 100644
--- a/lib/gitlab/health_checks/simple_abstract_check.rb
+++ b/lib/gitlab/health_checks/simple_abstract_check.rb
@@ -8,14 +8,14 @@ module Gitlab
def readiness
check_result = check
if successful?(check_result)
- HealthChecks::Result.new(true)
+ HealthChecks::Result.new(name, true)
elsif check_result.is_a?(Timeout::Error)
- HealthChecks::Result.new(false, "#{human_name} check timed out")
+ HealthChecks::Result.new(name, false, "#{human_name} check timed out")
else
- HealthChecks::Result.new(false, "unexpected #{human_name} check result: #{check_result}")
+ HealthChecks::Result.new(name, false, "unexpected #{human_name} check result: #{check_result}")
end
rescue => e
- HealthChecks::Result.new(false, "unexpected #{human_name} check result: #{e}")
+ HealthChecks::Result.new(name, false, "unexpected #{human_name} check result: #{e}")
end
def metrics
diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index ec9b2a2022e..7722480903d 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -113,10 +113,6 @@ module Gitlab
success
end
- # Move repository reroutes to mv_directory which is an alias for
- # mv_namespace. Given the underlying implementation is a move action,
- # indescriminate of what the folders might be.
- #
# storage - project's storage path
# path - project disk path
# new_path - new project disk path
@@ -275,7 +271,6 @@ module Gitlab
false
end
- alias_method :mv_directory, :mv_namespace # Note: ShellWorker uses this alias
def url_to_repo(path)
Gitlab.config.gitlab_shell.ssh_path_prefix + "#{path}.git"
diff --git a/lib/gitlab/url_blocker.rb b/lib/gitlab/url_blocker.rb
index 4285b2675c5..0adca34440c 100644
--- a/lib/gitlab/url_blocker.rb
+++ b/lib/gitlab/url_blocker.rb
@@ -125,6 +125,11 @@ module Gitlab
# If the addr can't be resolved or the url is invalid (i.e http://1.1.1.1.1)
# we block the url
raise BlockedUrlError, "Host cannot be resolved or invalid"
+ rescue ArgumentError => error
+ # Addrinfo.getaddrinfo errors if the domain exceeds 1024 characters.
+ raise unless error.message.include?('hostname too long')
+
+ raise BlockedUrlError, "Host is too long (maximum is 1024 characters)"
end
def validate_local_request(
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 75323601017..a17d0460967 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -95,8 +95,8 @@ msgid_plural "%d exporters"
msgstr[0] ""
msgstr[1] ""
-msgid "%d failed test result"
-msgid_plural "%d failed test results"
+msgid "%d failed/error test result"
+msgid_plural "%d failed/error test results"
msgstr[0] ""
msgstr[1] ""
diff --git a/spec/controllers/health_controller_spec.rb b/spec/controllers/health_controller_spec.rb
index ae05573af2e..dd6aac4b126 100644
--- a/spec/controllers/health_controller_spec.rb
+++ b/spec/controllers/health_controller_spec.rb
@@ -32,7 +32,8 @@ describe HealthController do
end
it 'responds with readiness checks data when a failure happens' do
- allow(Gitlab::HealthChecks::Redis::RedisCheck).to receive(:readiness).and_return(Gitlab::HealthChecks::Result.new(false, "check error"))
+ allow(Gitlab::HealthChecks::Redis::RedisCheck).to receive(:readiness).and_return(
+ Gitlab::HealthChecks::Result.new('redis_check', false, "check error"))
subject
diff --git a/spec/controllers/projects/settings/operations_controller_spec.rb b/spec/controllers/projects/settings/operations_controller_spec.rb
index 3a56511a8d6..0b34656e9e2 100644
--- a/spec/controllers/projects/settings/operations_controller_spec.rb
+++ b/spec/controllers/projects/settings/operations_controller_spec.rb
@@ -180,6 +180,21 @@ describe Projects::Settings::OperationsController do
end
end
+ context 'grafana integration' do
+ describe 'PATCH #update' do
+ let(:params) do
+ {
+ grafana_integration_attributes: {
+ grafana_url: 'https://grafana.gitlab.com',
+ token: 'eyJrIjoicDRlRTREdjhhOEZ5WjZPWXUzazJOSW0zZHJUejVOd3IiLCJuIjoiVGVzdCBLZXkiLCJpZCI6MX0='
+ }
+ }
+ end
+
+ it_behaves_like 'PATCHable'
+ end
+ end
+
private
def project_params(project, params = {})
diff --git a/spec/factories/grafana_integrations.rb b/spec/factories/grafana_integrations.rb
new file mode 100644
index 00000000000..c19417f5a90
--- /dev/null
+++ b/spec/factories/grafana_integrations.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :grafana_integration, class: GrafanaIntegration do
+ project
+ grafana_url { 'https://grafana.com' }
+ token { SecureRandom.hex(10) }
+ end
+end
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index d19835741e3..6b6226ad1c5 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -536,10 +536,10 @@ describe 'Merge request > User sees merge widget', :js do
within(".js-reports-container") do
click_button 'Expand'
- expect(page).to have_content('Test summary contained 1 failed test result out of 2 total tests')
+ expect(page).to have_content('Test summary contained 1 failed/error test result out of 2 total tests')
within(".js-report-section-container") do
expect(page).to have_content('rspec found no changed test results out of 1 total test')
- expect(page).to have_content('junit found 1 failed test result out of 1 total test')
+ expect(page).to have_content('junit found 1 failed/error test result out of 1 total test')
expect(page).to have_content('New')
expect(page).to have_content('addTest')
end
@@ -581,9 +581,9 @@ describe 'Merge request > User sees merge widget', :js do
within(".js-reports-container") do
click_button 'Expand'
- expect(page).to have_content('Test summary contained 1 failed test result out of 2 total tests')
+ expect(page).to have_content('Test summary contained 1 failed/error test result out of 2 total tests')
within(".js-report-section-container") do
- expect(page).to have_content('rspec found 1 failed test result out of 1 total test')
+ expect(page).to have_content('rspec found 1 failed/error test result out of 1 total test')
expect(page).to have_content('junit found no changed test results out of 1 total test')
expect(page).not_to have_content('New')
expect(page).to have_content('Test#sum when a is 1 and b is 3 returns summary')
@@ -677,10 +677,10 @@ describe 'Merge request > User sees merge widget', :js do
within(".js-reports-container") do
click_button 'Expand'
- expect(page).to have_content('Test summary contained 20 failed test results out of 20 total tests')
+ expect(page).to have_content('Test summary contained 20 failed/error test results out of 20 total tests')
within(".js-report-section-container") do
- expect(page).to have_content('rspec found 10 failed test results out of 10 total tests')
- expect(page).to have_content('junit found 10 failed test results out of 10 total tests')
+ expect(page).to have_content('rspec found 10 failed/error test results out of 10 total tests')
+ expect(page).to have_content('junit found 10 failed/error test results out of 10 total tests')
expect(page).to have_content('Test#sum when a is 1 and b is 3 returns summary', count: 2)
end
diff --git a/spec/frontend/reports/store/utils_spec.js b/spec/frontend/reports/store/utils_spec.js
index 1679d120db2..f0141b9e162 100644
--- a/spec/frontend/reports/store/utils_spec.js
+++ b/spec/frontend/reports/store/utils_spec.js
@@ -30,7 +30,9 @@ describe('Reports store utils', () => {
const data = { failed: 3, total: 10 };
const result = utils.summaryTextBuilder(name, data);
- expect(result).toBe('Test summary contained 3 failed test results out of 10 total tests');
+ expect(result).toBe(
+ 'Test summary contained 3 failed/error test results out of 10 total tests',
+ );
});
it('should render text for multiple fixed results', () => {
@@ -47,7 +49,7 @@ describe('Reports store utils', () => {
const result = utils.summaryTextBuilder(name, data);
expect(result).toBe(
- 'Test summary contained 3 failed test results and 4 fixed test results out of 10 total tests',
+ 'Test summary contained 3 failed/error test results and 4 fixed test results out of 10 total tests',
);
});
@@ -57,7 +59,7 @@ describe('Reports store utils', () => {
const result = utils.summaryTextBuilder(name, data);
expect(result).toBe(
- 'Test summary contained 1 failed test result and 1 fixed test result out of 10 total tests',
+ 'Test summary contained 1 failed/error test result and 1 fixed test result out of 10 total tests',
);
});
});
@@ -84,7 +86,7 @@ describe('Reports store utils', () => {
const data = { failed: 3, total: 10 };
const result = utils.reportTextBuilder(name, data);
- expect(result).toBe('Rspec found 3 failed test results out of 10 total tests');
+ expect(result).toBe('Rspec found 3 failed/error test results out of 10 total tests');
});
it('should render text for multiple fixed results', () => {
@@ -101,7 +103,7 @@ describe('Reports store utils', () => {
const result = utils.reportTextBuilder(name, data);
expect(result).toBe(
- 'Rspec found 3 failed test results and 4 fixed test results out of 10 total tests',
+ 'Rspec found 3 failed/error test results and 4 fixed test results out of 10 total tests',
);
});
@@ -111,7 +113,7 @@ describe('Reports store utils', () => {
const result = utils.reportTextBuilder(name, data);
expect(result).toBe(
- 'Rspec found 1 failed test result and 1 fixed test result out of 10 total tests',
+ 'Rspec found 1 failed/error test result and 1 fixed test result out of 10 total tests',
);
});
});
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index d2a4ce6540d..1fa3c639603 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -902,4 +902,40 @@ describe ProjectsHelper do
end
end
end
+
+ describe '#grafana_integration_url' do
+ let(:project) { create(:project) }
+
+ before do
+ helper.instance_variable_set(:@project, project)
+ end
+
+ subject { helper.grafana_integration_url }
+
+ it { is_expected.to eq(nil) }
+
+ context 'grafana integration exists' do
+ let!(:grafana_integration) { create(:grafana_integration, project: project) }
+
+ it { is_expected.to eq(grafana_integration.grafana_url) }
+ end
+ end
+
+ describe '#grafana_integration_token' do
+ let(:project) { create(:project) }
+
+ before do
+ helper.instance_variable_set(:@project, project)
+ end
+
+ subject { helper.grafana_integration_token }
+
+ it { is_expected.to eq(nil) }
+
+ context 'grafana integration exists' do
+ let!(:grafana_integration) { create(:grafana_integration, project: project) }
+
+ it { is_expected.to eq(grafana_integration.token) }
+ end
+ end
end
diff --git a/spec/javascripts/monitoring/components/dashboard_spec.js b/spec/javascripts/monitoring/components/dashboard_spec.js
index 87aa4ba500d..ab3ab477708 100644
--- a/spec/javascripts/monitoring/components/dashboard_spec.js
+++ b/spec/javascripts/monitoring/components/dashboard_spec.js
@@ -333,8 +333,8 @@ describe('Dashboard', () => {
});
it('shows a specific time window selected from the url params', done => {
- const start = 1564439536;
- const end = 1564441336;
+ const start = '2019-10-01T18:27:47.000Z';
+ const end = '2019-10-01T18:57:47.000Z';
spyOnDependency(Dashboard, 'getTimeDiff').and.returnValue({
start,
end,
diff --git a/spec/javascripts/monitoring/utils_spec.js b/spec/javascripts/monitoring/utils_spec.js
index e22e8cdc03d..7030156931f 100644
--- a/spec/javascripts/monitoring/utils_spec.js
+++ b/spec/javascripts/monitoring/utils_spec.js
@@ -1,5 +1,5 @@
-import { getTimeDiff, graphDataValidatorForValues } from '~/monitoring/utils';
-import { timeWindows } from '~/monitoring/constants';
+import { getTimeDiff, getTimeWindow, graphDataValidatorForValues } from '~/monitoring/utils';
+import { timeWindows, timeWindowsKeyNames } from '~/monitoring/constants';
import { graphDataPrometheusQuery, graphDataPrometheusQueryRange } from './mock_data';
describe('getTimeDiff', () => {
@@ -39,6 +39,55 @@ describe('getTimeDiff', () => {
});
});
+describe('getTimeWindow', () => {
+ [
+ {
+ args: [
+ {
+ start: '2019-10-01T18:27:47.000Z',
+ end: '2019-10-01T21:27:47.000Z',
+ },
+ ],
+ expected: timeWindowsKeyNames.threeHours,
+ },
+ {
+ args: [
+ {
+ start: '2019-10-01T28:27:47.000Z',
+ end: '2019-10-01T21:27:47.000Z',
+ },
+ ],
+ expected: timeWindowsKeyNames.eightHours,
+ },
+ {
+ args: [
+ {
+ start: '',
+ end: '',
+ },
+ ],
+ expected: timeWindowsKeyNames.eightHours,
+ },
+ {
+ args: [
+ {
+ start: null,
+ end: null,
+ },
+ ],
+ expected: timeWindowsKeyNames.eightHours,
+ },
+ {
+ args: [{}],
+ expected: timeWindowsKeyNames.eightHours,
+ },
+ ].forEach(({ args, expected }) => {
+ it(`returns "${expected}" with args=${JSON.stringify(args)}`, () => {
+ expect(getTimeWindow(...args)).toEqual(expected);
+ });
+ });
+});
+
describe('graphDataValidatorForValues', () => {
/*
* When dealing with a metric using the query format, e.g.
diff --git a/spec/javascripts/reports/components/grouped_test_reports_app_spec.js b/spec/javascripts/reports/components/grouped_test_reports_app_spec.js
index 1f1e626ed33..1b006cdbd4e 100644
--- a/spec/javascripts/reports/components/grouped_test_reports_app_spec.js
+++ b/spec/javascripts/reports/components/grouped_test_reports_app_spec.js
@@ -83,11 +83,11 @@ describe('Grouped Test Reports App', () => {
setTimeout(() => {
expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
- 'Test summary contained 2 failed test results out of 11 total tests',
+ 'Test summary contained 2 failed/error test results out of 11 total tests',
);
expect(vm.$el.textContent).toContain(
- 'rspec:pg found 2 failed test results out of 8 total tests',
+ 'rspec:pg found 2 failed/error test results out of 8 total tests',
);
expect(vm.$el.textContent).toContain('New');
@@ -111,16 +111,16 @@ describe('Grouped Test Reports App', () => {
setTimeout(() => {
expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
- 'Test summary contained 2 failed test results and 2 fixed test results out of 11 total tests',
+ 'Test summary contained 2 failed/error test results and 2 fixed test results out of 11 total tests',
);
expect(vm.$el.textContent).toContain(
- 'rspec:pg found 1 failed test result and 2 fixed test results out of 8 total tests',
+ 'rspec:pg found 1 failed/error test result and 2 fixed test results out of 8 total tests',
);
expect(vm.$el.textContent).toContain('New');
expect(vm.$el.textContent).toContain(
- ' java ant found 1 failed test result out of 3 total tests',
+ ' java ant found 1 failed/error test result out of 3 total tests',
);
done();
}, 0);
diff --git a/spec/lib/backup/repository_spec.rb b/spec/lib/backup/repository_spec.rb
index e1d46c25338..582effcc303 100644
--- a/spec/lib/backup/repository_spec.rb
+++ b/spec/lib/backup/repository_spec.rb
@@ -10,7 +10,6 @@ describe Backup::Repository do
before do
allow(progress).to receive(:puts)
allow(progress).to receive(:print)
- allow(FileUtils).to receive(:mkdir_p).and_return(true)
allow(FileUtils).to receive(:mv).and_return(true)
allow_any_instance_of(described_class).to receive(:progress).and_return(progress)
diff --git a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
index 8ff60710f67..6a7fe7a5927 100644
--- a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
@@ -38,12 +38,14 @@ describe Gitlab::Ci::Parsers::Test::Junit do
end
end
- context 'when there is only one <testcase> in <testsuite>' do
+ context 'when there is only one <testsuite> in <testsuites>' do
let(:junit) do
<<-EOF.strip_heredoc
- <testsuite>
- <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
- </testsuite>
+ <testsuites>
+ <testsuite>
+ <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
+ </testsuite>
+ </testsuites>
EOF
end
@@ -56,23 +58,65 @@ describe Gitlab::Ci::Parsers::Test::Junit do
end
end
- context 'when there is only one <testsuite> in <testsuites>' do
+ context 'when there is <testcase>' do
let(:junit) do
<<-EOF.strip_heredoc
- <testsuites>
<testsuite>
- <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
+ <testcase classname='Calculator' name='sumTest1' time='0.01'>
+ #{testcase_content}
+ </testcase>
</testsuite>
- </testsuites>
EOF
end
- it 'parses XML and adds a test case to a suite' do
+ let(:test_case) { test_cases[0] }
+
+ before do
expect { subject }.not_to raise_error
+ end
- expect(test_cases[0].classname).to eq('Calculator')
- expect(test_cases[0].name).to eq('sumTest1')
- expect(test_cases[0].execution_time).to eq(0.01)
+ shared_examples_for '<testcase> XML parser' do |status, output|
+ it 'parses XML and adds a test case to the suite' do
+ aggregate_failures do
+ expect(test_case.classname).to eq('Calculator')
+ expect(test_case.name).to eq('sumTest1')
+ expect(test_case.execution_time).to eq(0.01)
+ expect(test_case.status).to eq(status)
+ expect(test_case.system_output).to eq(output)
+ end
+ end
+ end
+
+ context 'and has failure' do
+ let(:testcase_content) { '<failure>Some failure</failure>' }
+
+ it_behaves_like '<testcase> XML parser',
+ ::Gitlab::Ci::Reports::TestCase::STATUS_FAILED,
+ 'Some failure'
+ end
+
+ context 'and has error' do
+ let(:testcase_content) { '<error>Some error</error>' }
+
+ it_behaves_like '<testcase> XML parser',
+ ::Gitlab::Ci::Reports::TestCase::STATUS_FAILED,
+ 'Some error'
+ end
+
+ context 'and has an unknown type' do
+ let(:testcase_content) { '<foo>Some foo</foo>' }
+
+ it_behaves_like '<testcase> XML parser',
+ ::Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS,
+ nil
+ end
+
+ context 'and has no content' do
+ let(:testcase_content) { '' }
+
+ it_behaves_like '<testcase> XML parser',
+ ::Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS,
+ nil
end
end
diff --git a/spec/lib/gitlab/health_checks/gitaly_check_spec.rb b/spec/lib/gitlab/health_checks/gitaly_check_spec.rb
index 4912cd48761..99d10312c15 100644
--- a/spec/lib/gitlab/health_checks/gitaly_check_spec.rb
+++ b/spec/lib/gitlab/health_checks/gitaly_check_spec.rb
@@ -18,13 +18,13 @@ describe Gitlab::HealthChecks::GitalyCheck do
context 'Gitaly server is up' do
let(:gitaly_check) { double(check: { success: true }) }
- it { is_expected.to eq([result_class.new(true, nil, shard: 'default')]) }
+ it { is_expected.to eq([result_class.new('gitaly_check', true, nil, shard: 'default')]) }
end
context 'Gitaly server is down' do
let(:gitaly_check) { double(check: { success: false, message: 'Connection refused' }) }
- it { is_expected.to eq([result_class.new(false, 'Connection refused', shard: 'default')]) }
+ it { is_expected.to eq([result_class.new('gitaly_check', false, 'Connection refused', shard: 'default')]) }
end
end
diff --git a/spec/lib/gitlab/health_checks/prometheus_text_format_spec.rb b/spec/lib/gitlab/health_checks/prometheus_text_format_spec.rb
deleted file mode 100644
index ed757ed60d8..00000000000
--- a/spec/lib/gitlab/health_checks/prometheus_text_format_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-describe Gitlab::HealthChecks::PrometheusTextFormat do
- let(:metric_class) { Gitlab::HealthChecks::Metric }
- subject { described_class.new }
-
- describe '#marshal' do
- let(:sample_metrics) do
- [metric_class.new('metric1', 1),
- metric_class.new('metric2', 2)]
- end
-
- it 'marshal to text with non repeating type definition' do
- expected = <<-EXPECTED.strip_heredoc
- # TYPE metric1 gauge
- metric1 1
- # TYPE metric2 gauge
- metric2 2
- EXPECTED
-
- expect(subject.marshal(sample_metrics)).to eq(expected)
- end
-
- context 'metrics where name repeats' do
- let(:sample_metrics) do
- [metric_class.new('metric1', 1),
- metric_class.new('metric1', 2),
- metric_class.new('metric2', 3)]
- end
-
- it 'marshal to text with non repeating type definition' do
- expected = <<-EXPECTED.strip_heredoc
- # TYPE metric1 gauge
- metric1 1
- metric1 2
- # TYPE metric2 gauge
- metric2 3
- EXPECTED
- expect(subject.marshal(sample_metrics)).to eq(expected)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 16d5da59f1b..36cac12e6bd 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -411,6 +411,7 @@ project:
- external_pull_requests
- pages_metadatum
- alerts_service
+- grafana_integration
award_emoji:
- awardable
- user
diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb
index 0e66e959b24..a68ba489986 100644
--- a/spec/lib/gitlab/url_blocker_spec.rb
+++ b/spec/lib/gitlab/url_blocker_spec.rb
@@ -62,6 +62,14 @@ describe Gitlab::UrlBlocker do
expect { subject }.to raise_error(described_class::BlockedUrlError)
end
end
+
+ context 'when domain is too long' do
+ let(:import_url) { 'https://example' + 'a' * 1024 + '.com' }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(described_class::BlockedUrlError)
+ end
+ end
end
context 'when the URL hostname is an IP address' do
diff --git a/spec/models/grafana_integration_spec.rb b/spec/models/grafana_integration_spec.rb
new file mode 100644
index 00000000000..f8973097a40
--- /dev/null
+++ b/spec/models/grafana_integration_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe GrafanaIntegration do
+ describe 'associations' do
+ it { is_expected.to belong_to(:project) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:project) }
+ it { is_expected.to validate_presence_of(:token) }
+
+ it 'disallows invalid urls for grafana_url' do
+ unsafe_url = %{https://replaceme.com/'><script>alert(document.cookie)</script>}
+ non_ascii_url = 'http://gitlab.com/api/0/projects/project1/something€'
+ blank_url = ''
+ excessively_long_url = 'https://grafan' + 'a' * 1024 + '.com'
+
+ is_expected.not_to allow_values(
+ unsafe_url,
+ non_ascii_url,
+ blank_url,
+ excessively_long_url
+ ).for(:grafana_url)
+ end
+
+ it 'allows valid urls for grafana_url' do
+ external_url = 'http://grafana.com/'
+ internal_url = 'http://192.168.1.1'
+
+ is_expected.to allow_value(
+ external_url,
+ internal_url
+ ).for(:grafana_url)
+ end
+ end
+end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index a4d60467071..797be0d1fe2 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -896,32 +896,6 @@ describe Namespace do
end
end
end
-
- context 'when :emails_disabled feature flag is off' do
- before do
- stub_feature_flags(emails_disabled: false)
- end
-
- context 'when not a subgroup' do
- it 'returns false' do
- group = create(:group, emails_disabled: true)
-
- expect(group.emails_disabled?).to be_falsey
- end
- end
-
- context 'when a subgroup and ancestor emails are disabled' do
- let(:grandparent) { create(:group) }
- let(:parent) { create(:group, parent: grandparent) }
- let(:group) { create(:group, parent: parent) }
-
- it 'returns false' do
- grandparent.update_attribute(:emails_disabled, true)
-
- expect(group.emails_disabled?).to be_falsey
- end
- end
- end
end
describe '#pages_virtual_domain' do
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 45812a83c68..c6d1a17c6cb 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -2387,29 +2387,6 @@ describe Project do
expect(project.emails_disabled?).to be_truthy
end
end
-
- context 'when :emails_disabled feature flag is off' do
- before do
- stub_feature_flags(emails_disabled: false)
- end
-
- context 'emails disabled in group' do
- it 'returns false' do
- allow(project.namespace).to receive(:emails_disabled?) { true }
-
- expect(project.emails_disabled?).to be_falsey
- end
- end
-
- context 'emails enabled in group' do
- it 'returns false' do
- allow(project.namespace).to receive(:emails_disabled?) { false }
- project.update_attribute(:emails_disabled, true)
-
- expect(project.emails_disabled?).to be_falsey
- end
- end
- end
end
describe '#lfs_enabled?' do
@@ -3671,14 +3648,6 @@ describe Project do
end
end
- describe '#ensure_storage_path_exists' do
- it 'delegates to gitlab_shell to ensure namespace is created' do
- expect(gitlab_shell).to receive(:add_namespace).with(project.repository_storage, project.base_dir)
-
- project.ensure_storage_path_exists
- end
- end
-
describe '#legacy_storage?' do
it 'returns true when storage_version is nil' do
project = build(:project, storage_version: nil)
@@ -3793,16 +3762,6 @@ describe Project do
end
end
- describe '#ensure_storage_path_exists' do
- it 'delegates to gitlab_shell to ensure namespace is created' do
- allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
-
- expect(gitlab_shell).to receive(:add_namespace).with(project.repository_storage, hashed_prefix)
-
- project.ensure_storage_path_exists
- end
- end
-
describe '#pages_path' do
it 'returns a path where pages are stored' do
expect(project.pages_path).to eq(File.join(Settings.pages.path, project.namespace.full_path, project.path))
diff --git a/spec/services/groups/destroy_service_spec.rb b/spec/services/groups/destroy_service_spec.rb
index 1ab2e994b7e..b50a2db8bbe 100644
--- a/spec/services/groups/destroy_service_spec.rb
+++ b/spec/services/groups/destroy_service_spec.rb
@@ -8,7 +8,7 @@ describe Groups::DestroyService do
let!(:user) { create(:user) }
let!(:group) { create(:group) }
let!(:nested_group) { create(:group, parent: group) }
- let!(:project) { create(:project, :legacy_storage, namespace: group) }
+ let!(:project) { create(:project, :repository, :legacy_storage, namespace: group) }
let!(:notification_setting) { create(:notification_setting, source: group)}
let(:gitlab_shell) { Gitlab::Shell.new }
let(:remove_path) { group.path + "+#{group.id}+deleted" }
diff --git a/spec/services/projects/operations/update_service_spec.rb b/spec/services/projects/operations/update_service_spec.rb
index 7e765659b9d..b2f9fd6df79 100644
--- a/spec/services/projects/operations/update_service_spec.rb
+++ b/spec/services/projects/operations/update_service_spec.rb
@@ -170,5 +170,61 @@ describe Projects::Operations::UpdateService do
expect(project.reload.name).to eq(original_name)
end
end
+
+ context 'grafana integration' do
+ let(:params) do
+ {
+ grafana_integration_attributes: {
+ grafana_url: 'http://new.grafana.com',
+ token: 'VerySecureToken='
+ }
+ }
+ end
+
+ context 'without existing grafana integration' do
+ it 'creates an integration' do
+ expect(result[:status]).to eq(:success)
+
+ expected_attrs = params[:grafana_integration_attributes]
+ integration = project.reload.grafana_integration
+
+ expect(integration.grafana_url).to eq(expected_attrs[:grafana_url])
+ expect(integration.token).to eq(expected_attrs[:token])
+ end
+ end
+
+ context 'with an existing grafana integration' do
+ before do
+ create(:grafana_integration, project: project)
+ end
+
+ it 'updates the settings' do
+ expect(result[:status]).to eq(:success)
+
+ expected_attrs = params[:grafana_integration_attributes]
+ integration = project.reload.grafana_integration
+
+ expect(integration.grafana_url).to eq(expected_attrs[:grafana_url])
+ expect(integration.token).to eq(expected_attrs[:token])
+ end
+
+ context 'with all grafana attributes blank in params' do
+ let(:params) do
+ {
+ grafana_integration_attributes: {
+ grafana_url: '',
+ token: ''
+ }
+ }
+ end
+
+ it 'destroys the metrics_setting entry in DB' do
+ expect(result[:status]).to eq(:success)
+
+ expect(project.reload.grafana_integration).to be_nil
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/workers/repository_check/dispatch_worker_spec.rb b/spec/workers/repository_check/dispatch_worker_spec.rb
index 03efb6a0a80..e4bb0bf4046 100644
--- a/spec/workers/repository_check/dispatch_worker_spec.rb
+++ b/spec/workers/repository_check/dispatch_worker_spec.rb
@@ -30,8 +30,8 @@ describe RepositoryCheck::DispatchWorker do
context 'with unhealthy shard' do
let(:default_shard_name) { 'default' }
let(:unhealthy_shard_name) { 'unhealthy' }
- let(:default_shard) { Gitlab::HealthChecks::Result.new(true, nil, shard: default_shard_name) }
- let(:unhealthy_shard) { Gitlab::HealthChecks::Result.new(false, '14:Connect Failed', shard: unhealthy_shard_name) }
+ let(:default_shard) { Gitlab::HealthChecks::Result.new('gitaly_check', true, nil, shard: default_shard_name) }
+ let(:unhealthy_shard) { Gitlab::HealthChecks::Result.new('gitaly_check', false, '14:Connect Failed', shard: unhealthy_shard_name) }
before do
allow(Gitlab::HealthChecks::GitalyCheck).to receive(:readiness).and_return([default_shard, unhealthy_shard])