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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/services/groups/group_links/destroy_service.rb26
-rw-r--r--app/workers/remove_expired_group_links_worker.rb4
-rw-r--r--changelogs/unreleased/include-worker-attributes-in-sidekiq-metrics.yml5
-rw-r--r--doc/administration/geo/replication/database.md3
-rw-r--r--jest.config.js2
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events.rb18
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start.rb2
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/issue_created.rb2
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/issue_first_mentioned_in_commit.rb8
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/issue_stage_end.rb4
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_created.rb2
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_first_deployed_to_production.rb4
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_finished.rb8
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_started.rb8
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_merged.rb8
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/metrics_based_stage_event.rb17
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/plan_stage_start.rb5
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/production_stage_end.rb2
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/simple_stage_event.rb13
-rw-r--r--lib/gitlab/sidekiq_middleware/metrics.rb22
-rw-r--r--locale/gitlab.pot18
-rw-r--r--package.json1
-rw-r--r--spec/frontend/monitoring/charts/time_series_spec.js (renamed from spec/javascripts/monitoring/charts/time_series_spec.js)40
-rw-r--r--spec/frontend/monitoring/panel_type_spec.js (renamed from spec/javascripts/monitoring/panel_type_spec.js)23
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb92
-rw-r--r--spec/services/groups/group_links/destroy_service_spec.rb63
-rw-r--r--spec/workers/remove_expired_group_links_worker_spec.rb57
-rw-r--r--yarn.lock22
28 files changed, 305 insertions, 174 deletions
diff --git a/app/services/groups/group_links/destroy_service.rb b/app/services/groups/group_links/destroy_service.rb
new file mode 100644
index 00000000000..29aa8de4e68
--- /dev/null
+++ b/app/services/groups/group_links/destroy_service.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Groups
+ module GroupLinks
+ class DestroyService < BaseService
+ def execute(one_or_more_links)
+ links = Array(one_or_more_links)
+
+ GroupGroupLink.transaction do
+ GroupGroupLink.delete(links)
+
+ groups_to_refresh = links.map(&:shared_with_group)
+ groups_to_refresh.uniq.each do |group|
+ group.refresh_members_authorized_projects
+ end
+
+ Gitlab::AppLogger.info("GroupGroupLinks with ids: #{links.map(&:id)} have been deleted.")
+ rescue => ex
+ Gitlab::AppLogger.error(ex)
+
+ raise
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/remove_expired_group_links_worker.rb b/app/workers/remove_expired_group_links_worker.rb
index 147b412b772..a43e6fd11d5 100644
--- a/app/workers/remove_expired_group_links_worker.rb
+++ b/app/workers/remove_expired_group_links_worker.rb
@@ -8,5 +8,9 @@ class RemoveExpiredGroupLinksWorker
def perform
ProjectGroupLink.expired.destroy_all # rubocop: disable DestroyAll
+
+ GroupGroupLink.expired.find_in_batches do |link_batch|
+ Groups::GroupLinks::DestroyService.new(nil, nil).execute(link_batch)
+ end
end
end
diff --git a/changelogs/unreleased/include-worker-attributes-in-sidekiq-metrics.yml b/changelogs/unreleased/include-worker-attributes-in-sidekiq-metrics.yml
deleted file mode 100644
index ea7e229d0ea..00000000000
--- a/changelogs/unreleased/include-worker-attributes-in-sidekiq-metrics.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add worker attributes to Sidekiq metrics
-merge_request: 19491
-author:
-type: other
diff --git a/doc/administration/geo/replication/database.md b/doc/administration/geo/replication/database.md
index fa1b0f0e1d7..0919e62ab6c 100644
--- a/doc/administration/geo/replication/database.md
+++ b/doc/administration/geo/replication/database.md
@@ -425,6 +425,9 @@ data before running `pg_basebackup`.
--host=<primary_node_ip>
```
+ NOTE: **Note:**
+ Replication slot names must only contain lowercase letters, numbers, and the underscore character.
+
When prompted, enter the _plaintext_ password you set up for the `gitlab_replicator`
user in the first step.
diff --git a/jest.config.js b/jest.config.js
index f5e589934e6..3f9dc3fe213 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -60,7 +60,7 @@ module.exports = {
cacheDirectory: '<rootDir>/tmp/cache/jest',
modulePathIgnorePatterns: ['<rootDir>/.yarn-cache/'],
reporters,
- setupFilesAfterEnv: ['<rootDir>/spec/frontend/test_setup.js'],
+ setupFilesAfterEnv: ['<rootDir>/spec/frontend/test_setup.js', 'jest-canvas-mock'],
restoreMocks: true,
transform: {
'^.+\\.(gql|graphql)$': 'jest-transform-graphql',
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events.rb b/lib/gitlab/analytics/cycle_analytics/stage_events.rb
index 58572446de6..f6e22044142 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events.rb
@@ -47,27 +47,29 @@ module Gitlab
]
}.freeze
- def [](identifier)
+ def self.[](identifier)
events.find { |e| e.identifier.to_s.eql?(identifier.to_s) } || raise(KeyError)
end
# hash for defining ActiveRecord enum: identifier => number
- def to_enum
- ENUM_MAPPING.each_with_object({}) { |(k, v), hash| hash[k.identifier] = v }
+ def self.to_enum
+ enum_mapping.each_with_object({}) { |(k, v), hash| hash[k.identifier] = v }
end
- # will be overridden in EE with custom events
- def pairing_rules
+ def self.pairing_rules
PAIRING_RULES
end
- # will be overridden in EE with custom events
- def events
+ def self.events
EVENTS
end
- module_function :[], :to_enum, :pairing_rules, :events
+ def self.enum_mapping
+ ENUM_MAPPING
+ end
end
end
end
end
+
+Gitlab::Analytics::CycleAnalytics::StageEvents.prepend_if_ee('::EE::Gitlab::Analytics::CycleAnalytics::StageEvents')
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start.rb
index 6af1b90bccc..9f0ca80ba50 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start.rb
@@ -4,7 +4,7 @@ module Gitlab
module Analytics
module CycleAnalytics
module StageEvents
- class CodeStageStart < SimpleStageEvent
+ class CodeStageStart < StageEvent
def self.name
s_("CycleAnalyticsEvent|Issue first mentioned in a commit")
end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/issue_created.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/issue_created.rb
index 8c9a80740a9..a159580b7bd 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/issue_created.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/issue_created.rb
@@ -4,7 +4,7 @@ module Gitlab
module Analytics
module CycleAnalytics
module StageEvents
- class IssueCreated < SimpleStageEvent
+ class IssueCreated < StageEvent
def self.name
s_("CycleAnalyticsEvent|Issue created")
end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/issue_first_mentioned_in_commit.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/issue_first_mentioned_in_commit.rb
index fe7f2d85f8b..a3b7fa16daf 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/issue_first_mentioned_in_commit.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/issue_first_mentioned_in_commit.rb
@@ -4,7 +4,7 @@ module Gitlab
module Analytics
module CycleAnalytics
module StageEvents
- class IssueFirstMentionedInCommit < SimpleStageEvent
+ class IssueFirstMentionedInCommit < MetricsBasedStageEvent
def self.name
s_("CycleAnalyticsEvent|Issue first mentioned in a commit")
end
@@ -20,12 +20,6 @@ module Gitlab
def timestamp_projection
issue_metrics_table[:first_mentioned_in_commit_at]
end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def apply_query_customization(query)
- query.joins(:metrics)
- end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/issue_stage_end.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/issue_stage_end.rb
index 77e4092b9ab..0ea98e82ecc 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/issue_stage_end.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/issue_stage_end.rb
@@ -4,7 +4,7 @@ module Gitlab
module Analytics
module CycleAnalytics
module StageEvents
- class IssueStageEnd < SimpleStageEvent
+ class IssueStageEnd < MetricsBasedStageEvent
def self.name
PlanStageStart.name
end
@@ -26,7 +26,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def apply_query_customization(query)
- query.joins(:metrics).where(issue_metrics_table[:first_added_to_board_at].not_eq(nil).or(issue_metrics_table[:first_associated_with_milestone_at].not_eq(nil)))
+ super.where(issue_metrics_table[:first_added_to_board_at].not_eq(nil).or(issue_metrics_table[:first_associated_with_milestone_at].not_eq(nil)))
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_created.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_created.rb
index 7059c425b8f..013e068e479 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_created.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_created.rb
@@ -4,7 +4,7 @@ module Gitlab
module Analytics
module CycleAnalytics
module StageEvents
- class MergeRequestCreated < SimpleStageEvent
+ class MergeRequestCreated < StageEvent
def self.name
s_("CycleAnalyticsEvent|Merge request created")
end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_first_deployed_to_production.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_first_deployed_to_production.rb
index 3d7482eaaf0..654d0befbc3 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_first_deployed_to_production.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_first_deployed_to_production.rb
@@ -4,7 +4,7 @@ module Gitlab
module Analytics
module CycleAnalytics
module StageEvents
- class MergeRequestFirstDeployedToProduction < SimpleStageEvent
+ class MergeRequestFirstDeployedToProduction < MetricsBasedStageEvent
def self.name
s_("CycleAnalyticsEvent|Merge request first deployed to production")
end
@@ -23,7 +23,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def apply_query_customization(query)
- query.joins(:metrics).where(timestamp_projection.gteq(mr_table[:created_at]))
+ super.where(timestamp_projection.gteq(mr_table[:created_at]))
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_finished.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_finished.rb
index 36bb4d6fc8d..a0b1c12756f 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_finished.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_finished.rb
@@ -4,7 +4,7 @@ module Gitlab
module Analytics
module CycleAnalytics
module StageEvents
- class MergeRequestLastBuildFinished < SimpleStageEvent
+ class MergeRequestLastBuildFinished < MetricsBasedStageEvent
def self.name
s_("CycleAnalyticsEvent|Merge request last build finish time")
end
@@ -20,12 +20,6 @@ module Gitlab
def timestamp_projection
mr_metrics_table[:latest_build_finished_at]
end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def apply_query_customization(query)
- query.joins(:metrics)
- end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_started.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_started.rb
index 468d9899cc7..da3b5cdfaa4 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_started.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_build_started.rb
@@ -4,7 +4,7 @@ module Gitlab
module Analytics
module CycleAnalytics
module StageEvents
- class MergeRequestLastBuildStarted < SimpleStageEvent
+ class MergeRequestLastBuildStarted < MetricsBasedStageEvent
def self.name
s_("CycleAnalyticsEvent|Merge request last build start time")
end
@@ -20,12 +20,6 @@ module Gitlab
def timestamp_projection
mr_metrics_table[:latest_build_started_at]
end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def apply_query_customization(query)
- query.joins(:metrics)
- end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_merged.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_merged.rb
index 82ecaf1cd6b..e67a6f7eea6 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_merged.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_merged.rb
@@ -4,7 +4,7 @@ module Gitlab
module Analytics
module CycleAnalytics
module StageEvents
- class MergeRequestMerged < SimpleStageEvent
+ class MergeRequestMerged < MetricsBasedStageEvent
def self.name
s_("CycleAnalyticsEvent|Merge request merged")
end
@@ -20,12 +20,6 @@ module Gitlab
def timestamp_projection
mr_metrics_table[:merged_at]
end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def apply_query_customization(query)
- query.joins(:metrics)
- end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/metrics_based_stage_event.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/metrics_based_stage_event.rb
new file mode 100644
index 00000000000..4ca8745abe4
--- /dev/null
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/metrics_based_stage_event.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Analytics
+ module CycleAnalytics
+ module StageEvents
+ class MetricsBasedStageEvent < StageEvent
+ # rubocop: disable CodeReuse/ActiveRecord
+ def apply_query_customization(query)
+ query.joins(:metrics)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/plan_stage_start.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/plan_stage_start.rb
index 7ece7d62faa..37168a1fb0f 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/plan_stage_start.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/plan_stage_start.rb
@@ -4,7 +4,7 @@ module Gitlab
module Analytics
module CycleAnalytics
module StageEvents
- class PlanStageStart < SimpleStageEvent
+ class PlanStageStart < MetricsBasedStageEvent
def self.name
s_("CycleAnalyticsEvent|Issue first associated with a milestone or issue first added to a board")
end
@@ -26,8 +26,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def apply_query_customization(query)
- query
- .joins(:metrics)
+ super
.where(issue_metrics_table[:first_added_to_board_at].not_eq(nil).or(issue_metrics_table[:first_associated_with_milestone_at].not_eq(nil)))
.where(issue_metrics_table[:first_mentioned_in_commit_at].not_eq(nil))
end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/production_stage_end.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/production_stage_end.rb
index 607371a32e8..b249f6874e7 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/production_stage_end.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/production_stage_end.rb
@@ -4,7 +4,7 @@ module Gitlab
module Analytics
module CycleAnalytics
module StageEvents
- class ProductionStageEnd < SimpleStageEvent
+ class ProductionStageEnd < StageEvent
def self.name
PlanStageStart.name
end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/simple_stage_event.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/simple_stage_event.rb
deleted file mode 100644
index 253c489d822..00000000000
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/simple_stage_event.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Analytics
- module CycleAnalytics
- module StageEvents
- # Represents a simple event that usually refers to one database column and does not require additional user input
- class SimpleStageEvent < StageEvent
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/sidekiq_middleware/metrics.rb b/lib/gitlab/sidekiq_middleware/metrics.rb
index 64e77a2d828..bd819843bd4 100644
--- a/lib/gitlab/sidekiq_middleware/metrics.rb
+++ b/lib/gitlab/sidekiq_middleware/metrics.rb
@@ -13,8 +13,8 @@ module Gitlab
@metrics[:sidekiq_concurrency].set({}, Sidekiq.options[:concurrency].to_i)
end
- def call(worker, job, queue)
- labels = create_labels(worker, queue)
+ def call(_worker, job, queue)
+ labels = create_labels(queue)
queue_duration = ::Gitlab::InstrumentationHelper.queue_duration_for_job(job)
@metrics[:sidekiq_jobs_queue_duration_seconds].observe(labels, queue_duration) if queue_duration
@@ -62,20 +62,10 @@ module Gitlab
}
end
- def create_labels(worker, queue)
- labels = { queue: queue }
- return labels unless worker.include? WorkerAttributes
-
- labels[:latency_sensitive] = true if worker.latency_sensitive_worker?
- labels[:external_deps] = true if worker.worker_has_external_dependencies?
-
- feature_category = worker.get_feature_category
- labels[:feat_cat] = feature_category if feature_category
-
- resource_boundary = worker.get_worker_resource_boundary
- labels[:boundary] = resource_boundary if resource_boundary && resource_boundary != :unknown
-
- labels
+ def create_labels(queue)
+ {
+ queue: queue
+ }
end
def get_thread_cputime
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index dde99a8583a..05eb287274a 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -4995,15 +4995,30 @@ msgstr ""
msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr ""
+msgid "CycleAnalyticsEvent|Issue closed"
+msgstr ""
+
msgid "CycleAnalyticsEvent|Issue created"
msgstr ""
+msgid "CycleAnalyticsEvent|Issue first added to a board"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first associated with a milestone"
+msgstr ""
+
msgid "CycleAnalyticsEvent|Issue first associated with a milestone or issue first added to a board"
msgstr ""
msgid "CycleAnalyticsEvent|Issue first mentioned in a commit"
msgstr ""
+msgid "CycleAnalyticsEvent|Issue last edited"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request closed"
+msgstr ""
+
msgid "CycleAnalyticsEvent|Merge request created"
msgstr ""
@@ -5016,6 +5031,9 @@ msgstr ""
msgid "CycleAnalyticsEvent|Merge request last build start time"
msgstr ""
+msgid "CycleAnalyticsEvent|Merge request last edited"
+msgstr ""
+
msgid "CycleAnalyticsEvent|Merge request merged"
msgstr ""
diff --git a/package.json b/package.json
index 183a978ca75..7deb8401f6d 100644
--- a/package.json
+++ b/package.json
@@ -174,6 +174,7 @@
"jasmine-diff": "^0.1.3",
"jasmine-jquery": "^2.1.1",
"jest": "^24.1.0",
+ "jest-canvas-mock": "^2.1.2",
"jest-environment-jsdom": "^24.0.0",
"jest-junit": "^6.3.0",
"jest-util": "^24.0.0",
diff --git a/spec/javascripts/monitoring/charts/time_series_spec.js b/spec/frontend/monitoring/charts/time_series_spec.js
index 42feaca616b..03d63ef7c3e 100644
--- a/spec/javascripts/monitoring/charts/time_series_spec.js
+++ b/spec/frontend/monitoring/charts/time_series_spec.js
@@ -2,21 +2,34 @@ import { shallowMount } from '@vue/test-utils';
import { createStore } from '~/monitoring/stores';
import { GlLink } from '@gitlab/ui';
import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
-import { shallowWrapperContainsSlotText } from 'spec/helpers/vue_test_utils_helper';
+import { shallowWrapperContainsSlotText } from 'helpers/vue_test_utils_helper';
import TimeSeries from '~/monitoring/components/charts/time_series.vue';
import * as types from '~/monitoring/stores/mutation_types';
import { TEST_HOST } from 'spec/test_constants';
-import MonitoringMock, { deploymentData, mockProjectPath } from '../mock_data';
+import MonitoringMock, {
+ deploymentData,
+ mockProjectPath,
+} from '../../../javascripts/monitoring/mock_data';
+import * as iconUtils from '~/lib/utils/icon_utils';
+
+const mockSvgPathContent = 'mockSvgPathContent';
+const mockSha = 'mockSha';
+const mockWidgets = 'mockWidgets';
+const projectPath = `${TEST_HOST}${mockProjectPath}`;
+const commitUrl = `${projectPath}/commit/${mockSha}`;
+
+jest.mock('~/lib/utils/icon_utils', () => ({
+ getSvgIconPathContent: jest.fn().mockImplementation(
+ () =>
+ new Promise(resolve => {
+ resolve(mockSvgPathContent);
+ }),
+ ),
+}));
describe('Time series component', () => {
- const mockSha = 'mockSha';
- const mockWidgets = 'mockWidgets';
- const mockSvgPathContent = 'mockSvgPathContent';
- const projectPath = `${TEST_HOST}${mockProjectPath}`;
- const commitUrl = `${projectPath}/commit/${mockSha}`;
let mockGraphData;
let makeTimeSeriesChart;
- let spriteSpy;
let store;
beforeEach(() => {
@@ -27,6 +40,7 @@ describe('Time series component', () => {
makeTimeSeriesChart = (graphData, type) =>
shallowMount(TimeSeries, {
+ attachToDocument: true,
propsData: {
graphData: { ...graphData, type },
deploymentData: store.state.monitoringDashboard.deploymentData,
@@ -38,10 +52,6 @@ describe('Time series component', () => {
sync: false,
store,
});
-
- spriteSpy = spyOnDependency(TimeSeries, 'getSvgIconPathContent').and.callFake(
- () => new Promise(resolve => resolve(mockSvgPathContent)),
- );
});
describe('general functions', () => {
@@ -147,7 +157,7 @@ describe('Time series component', () => {
});
it('gets svg path content', () => {
- expect(spriteSpy).toHaveBeenCalledWith(mockSvgName);
+ expect(iconUtils.getSvgIconPathContent).toHaveBeenCalledWith(mockSvgName);
});
it('sets svg path content', () => {
@@ -171,7 +181,7 @@ describe('Time series component', () => {
const mockWidth = 233;
beforeEach(() => {
- spyOn(Element.prototype, 'getBoundingClientRect').and.callFake(() => ({
+ jest.spyOn(Element.prototype, 'getBoundingClientRect').mockImplementation(() => ({
width: mockWidth,
}));
timeSeriesChart.vm.onResize();
@@ -227,7 +237,7 @@ describe('Time series component', () => {
option: mockOption,
});
- expect(timeSeriesChart.vm.chartOptions).toEqual(jasmine.objectContaining(mockOption));
+ expect(timeSeriesChart.vm.chartOptions).toEqual(expect.objectContaining(mockOption));
});
it('additional series', () => {
diff --git a/spec/javascripts/monitoring/panel_type_spec.js b/spec/frontend/monitoring/panel_type_spec.js
index e3781117eaf..1cf302c25da 100644
--- a/spec/javascripts/monitoring/panel_type_spec.js
+++ b/spec/frontend/monitoring/panel_type_spec.js
@@ -1,17 +1,31 @@
import { shallowMount } from '@vue/test-utils';
+import AxiosMockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
import PanelType from '~/monitoring/components/panel_type.vue';
import EmptyChart from '~/monitoring/components/charts/empty_chart.vue';
import TimeSeriesChart from '~/monitoring/components/charts/time_series.vue';
import AnomalyChart from '~/monitoring/components/charts/anomaly.vue';
-import { graphDataPrometheusQueryRange } from './mock_data';
+import { graphDataPrometheusQueryRange } from '../../javascripts/monitoring/mock_data';
import { anomalyMockGraphData } from '../../frontend/monitoring/mock_data';
import { createStore } from '~/monitoring/stores';
+global.IS_EE = true;
+global.URL.createObjectURL = jest.fn(() => {});
+
describe('Panel Type component', () => {
+ let axiosMock;
let store;
let panelType;
const dashboardWidth = 100;
+ beforeEach(() => {
+ axiosMock = new AxiosMockAdapter(axios);
+ });
+
+ afterEach(() => {
+ axiosMock.reset();
+ });
+
describe('When no graphData is available', () => {
let glEmptyChart;
// Deep clone object before modifying
@@ -25,6 +39,7 @@ describe('Panel Type component', () => {
dashboardWidth,
graphData: graphDataNoResult,
},
+ sync: false,
});
});
@@ -57,14 +72,14 @@ describe('Panel Type component', () => {
graphData: graphDataPrometheusQueryRange,
};
- beforeEach(done => {
+ beforeEach(() => {
store = createStore();
panelType = shallowMount(PanelType, {
propsData,
- sync: false,
store,
+ sync: false,
+ attachToDocument: true,
});
- panelType.vm.$nextTick(done);
});
describe('Time Series Chart panel type', () => {
diff --git a/spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb
index c9399f591da..0d8cff3a295 100644
--- a/spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/metrics_spec.rb
@@ -1,11 +1,8 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-require 'rspec-parameterized'
describe Gitlab::SidekiqMiddleware::Metrics do
- using RSpec::Parameterized::TableSyntax
-
let(:middleware) { described_class.new }
let(:concurrency_metric) { double('concurrency metric') }
@@ -48,7 +45,7 @@ describe Gitlab::SidekiqMiddleware::Metrics do
let(:job) { {} }
let(:job_status) { :done }
let(:labels) { { queue: :test } }
- let(:labels_with_job_status) { labels.merge(job_status: job_status) }
+ let(:labels_with_job_status) { { queue: :test, job_status: job_status } }
let(:thread_cputime_before) { 1 }
let(:thread_cputime_after) { 2 }
@@ -60,75 +57,52 @@ describe Gitlab::SidekiqMiddleware::Metrics do
let(:queue_duration_for_job) { 0.01 }
- where(:worker_has_attributes, :worker_is_latency_sensitive, :worker_has_external_dependencies, :worker_feature_category, :worker_resource_boundary, :labels) do
- false | false | false | nil | nil | { queue: :test }
- true | false | false | nil | nil | { queue: :test }
- true | true | false | nil | nil | { queue: :test, latency_sensitive: true }
- true | false | true | nil | nil | { queue: :test, external_deps: true }
- true | false | false | :authentication | nil | { queue: :test, feat_cat: :authentication }
- true | false | false | nil | :cpu | { queue: :test, boundary: :cpu }
- true | false | false | nil | :memory | { queue: :test, boundary: :memory }
- true | false | false | nil | :unknown | { queue: :test }
- true | true | true | :authentication | :cpu | { queue: :test, latency_sensitive: true, external_deps: true, feat_cat: :authentication, boundary: :cpu }
- end
+ before do
+ allow(middleware).to receive(:get_thread_cputime).and_return(thread_cputime_before, thread_cputime_after)
+ allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(monotonic_time_before, monotonic_time_after)
+ allow(Gitlab::InstrumentationHelper).to receive(:queue_duration_for_job).with(job).and_return(queue_duration_for_job)
- with_them do
- before do
- allow(middleware).to receive(:get_thread_cputime).and_return(thread_cputime_before, thread_cputime_after)
- allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(monotonic_time_before, monotonic_time_after)
- allow(Gitlab::InstrumentationHelper).to receive(:queue_duration_for_job).with(job).and_return(queue_duration_for_job)
-
- # Attributes
- allow(worker).to receive(:include?).with(WorkerAttributes).and_return(worker_has_attributes)
- allow(worker).to receive(:latency_sensitive_worker?).and_return(worker_is_latency_sensitive)
- allow(worker).to receive(:worker_has_external_dependencies?).and_return(worker_has_external_dependencies)
- allow(worker).to receive(:get_worker_resource_boundary).and_return(worker_resource_boundary)
- allow(worker).to receive(:get_feature_category).and_return(worker_feature_category)
-
- expect(running_jobs_metric).to receive(:increment).with(labels, 1)
- expect(running_jobs_metric).to receive(:increment).with(labels, -1)
-
- expect(queue_duration_seconds).to receive(:observe).with(labels, queue_duration_for_job) if queue_duration_for_job
- expect(user_execution_seconds_metric).to receive(:observe).with(labels_with_job_status, thread_cputime_duration)
- expect(completion_seconds_metric).to receive(:observe).with(labels_with_job_status, monotonic_time_duration)
- end
+ expect(running_jobs_metric).to receive(:increment).with(labels, 1)
+ expect(running_jobs_metric).to receive(:increment).with(labels, -1)
- it 'yields block' do
- expect { |b| middleware.call(worker, job, :test, &b) }.to yield_control.once
- end
+ expect(queue_duration_seconds).to receive(:observe).with(labels, queue_duration_for_job) if queue_duration_for_job
+ expect(user_execution_seconds_metric).to receive(:observe).with(labels_with_job_status, thread_cputime_duration)
+ expect(completion_seconds_metric).to receive(:observe).with(labels_with_job_status, monotonic_time_duration)
+ end
- it 'sets queue specific metrics' do
- middleware.call(worker, job, :test) { nil }
- end
+ it 'yields block' do
+ expect { |b| middleware.call(worker, job, :test, &b) }.to yield_control.once
+ end
- context 'when job_duration is not available' do
- let(:queue_duration_for_job) { nil }
+ it 'sets queue specific metrics' do
+ middleware.call(worker, job, :test) { nil }
+ end
- it 'does not set the queue_duration_seconds histogram' do
- expect(queue_duration_seconds).not_to receive(:observe)
+ context 'when job_duration is not available' do
+ let(:queue_duration_for_job) { nil }
- middleware.call(worker, job, :test) { nil }
- end
+ it 'does not set the queue_duration_seconds histogram' do
+ middleware.call(worker, job, :test) { nil }
end
+ end
- context 'when job is retried' do
- let(:job) { { 'retry_count' => 1 } }
+ context 'when job is retried' do
+ let(:job) { { 'retry_count' => 1 } }
- it 'sets sidekiq_jobs_retried_total metric' do
- expect(retried_total_metric).to receive(:increment)
+ it 'sets sidekiq_jobs_retried_total metric' do
+ expect(retried_total_metric).to receive(:increment)
- middleware.call(worker, job, :test) { nil }
- end
+ middleware.call(worker, job, :test) { nil }
end
+ end
- context 'when error is raised' do
- let(:job_status) { :fail }
+ context 'when error is raised' do
+ let(:job_status) { :fail }
- it 'sets sidekiq_jobs_failed_total and reraises' do
- expect(failed_total_metric).to receive(:increment).with(labels, 1)
+ it 'sets sidekiq_jobs_failed_total and reraises' do
+ expect(failed_total_metric).to receive(:increment).with(labels, 1)
- expect { middleware.call(worker, job, :test) { raise StandardError, "Failed" } }.to raise_error(StandardError, "Failed")
- end
+ expect { middleware.call(worker, job, :test) { raise StandardError, "Failed" } }.to raise_error(StandardError, "Failed")
end
end
end
diff --git a/spec/services/groups/group_links/destroy_service_spec.rb b/spec/services/groups/group_links/destroy_service_spec.rb
new file mode 100644
index 00000000000..6f49b6eda94
--- /dev/null
+++ b/spec/services/groups/group_links/destroy_service_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Groups::GroupLinks::DestroyService, '#execute' do
+ let(:user) { create(:user) }
+
+ let_it_be(:group) { create(:group, :private) }
+ let_it_be(:shared_group) { create(:group, :private) }
+ let_it_be(:project) { create(:project, group: shared_group) }
+
+ subject { described_class.new(nil, nil) }
+
+ context 'single link' do
+ let!(:link) { create(:group_group_link, shared_group: shared_group, shared_with_group: group) }
+
+ it 'destroys link' do
+ expect { subject.execute(link) }.to change { GroupGroupLink.count }.from(1).to(0)
+ end
+
+ it 'revokes project authorization' do
+ group.add_developer(user)
+
+ expect { subject.execute(link) }.to(
+ change { Ability.allowed?(user, :read_project, project) }.from(true).to(false))
+ end
+ end
+
+ context 'multiple links' do
+ let_it_be(:another_group) { create(:group, :private) }
+ let_it_be(:another_shared_group) { create(:group, :private) }
+
+ let!(:links) do
+ [
+ create(:group_group_link, shared_group: shared_group, shared_with_group: group),
+ create(:group_group_link, shared_group: shared_group, shared_with_group: another_group),
+ create(:group_group_link, shared_group: another_shared_group, shared_with_group: group),
+ create(:group_group_link, shared_group: another_shared_group, shared_with_group: another_group)
+ ]
+ end
+
+ it 'updates project authorization once per group' do
+ expect(GroupGroupLink).to receive(:delete)
+ expect(group).to receive(:refresh_members_authorized_projects).once
+ expect(another_group).to receive(:refresh_members_authorized_projects).once
+
+ subject.execute(links)
+ end
+
+ it 'rolls back changes when error happens' do
+ group.add_developer(user)
+
+ expect(group).to receive(:refresh_members_authorized_projects).once.and_call_original
+ expect(another_group).to(
+ receive(:refresh_members_authorized_projects).and_raise('boom'))
+
+ expect { subject.execute(links) }.to raise_error('boom')
+
+ expect(GroupGroupLink.count).to eq(links.length)
+ expect(Ability.allowed?(user, :read_project, project)).to be_truthy
+ end
+ end
+end
diff --git a/spec/workers/remove_expired_group_links_worker_spec.rb b/spec/workers/remove_expired_group_links_worker_spec.rb
index 10d9aa37dee..9557aa3086c 100644
--- a/spec/workers/remove_expired_group_links_worker_spec.rb
+++ b/spec/workers/remove_expired_group_links_worker_spec.rb
@@ -4,23 +4,54 @@ require 'spec_helper'
describe RemoveExpiredGroupLinksWorker do
describe '#perform' do
- let!(:expired_project_group_link) { create(:project_group_link, expires_at: 1.hour.ago) }
- let!(:project_group_link_expiring_in_future) { create(:project_group_link, expires_at: 10.days.from_now) }
- let!(:non_expiring_project_group_link) { create(:project_group_link, expires_at: nil) }
+ context 'ProjectGroupLinks' do
+ let!(:expired_project_group_link) { create(:project_group_link, expires_at: 1.hour.ago) }
+ let!(:project_group_link_expiring_in_future) { create(:project_group_link, expires_at: 10.days.from_now) }
+ let!(:non_expiring_project_group_link) { create(:project_group_link, expires_at: nil) }
- it 'removes expired group links' do
- expect { subject.perform }.to change { ProjectGroupLink.count }.by(-1)
- expect(ProjectGroupLink.find_by(id: expired_project_group_link.id)).to be_nil
- end
+ it 'removes expired group links' do
+ expect { subject.perform }.to change { ProjectGroupLink.count }.by(-1)
+ expect(ProjectGroupLink.find_by(id: expired_project_group_link.id)).to be_nil
+ end
+
+ it 'leaves group links that expire in the future' do
+ subject.perform
+ expect(project_group_link_expiring_in_future.reload).to be_present
+ end
- it 'leaves group links that expire in the future' do
- subject.perform
- expect(project_group_link_expiring_in_future.reload).to be_present
+ it 'leaves group links that do not expire at all' do
+ subject.perform
+ expect(non_expiring_project_group_link.reload).to be_present
+ end
end
- it 'leaves group links that do not expire at all' do
- subject.perform
- expect(non_expiring_project_group_link.reload).to be_present
+ context 'GroupGroupLinks' do
+ let(:mock_destroy_service) { instance_double(Groups::GroupLinks::DestroyService) }
+
+ before do
+ allow(Groups::GroupLinks::DestroyService).to(
+ receive(:new).and_return(mock_destroy_service))
+ end
+
+ context 'expired GroupGroupLink exists' do
+ before do
+ create(:group_group_link, expires_at: 1.hour.ago)
+ end
+
+ it 'calls Groups::GroupLinks::DestroyService' do
+ expect(mock_destroy_service).to receive(:execute).once
+
+ subject.perform
+ end
+ end
+
+ context 'expired GroupGroupLink does not exist' do
+ it 'does not call Groups::GroupLinks::DestroyService' do
+ expect(mock_destroy_service).not_to receive(:execute)
+
+ subject.perform
+ end
+ end
end
end
end
diff --git a/yarn.lock b/yarn.lock
index 9beb499025c..515ac2b3549 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2991,7 +2991,7 @@ collection-visit@^1.0.0:
map-visit "^1.0.0"
object-visit "^1.0.0"
-color-convert@^0.5.3:
+color-convert@^0.5.3, color-convert@~0.5.0:
version "0.5.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd"
integrity sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=
@@ -3468,6 +3468,11 @@ cssesc@^3.0.0:
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
+cssfontparser@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/cssfontparser/-/cssfontparser-1.2.1.tgz#f4022fc8f9700c68029d542084afbaf425a3f3e3"
+ integrity sha1-9AIvyPlwDGgCnVQghK+69CWj8+M=
+
cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
version "0.3.4"
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.4.tgz#8cd52e8a3acfd68d3aed38ee0a640177d2f9d797"
@@ -6877,6 +6882,14 @@ jed@^1.1.1:
resolved "https://registry.yarnpkg.com/jed/-/jed-1.1.1.tgz#7a549bbd9ffe1585b0cd0a191e203055bee574b4"
integrity sha1-elSbvZ/+FYWwzQoZHiAwVb7ldLQ=
+jest-canvas-mock@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/jest-canvas-mock/-/jest-canvas-mock-2.1.2.tgz#0d16c9f91534f773fd132fc289f2e6b6db8faa28"
+ integrity sha512-1VI4PK4/X70yrSjYScYVkYJYbXYlZLKJkUrAlyHjQsfolv64aoFyIrmMDtqCjpYrpVvWYEcAGUaYv5DVJj00oQ==
+ dependencies:
+ cssfontparser "^1.2.1"
+ parse-color "^1.0.0"
+
jest-changed-files@^24.8.0:
version "24.8.0"
resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.8.0.tgz#7e7eb21cf687587a85e50f3d249d1327e15b157b"
@@ -9123,6 +9136,13 @@ parse-asn1@^5.0.0:
evp_bytestokey "^1.0.0"
pbkdf2 "^3.0.3"
+parse-color@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/parse-color/-/parse-color-1.0.0.tgz#7b748b95a83f03f16a94f535e52d7f3d94658619"
+ integrity sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=
+ dependencies:
+ color-convert "~0.5.0"
+
parse-entities@^1.0.2, parse-entities@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.0.tgz#9deac087661b2e36814153cb78d7e54a4c5fd6f4"