Commit a05477b0 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 09d81de5e5f6
import { secondsIn, timeWindowsKeyNames } from './constants'; import { secondsIn, timeWindowsKeyNames } from './constants';
const secondsToMilliseconds = seconds => seconds * 1000;
export const getTimeDiff = timeWindow => { export const getTimeDiff = timeWindow => {
const end = Math.floor(Date.now() / 1000); // convert milliseconds to seconds const end = Math.floor(Date.now() / 1000); // convert milliseconds to seconds
const difference = secondsIn[timeWindow] || secondsIn.eightHours; const difference = secondsIn[timeWindow] || secondsIn.eightHours;
const start = end - difference; const start = end - difference;
return { return {
start: new Date(start * 1000).toISOString(), start: new Date(secondsToMilliseconds(start)).toISOString(),
end: new Date(end * 1000).toISOString(), end: new Date(secondsToMilliseconds(end)).toISOString(),
}; };
}; };
export const getTimeWindow = ({ start, end }) => export const getTimeWindow = ({ start, end }) =>
Object.entries(secondsIn).reduce((acc, [timeRange, value]) => { Object.entries(secondsIn).reduce((acc, [timeRange, value]) => {
if (end - start === value) { if (new Date(end) - new Date(start) === secondsToMilliseconds(value)) {
return timeRange; return timeRange;
} }
return acc; return acc;
......
...@@ -11,7 +11,7 @@ const textBuilder = results => { ...@@ -11,7 +11,7 @@ const textBuilder = results => {
const { failed, resolved, total } = results; const { failed, resolved, total } = results;
const failedString = failed 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; : null;
const resolvedString = resolved const resolvedString = resolved
? n__('%d fixed test result', '%d fixed test results', resolved) ? n__('%d fixed test result', '%d fixed test results', resolved)
......
...@@ -4,19 +4,15 @@ class HealthController < ActionController::Base ...@@ -4,19 +4,15 @@ class HealthController < ActionController::Base
protect_from_forgery with: :exception, prepend: true protect_from_forgery with: :exception, prepend: true
include RequiresWhitelistedMonitoringClient 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 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 end
def liveness def liveness
...@@ -25,26 +21,7 @@ def liveness ...@@ -25,26 +21,7 @@ def liveness
private private
def render_check_results(results) def checks
flattened = results.flat_map do |name, result| ::Gitlab::HealthChecks::CHECKS
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
end end
end end
...@@ -63,7 +63,9 @@ def permitted_project_params ...@@ -63,7 +63,9 @@ def permitted_project_params
:api_host, :api_host,
:token, :token,
project: [:slug, :name, :organization_slug, :organization_name] project: [:slug, :name, :organization_slug, :organization_name]
] ],
grafana_integration_attributes: [:token, :grafana_url]
} }
end end
end end
......
...@@ -32,8 +32,7 @@ def can_change_share_with_group_lock?(group) ...@@ -32,8 +32,7 @@ def can_change_share_with_group_lock?(group)
end end
def can_disable_group_emails?(group) 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 end
def group_issues_count(state:) def group_issues_count(state:)
......
...@@ -160,7 +160,7 @@ def can_change_visibility_level?(project, current_user) ...@@ -160,7 +160,7 @@ def can_change_visibility_level?(project, current_user)
def can_disable_emails?(project, current_user) def can_disable_emails?(project, current_user)
return false if project.group&.emails_disabled? 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 end
def last_push_event def last_push_event
...@@ -354,6 +354,14 @@ def metrics_external_dashboard_url ...@@ -354,6 +354,14 @@ def metrics_external_dashboard_url
@project.metrics_setting_external_dashboard_url @project.metrics_setting_external_dashboard_url
end end
def grafana_integration_url
@project.grafana_integration&.grafana_url
end
def grafana_integration_token
@project.grafana_integration&.token
end
private private
def get_project_nav_tabs(project, current_user) def get_project_nav_tabs(project, current_user)
......
# 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
...@@ -182,7 +182,7 @@ def find_fork_of(project) ...@@ -182,7 +182,7 @@ def find_fork_of(project)
# any ancestor can disable emails for all descendants # any ancestor can disable emails for all descendants
def emails_disabled? def emails_disabled?
strong_memoize(:emails_disabled) do 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
end end
......
...@@ -195,6 +195,7 @@ class Project < ApplicationRecord ...@@ -195,6 +195,7 @@ class Project < ApplicationRecord
has_one :project_repository, inverse_of: :project has_one :project_repository, inverse_of: :project
has_one :error_tracking_setting, inverse_of: :project, class_name: 'ErrorTracking::ProjectErrorTrackingSetting' has_one :error_tracking_setting, inverse_of: :project, class_name: 'ErrorTracking::ProjectErrorTrackingSetting'
has_one :metrics_setting, inverse_of: :project, class_name: 'ProjectMetricsSetting' 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 # Merge Requests for target project should be removed with it
has_many :merge_requests, foreign_key: 'target_project_id', inverse_of: :target_project has_many :merge_requests, foreign_key: 'target_project_id', inverse_of: :target_project
...@@ -311,6 +312,7 @@ class Project < ApplicationRecord ...@@ -311,6 +312,7 @@ class Project < ApplicationRecord
accepts_nested_attributes_for :error_tracking_setting, update_only: true 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 :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 :name, to: :owner, allow_nil: true, prefix: true
delegate :members, to: :team, prefix: true delegate :members, to: :team, prefix: true
...@@ -664,7 +666,7 @@ def ancestors_upto(top = nil, hierarchy_order: nil) ...@@ -664,7 +666,7 @@ def ancestors_upto(top = nil, hierarchy_order: nil)
def emails_disabled? def emails_disabled?
strong_memoize(:emails_disabled) do strong_memoize(:emails_disabled) do
# disabling in the namespace overrides the project setting # 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
end end
......
...@@ -27,8 +27,12 @@ def disk_path ...@@ -27,8 +27,12 @@ def disk_path
"#{base_dir}/#{disk_hash}" if disk_hash "#{base_dir}/#{disk_hash}" if disk_hash
end 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 def ensure_storage_path_exists
gitlab_shell.add_namespace(repository_storage, base_dir) true
end end
def rename_repo(old_full_path: nil, new_full_path: nil) def rename_repo(old_full_path: nil, new_full_path: nil)
......
...@@ -23,10 +23,14 @@ def disk_path ...@@ -23,10 +23,14 @@ def disk_path
project.full_path project.full_path
end 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 def ensure_storage_path_exists
return unless namespace return unless namespace
gitlab_shell.add_namespace(repository_storage, base_dir) true
end end
def rename_repo(old_full_path: nil, new_full_path: nil) def rename_repo(old_full_path: nil, new_full_path: nil)
......
...@@ -12,7 +12,9 @@ def execute ...@@ -12,7 +12,9 @@ def execute
private private
def project_update_params def project_update_params
error_tracking_params.merge(metrics_setting_params) error_tracking_params
.merge(metrics_setting_params)
.merge(grafana_integration_params)
end end
def metrics_setting_params def metrics_setting_params
...@@ -44,6 +46,14 @@ def error_tracking_params ...@@ -44,6 +46,14 @@ def error_tracking_params
} }
} }
end 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 end
end end
......
---
title: Do not start mirroring via API when paused
merge_request: 17930
author:
type: changed
---
title: Time window filter in monitor dashboard gets reset
merge_request: 17972
author:
type: fixed
---
title: MR Test Summary now shows errors as failures.
merge_request: 17039
author:
type: changed
---
title: Create table for grafana api token for metrics embeds
merge_request: 17234
author:
type: added
...@@ -22,7 +22,7 @@ def settings_path ...@@ -22,7 +22,7 @@ def settings_path
end end
def host def host
config['gitlab']['host'] config.dig('gitlab', 'host') || ENV['GITLAB_HOST'] || 'localhost'
end end
def gl_subdomain? def gl_subdomain?
......
...@@ -16,6 +16,9 @@ en: ...@@ -16,6 +16,9 @@ en:
api_url: "Sentry API URL" api_url: "Sentry API URL"
project/metrics_setting: project/metrics_setting:
external_dashboard_url: "External dashboard URL" external_dashboard_url: "External dashboard URL"
project/grafana_integration:
token: "Grafana HTTP API Token"
grafana_url: "Grafana API URL"
views: views:
pagination: pagination:
previous: "Prev" previous: "Prev"
......
# 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
...@@ -1704,6 +1704,16 @@ ...@@ -1704,6 +1704,16 @@
t.index ["project_id"], name: "index_gpg_signatures_on_project_id" t.index ["project_id"], name: "index_gpg_signatures_on_project_id"
end 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| create_table "group_custom_attributes", id: :serial, force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false t.datetime_with_timezone "updated_at", null: false
...@@ -3997,6 +4007,7 @@ ...@@ -3997,6 +4007,7 @@
add_foreign_key "gpg_signatures", "gpg_key_subkeys", on_delete: :nullify 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", "gpg_keys", on_delete: :nullify
add_foreign_key "gpg_signatures", "projects", on_delete: :cascade 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 "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 "identities", "saml_providers", name: "fk_aade90f0fc", on_delete: :cascade
add_foreign_key "import_export_uploads", "projects", on_delete: :cascade add_foreign_key "import_export_uploads", "projects", on_delete: :cascade
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment