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

Add latest changes from gitlab-org/gitlab@master

parent 09d81de5e5f6
......@@ -49,6 +49,12 @@ def create_test_case(data)
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
......
# 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
......@@ -29,7 +29,13 @@ def metrics
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
......
# 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
# 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
# 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
......@@ -8,14 +8,14 @@ module SimpleAbstractCheck
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
......
......@@ -113,10 +113,6 @@ def import_repository(storage, name, url, gl_project_path)
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 @@ def mv_namespace(storage, old_name, new_name)
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"
......
......@@ -125,6 +125,11 @@ def get_address_info(uri, dns_rebind_protection)
# 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(
......
......@@ -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] ""
......
......@@ -32,7 +32,8 @@
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
......
......@@ -180,6 +180,21 @@ def stub_operations_update_service_returning(return_value = {})
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 = {})
......
# 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
......@@ -536,10 +536,10 @@ def compared_data
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 @@ def compared_data
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 @@ def compared_data
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
......
......@@ -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',
);
});
});
......
......@@ -902,4 +902,40 @@ def grant_user_access(project, user, access)
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
......@@ -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,
......
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.
......
......@@ -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);
......
......@@ -10,7 +10,6 @@
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)
......
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