Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
691ed55a05
commit
27b73daa23
|
@ -1,9 +1,11 @@
|
|||
<script>
|
||||
import { GlSingleStat } from '@gitlab/ui/dist/charts';
|
||||
import { __ } from '~/locale';
|
||||
import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format';
|
||||
import { graphDataValidatorForValues } from '../../utils';
|
||||
|
||||
const defaultPrecision = 2;
|
||||
const emptyStateMsg = __('No data to display');
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -21,6 +23,9 @@ export default {
|
|||
queryInfo() {
|
||||
return this.graphData.metrics[0];
|
||||
},
|
||||
queryMetric() {
|
||||
return this.queryInfo.result[0]?.metric;
|
||||
},
|
||||
queryResult() {
|
||||
return this.queryInfo.result[0]?.value[1];
|
||||
},
|
||||
|
@ -33,6 +38,12 @@ export default {
|
|||
statValue() {
|
||||
let formatter;
|
||||
|
||||
// if field is present the metric value is not displayed. Hence
|
||||
// the early exit without formatting.
|
||||
if (this.graphData?.field) {
|
||||
return this.queryMetric?.[this.graphData.field] ?? emptyStateMsg;
|
||||
}
|
||||
|
||||
if (this.graphData?.maxValue) {
|
||||
formatter = getFormatter(SUPPORTED_FORMATS.percent);
|
||||
return formatter(this.queryResult / Number(this.graphData.maxValue), defaultPrecision);
|
||||
|
|
|
@ -173,6 +173,7 @@ const mapPanelToViewModel = ({
|
|||
x_label,
|
||||
y_label,
|
||||
y_axis = {},
|
||||
field,
|
||||
metrics = [],
|
||||
links = [],
|
||||
max_value,
|
||||
|
@ -193,6 +194,7 @@ const mapPanelToViewModel = ({
|
|||
y_label: yAxis.name, // Changing y_label to yLabel is pending https://gitlab.com/gitlab-org/gitlab/issues/207198
|
||||
yAxis,
|
||||
xAxis,
|
||||
field,
|
||||
maxValue: max_value,
|
||||
links: links.map(mapLinksToViewModel),
|
||||
metrics: mapToMetricsViewModel(metrics),
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Display metric label in single stat
|
||||
merge_request: 35289
|
||||
author:
|
||||
type: added
|
|
@ -254,6 +254,13 @@ These results can also be placed into a PostgreSQL database by setting the
|
|||
`RSPEC_PROFILING_POSTGRES_URL` variable. This is used to profile the test suite
|
||||
when running in the CI environment.
|
||||
|
||||
We store these results also when running CI jobs on the default branch on
|
||||
`gitlab.com`. Statistics of these profiling data are [available
|
||||
online](https://gitlab-org.gitlab.io/rspec_profiling_stats/). For example,
|
||||
you can find which tests take longest to run or which execute the most
|
||||
queries. This can be handy for optimizing our tests or identifying performance
|
||||
issues in our code.
|
||||
|
||||
## Memory profiling
|
||||
|
||||
One of the reasons of the increased memory footprint could be Ruby memory fragmentation.
|
||||
|
|
|
@ -545,6 +545,99 @@ In order to ensure that a clean wrapper object and DOM are being used in each te
|
|||
|
||||
See also the [Vue Test Utils documentation on `destroy`](https://vue-test-utils.vuejs.org/api/wrapper/#destroy).
|
||||
|
||||
### Jest best practices
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34209) in GitLab 13.2.
|
||||
|
||||
#### Prefer `toBe` over `toEqual` when comparing primitive values
|
||||
|
||||
Jest has [`toBe`](https://jestjs.io/docs/en/expect#tobevalue) and
|
||||
[`toEqual`](https://jestjs.io/docs/en/expect#toequalvalue) matchers.
|
||||
As [`toBe`](https://jestjs.io/docs/en/expect#tobevalue) uses
|
||||
[`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)
|
||||
to compare values, it's faster (by default) than using `toEqual`.
|
||||
While the latter will eventually fallback to leverage [`Object.is`](https://github.com/facebook/jest/blob/master/packages/expect/src/jasmineUtils.ts#L91),
|
||||
for primitive values, it should only be used when complex objects need a comparison.
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
const foo = 1;
|
||||
|
||||
// good
|
||||
expect(foo).toBe(1);
|
||||
|
||||
// bad
|
||||
expect(foo).toEqual(1);
|
||||
```
|
||||
|
||||
#### Prefer more befitting matchers
|
||||
|
||||
Jest provides useful matchers like `toHaveLength` or `toBeUndefined` to make your tests more
|
||||
readable and to produce more understandable error messages. Check their docs for the
|
||||
[full list of matchers](https://jestjs.io/docs/en/expect#methods).
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
const arr = [1, 2];
|
||||
|
||||
// prints:
|
||||
// Expected length: 1
|
||||
// Received length: 2
|
||||
expect(arr).toHaveLength(1);
|
||||
|
||||
// prints:
|
||||
// Expected: 1
|
||||
// Received: 2
|
||||
expect(arr.length).toBe(1);
|
||||
|
||||
// prints:
|
||||
// expect(received).toBe(expected) // Object.is equality
|
||||
// Expected: undefined
|
||||
// Received: "bar"
|
||||
const foo = 'bar';
|
||||
expect(foo).toBe(undefined);
|
||||
|
||||
// prints:
|
||||
// expect(received).toBeUndefined()
|
||||
// Received: "bar"
|
||||
const foo = 'bar';
|
||||
expect(foo).toBeUndefined();
|
||||
```
|
||||
|
||||
#### Avoid using `toBeTruthy` or `toBeFalsy`
|
||||
|
||||
Jest also provides following matchers: `toBeTruthy` and `toBeFalsy`. We should not use them because
|
||||
they make tests weaker and produce false-positive results.
|
||||
|
||||
For example, `expect(someBoolean).toBeFalsy()` passes when `someBoolean === null`, and when
|
||||
`someBoolean === false`.
|
||||
|
||||
#### Tricky `toBeDefined` matcher
|
||||
|
||||
Jest has the tricky `toBeDefined` matcher that can produce false positive test. Because it
|
||||
[validates](https://github.com/facebook/jest/blob/master/packages/expect/src/matchers.ts#L204)
|
||||
the given value for `undefined` only.
|
||||
|
||||
```javascript
|
||||
// good
|
||||
expect(wrapper.find('foo').exists()).toBe(true);
|
||||
|
||||
// bad
|
||||
// if finder returns null, the test will pass
|
||||
expect(wrapper.find('foo')).toBeDefined();
|
||||
```
|
||||
|
||||
#### Avoid using `setImmediate`
|
||||
|
||||
Try to avoid using `setImmediate`. `setImmediate` is an ad-hoc solution to run your callback after
|
||||
the I/O completes. And it's not part of the Web API, hence, we target NodeJS environments in our
|
||||
unit tests.
|
||||
|
||||
Instead of `setImmediate`, use `jest.runAllTimers` or `jest.runOnlyPendingTimers` to run pending timers.
|
||||
The latter is useful when you have `setInterval` in the code. **Remember:** our Jest configuration uses fake timers.
|
||||
|
||||
## Factories
|
||||
|
||||
TBU
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
|
@ -74,7 +74,7 @@ You can also dismiss vulnerabilities in the table:
|
|||
1. Select the checkbox for each vulnerability you want to dismiss.
|
||||
1. In the menu that appears, select the reason for dismissal and click **Dismiss Selected**.
|
||||
|
||||
![Project Security Dashboard](img/project_security_dashboard_v13_2_noNav.png)
|
||||
![Project Security Dashboard](img/project_security_dashboard_v13_2.png)
|
||||
|
||||
## Group Security Dashboard
|
||||
|
||||
|
|
|
@ -139,13 +139,13 @@ module Gitlab
|
|||
%r{\Arubocop/cop/migration(/|\.rb)} => :database,
|
||||
|
||||
%r{\A(\.gitlab-ci\.yml\z|\.gitlab\/ci)} => :engineering_productivity,
|
||||
%r{\A\.codeclimate\.yml\z} => :engineering_productivity,
|
||||
%r{\A\.overcommit\.yml\.example\z} => :engineering_productivity,
|
||||
%r{\Atooling/overcommit/} => :engineering_productivity,
|
||||
%r{\A.editorconfig\z} => :engineering_productivity,
|
||||
%r{\A\.editorconfig\z} => :engineering_productivity,
|
||||
%r{Dangerfile\z} => :engineering_productivity,
|
||||
%r{\A(ee/)?(danger/|lib/gitlab/danger/)} => :engineering_productivity,
|
||||
%r{\A(ee/)?scripts/} => :engineering_productivity,
|
||||
%r{\A\.codeclimate\.yml\z} => :engineering_productivity,
|
||||
%r{\Atooling/} => :engineering_productivity,
|
||||
|
||||
%r{\A(ee/)?app/(?!assets|views)[^/]+} => :backend,
|
||||
%r{\A(ee/)?(bin|config|generator_templates|lib|rubocop)/} => :backend,
|
||||
|
|
|
@ -752,6 +752,9 @@ msgstr ""
|
|||
msgid "(external source)"
|
||||
msgstr ""
|
||||
|
||||
msgid "(line: %{startLine})"
|
||||
msgstr ""
|
||||
|
||||
msgid "(removed)"
|
||||
msgstr ""
|
||||
|
||||
|
@ -25677,6 +25680,9 @@ msgstr ""
|
|||
msgid "Vulnerability|File"
|
||||
msgstr ""
|
||||
|
||||
msgid "Vulnerability|Identifier"
|
||||
msgstr ""
|
||||
|
||||
msgid "Vulnerability|Identifiers"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
"@babel/plugin-syntax-import-meta": "^7.10.1",
|
||||
"@babel/preset-env": "^7.10.1",
|
||||
"@gitlab/at.js": "1.5.5",
|
||||
"@gitlab/svgs": "1.148.0",
|
||||
"@gitlab/svgs": "1.150.0",
|
||||
"@gitlab/ui": "17.16.0",
|
||||
"@gitlab/visual-review-tools": "1.6.1",
|
||||
"@rails/actioncable": "^6.0.3-1",
|
||||
|
|
|
@ -13,6 +13,10 @@ module QA
|
|||
@secondary_node = @second_node
|
||||
end
|
||||
|
||||
def enable_writes
|
||||
shell "docker exec praefect bash -c '/opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml enable-writes -virtual-storage default'"
|
||||
end
|
||||
|
||||
def stop_primary_node
|
||||
shell "docker stop #{@primary_node}"
|
||||
@secondary_node, @primary_node = @primary_node, @secondary_node
|
||||
|
|
|
@ -10,7 +10,7 @@ module QA
|
|||
end
|
||||
end
|
||||
let(:initial_file) { 'pushed_to_primary.txt' }
|
||||
let(:final_file) { 'pushed_to_secondary.txt' }
|
||||
let(:final_file) { 'committed_to_primary.txt' }
|
||||
let(:praefect_manager) { Service::PraefectManager.new }
|
||||
|
||||
before do
|
||||
|
@ -41,11 +41,13 @@ module QA
|
|||
expect(show).to have_file(initial_file)
|
||||
end
|
||||
|
||||
praefect_manager.enable_writes
|
||||
|
||||
Resource::Repository::Commit.fabricate_via_api! do |commit|
|
||||
commit.project = project
|
||||
commit.add_files([
|
||||
{
|
||||
file_path: 'committed_to_primary.txt',
|
||||
file_path: final_file,
|
||||
content: 'This should exist on both nodes too'
|
||||
}
|
||||
])
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
require 'pathname'
|
||||
|
||||
module QA
|
||||
context 'Configure' do
|
||||
RSpec.describe 'Configure' do
|
||||
let(:project) do
|
||||
Resource::Project.fabricate_via_api! do |project|
|
||||
project.name = Runtime::Env.auto_devops_project_name || 'autodevops-project'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
context 'Configure' do
|
||||
RSpec.describe 'Configure' do
|
||||
describe 'Kubernetes Cluster Integration', :orchestrated, :kubernetes, :requires_admin, :skip_live_env do
|
||||
context 'Project Clusters' do
|
||||
let!(:cluster) { Service::KubernetesCluster.new(provider_class: Service::ClusterProvider::K3s).create! }
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'gitlab'
|
||||
require_relative File.expand_path('../../lib/quality/helm3_client.rb', __dir__)
|
||||
require_relative File.expand_path('../../lib/quality/kubernetes_client.rb', __dir__)
|
||||
require_relative File.expand_path('../../tooling/lib/tooling/helm3_client.rb', __dir__)
|
||||
require_relative File.expand_path('../../tooling/lib/tooling/kubernetes_client.rb', __dir__)
|
||||
|
||||
class AutomatedCleanup
|
||||
attr_reader :project_path, :gitlab_token
|
||||
|
@ -44,11 +44,11 @@ class AutomatedCleanup
|
|||
end
|
||||
|
||||
def helm
|
||||
@helm ||= Quality::Helm3Client.new(namespace: review_apps_namespace)
|
||||
@helm ||= Tooling::Helm3Client.new(namespace: review_apps_namespace)
|
||||
end
|
||||
|
||||
def kubernetes
|
||||
@kubernetes ||= Quality::KubernetesClient.new(namespace: review_apps_namespace)
|
||||
@kubernetes ||= Tooling::KubernetesClient.new(namespace: review_apps_namespace)
|
||||
end
|
||||
|
||||
def perform_gitlab_environment_cleanup!(days_for_stop:, days_for_delete:)
|
||||
|
@ -76,7 +76,7 @@ class AutomatedCleanup
|
|||
if deployed_at < delete_threshold
|
||||
deleted_environment = delete_environment(environment, deployment)
|
||||
if deleted_environment
|
||||
release = Quality::Helm3Client::Release.new(environment.slug, 1, deployed_at.to_s, nil, nil, review_apps_namespace)
|
||||
release = Tooling::Helm3Client::Release.new(environment.slug, 1, deployed_at.to_s, nil, nil, review_apps_namespace)
|
||||
releases_to_delete << release
|
||||
end
|
||||
else
|
||||
|
@ -157,11 +157,11 @@ class AutomatedCleanup
|
|||
helm.delete(release_name: releases_names)
|
||||
kubernetes.cleanup(release_name: releases_names, wait: false)
|
||||
|
||||
rescue Quality::Helm3Client::CommandFailedError => ex
|
||||
rescue Tooling::Helm3Client::CommandFailedError => ex
|
||||
raise ex unless ignore_exception?(ex.message, IGNORED_HELM_ERRORS)
|
||||
|
||||
puts "Ignoring the following Helm error:\n#{ex}\n"
|
||||
rescue Quality::KubernetesClient::CommandFailedError => ex
|
||||
rescue Tooling::KubernetesClient::CommandFailedError => ex
|
||||
raise ex unless ignore_exception?(ex.message, IGNORED_KUBERNETES_ERRORS)
|
||||
|
||||
puts "Ignoring the following Kubernetes error:\n#{ex}\n"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import SingleStatChart from '~/monitoring/components/charts/single_stat.vue';
|
||||
import { singleStatMetricsResult } from '../../mock_data';
|
||||
import { singleStatMetricsResult, singleStatMetricsWithFieldResult } from '../../mock_data';
|
||||
|
||||
describe('Single Stat Chart component', () => {
|
||||
let singleStatChart;
|
||||
|
@ -66,6 +66,31 @@ describe('Single Stat Chart component', () => {
|
|||
|
||||
expect(singleStatChart.vm.statValue).toContain('NaN');
|
||||
});
|
||||
|
||||
describe('field attribute', () => {
|
||||
it('displays a label value instead of metric value when field attribute is used', () => {
|
||||
singleStatChart.setProps({
|
||||
graphData: singleStatMetricsWithFieldResult,
|
||||
});
|
||||
|
||||
return singleStatChart.vm.$nextTick(() => {
|
||||
expect(singleStatChart.vm.statValue).toContain('prometheus');
|
||||
});
|
||||
});
|
||||
|
||||
it('displays No data to display if field attribute is not present', () => {
|
||||
singleStatChart.setProps({
|
||||
graphData: {
|
||||
...singleStatMetricsWithFieldResult,
|
||||
field: 'this-does-not-exist',
|
||||
},
|
||||
});
|
||||
|
||||
return singleStatChart.vm.$nextTick(() => {
|
||||
expect(singleStatChart.vm.statValue).toContain('No data to display');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -359,6 +359,11 @@ export const singleStatMetricsResult = {
|
|||
],
|
||||
};
|
||||
|
||||
export const singleStatMetricsWithFieldResult = {
|
||||
...singleStatMetricsResult,
|
||||
field: 'job',
|
||||
};
|
||||
|
||||
export const graphDataPrometheusQueryRangeMultiTrack = {
|
||||
title: 'Super Chart A3',
|
||||
type: 'heatmap',
|
||||
|
|
|
@ -10,6 +10,7 @@ describe('MRWidgetSuggestPipeline', () => {
|
|||
let trackingSpy;
|
||||
|
||||
const mockTrackingOnWrapper = () => {
|
||||
unmockTracking();
|
||||
trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require_relative '../../../../tooling/lib/tooling/helm3_client'
|
||||
|
||||
RSpec.describe Quality::Helm3Client do
|
||||
RSpec.describe Tooling::Helm3Client do
|
||||
let(:namespace) { 'review-apps' }
|
||||
let(:release_name) { 'my-release' }
|
||||
let(:raw_helm_list_page1) do
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require_relative '../../../../tooling/lib/tooling/kubernetes_client'
|
||||
|
||||
RSpec.describe Quality::KubernetesClient do
|
||||
RSpec.describe Tooling::KubernetesClient do
|
||||
let(:namespace) { 'review-apps' }
|
||||
let(:release_name) { 'my-release' }
|
||||
let(:pod_for_release) { "pod-my-release-abcd" }
|
|
@ -3,7 +3,7 @@
|
|||
require_relative '../../../../tooling/lib/tooling/test_file_finder'
|
||||
|
||||
RSpec.describe Tooling::TestFileFinder do
|
||||
subject { Tooling::TestFileFinder.new(file) }
|
||||
subject { described_class.new(file) }
|
||||
|
||||
describe '#test_files' do
|
||||
context 'when given non .rb files' do
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'time'
|
||||
require_relative '../gitlab/popen' unless defined?(Gitlab::Popen)
|
||||
require 'json'
|
||||
require_relative '../../../lib/gitlab/popen' unless defined?(Gitlab::Popen)
|
||||
require_relative '../../../lib/gitlab/json' unless defined?(Gitlab::Json)
|
||||
|
||||
module Quality
|
||||
module Tooling
|
||||
class Helm3Client
|
||||
CommandFailedError = Class.new(StandardError)
|
||||
|
||||
|
@ -65,12 +67,12 @@ module Quality
|
|||
%(--output json),
|
||||
*args
|
||||
]
|
||||
releases = JSON.parse(run_command(command))
|
||||
releases = Gitlab::Json.parse(run_command(command))
|
||||
|
||||
releases.map do |release|
|
||||
Release.new(*release.values_at(*RELEASE_JSON_ATTRIBUTES))
|
||||
end
|
||||
rescue JSON::ParserError => ex
|
||||
rescue ::JSON::ParserError => ex
|
||||
puts "Ignoring this JSON parsing error: #{ex}" # rubocop:disable Rails/Output
|
||||
[]
|
||||
end
|
|
@ -1,8 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../gitlab/popen' unless defined?(Gitlab::Popen)
|
||||
require_relative '../../../lib/gitlab/popen' unless defined?(Gitlab::Popen)
|
||||
require_relative '../../../lib/gitlab/json' unless defined?(Gitlab::JSON)
|
||||
|
||||
module Quality
|
||||
module Tooling
|
||||
class KubernetesClient
|
||||
RESOURCE_LIST = 'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa,crd'
|
||||
CommandFailedError = Class.new(StandardError)
|
|
@ -843,10 +843,10 @@
|
|||
eslint-plugin-vue "^6.2.1"
|
||||
vue-eslint-parser "^7.0.0"
|
||||
|
||||
"@gitlab/svgs@1.148.0":
|
||||
version "1.148.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.148.0.tgz#cb3fd68249d7e97d0c578bf443459a32370a6dba"
|
||||
integrity sha512-5GJtUNjCBzEdfi1J3jZPr7UUsvZ1KYnzK3VkMPmp+t2GNWHtdqBmi3Y6WKTOWJo8qFIAJO0tIs6w7XMMCIUBCg==
|
||||
"@gitlab/svgs@1.150.0":
|
||||
version "1.150.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.150.0.tgz#7dbbdf1b50c4409adf30d23710bbe4515608e245"
|
||||
integrity sha512-jfD1EiawNlBM1XNEz7hriPJg2UOX6zE2/lKMIocSpkg9R58VGyIr+oyWOTn2AfknrepsLfnTiGJNveLdRYcy4w==
|
||||
|
||||
"@gitlab/ui@17.16.0":
|
||||
version "17.16.0"
|
||||
|
|
Loading…
Reference in New Issue