diff --git a/app/assets/javascripts/projects/storage_counter/components/app.vue b/app/assets/javascripts/projects/storage_counter/components/app.vue index 19f9d29efaa..773459df14f 100644 --- a/app/assets/javascripts/projects/storage_counter/components/app.vue +++ b/app/assets/javascripts/projects/storage_counter/components/app.vue @@ -1,13 +1,50 @@ diff --git a/app/assets/javascripts/projects/storage_counter/index.js b/app/assets/javascripts/projects/storage_counter/index.js index 915ee263063..8812bfb56a2 100644 --- a/app/assets/javascripts/projects/storage_counter/index.js +++ b/app/assets/javascripts/projects/storage_counter/index.js @@ -1,6 +1,10 @@ import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; import StorageCounterApp from './components/app.vue'; +Vue.use(VueApollo); + export default (containerId = 'js-project-storage-count-app') => { const el = document.getElementById(containerId); @@ -8,8 +12,18 @@ export default (containerId = 'js-project-storage-count-app') => { return false; } + const { projectPath } = el.dataset; + + const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + }); + return new Vue({ el, + apolloProvider, + provide: { + projectPath, + }, render(createElement) { return createElement(StorageCounterApp); }, diff --git a/app/assets/javascripts/projects/storage_counter/queries/project_storage.query.graphql b/app/assets/javascripts/projects/storage_counter/queries/project_storage.query.graphql new file mode 100644 index 00000000000..8e549846875 --- /dev/null +++ b/app/assets/javascripts/projects/storage_counter/queries/project_storage.query.graphql @@ -0,0 +1,15 @@ +query getProjectStorageCount($fullPath: ID!) { + project(fullPath: $fullPath) { + id + statistics { + buildArtifactsSize + lfsObjectsSize + packagesSize + repositorySize + snippetsSize + storageSize + uploadsSize + wikiSize + } + } +} diff --git a/app/assets/javascripts/projects/storage_counter/utils.js b/app/assets/javascripts/projects/storage_counter/utils.js new file mode 100644 index 00000000000..009aabbc221 --- /dev/null +++ b/app/assets/javascripts/projects/storage_counter/utils.js @@ -0,0 +1,64 @@ +import { numberToHumanSize } from '~/lib/utils/number_utils'; +import { s__ } from '~/locale'; + +const projectStorageTypes = [ + { + id: 'buildArtifactsSize', + name: s__('UsageQuota|Artifacts'), + }, + { + id: 'lfsObjectsSize', + name: s__('UsageQuota|LFS Storage'), + }, + { + id: 'packagesSize', + name: s__('UsageQuota|Packages'), + }, + { + id: 'repositorySize', + name: s__('UsageQuota|Repository'), + }, + { + id: 'snippetsSize', + name: s__('UsageQuota|Snippets'), + }, + { + id: 'uploadsSize', + name: s__('UsageQuota|Uploads'), + }, + { + id: 'wikiSize', + name: s__('UsageQuota|Wiki'), + }, +]; + +/** + * This method parses the results from `getProjectStorageCount` call. + * + * @param {Object} data graphql result + * @returns {Object} + */ +export const parseGetProjectStorageResults = (data) => { + const projectStatistics = data?.project?.statistics; + if (!projectStatistics) { + return {}; + } + const { storageSize, ...storageStatistics } = projectStatistics; + const storageTypes = projectStorageTypes.reduce((types, currentType) => { + if (!storageStatistics[currentType.id]) { + return types; + } + + return types.concat({ + ...currentType, + value: numberToHumanSize(storageStatistics[currentType.id]), + }); + }, []); + + return { + storage: { + totalUsage: numberToHumanSize(storageSize), + storageTypes, + }, + }; +}; diff --git a/app/models/group.rb b/app/models/group.rb index 4ded7174619..3874258a403 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -823,9 +823,15 @@ class Group < Namespace end def self.groups_including_descendants_by(group_ids) - Gitlab::ObjectHierarchy - .new(Group.where(id: group_ids)) + groups = Group.where(id: group_ids) + + if Feature.enabled?(:linear_group_including_descendants_by, default_enabled: :yaml) + groups.self_and_descendants + else + Gitlab::ObjectHierarchy + .new(groups) .base_and_descendants + end end def disable_shared_runners! diff --git a/app/views/groups/settings/repository/_initial_branch_name.html.haml b/app/views/groups/settings/repository/_initial_branch_name.html.haml index 5299c38576d..15a3bacf12d 100644 --- a/app/views/groups/settings/repository/_initial_branch_name.html.haml +++ b/app/views/groups/settings/repository/_initial_branch_name.html.haml @@ -1,6 +1,6 @@ %section.settings.as-default-branch-name.no-animate#js-default-branch-name{ class: ('expanded' if expanded_by_default?) } .settings-header - %h4 + %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only = _('Default initial branch name') %button.gl-button.js-settings-toggle{ type: 'button' } = expanded_by_default? ? _('Collapse') : _('Expand') diff --git a/app/views/projects/usage_quotas/index.html.haml b/app/views/projects/usage_quotas/index.html.haml index f45f8a2fd1d..a6b3ba7153d 100644 --- a/app/views/projects/usage_quotas/index.html.haml +++ b/app/views/projects/usage_quotas/index.html.haml @@ -14,4 +14,4 @@ = s_('UsageQuota|Storage') .tab-content .tab-pane#storage-quota-tab - #js-project-storage-count-app + #js-project-storage-count-app{ data: { project_path: @project.full_path } } diff --git a/app/workers/expire_job_cache_worker.rb b/app/workers/expire_job_cache_worker.rb index 5c2f0e0b664..207ae8be692 100644 --- a/app/workers/expire_job_cache_worker.rb +++ b/app/workers/expire_job_cache_worker.rb @@ -3,7 +3,7 @@ class ExpireJobCacheWorker # rubocop:disable Scalability/IdempotentWorker include ApplicationWorker - data_consistency :delayed, feature_flag: :load_balancing_for_expire_job_cache_worker + data_consistency :delayed sidekiq_options retry: 3 include PipelineQueue diff --git a/config/feature_flags/development/load_balancing_for_expire_job_cache_worker.yml b/config/feature_flags/development/linear_group_including_descendants_by.yml similarity index 64% rename from config/feature_flags/development/load_balancing_for_expire_job_cache_worker.yml rename to config/feature_flags/development/linear_group_including_descendants_by.yml index 25c4c9d6eb9..cf70edce6cc 100644 --- a/config/feature_flags/development/load_balancing_for_expire_job_cache_worker.yml +++ b/config/feature_flags/development/linear_group_including_descendants_by.yml @@ -1,8 +1,8 @@ --- -name: load_balancing_for_expire_job_cache_worker -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68791 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339137 +name: linear_group_including_descendants_by +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68835 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339431 milestone: '14.3' type: development -group: group::pipeline authoring +group: group::access default_enabled: false diff --git a/doc/ci/index.md b/doc/ci/index.md index b9e56a016a8..8d5c5c082ba 100644 --- a/doc/ci/index.md +++ b/doc/ci/index.md @@ -9,33 +9,23 @@ type: index # GitLab CI/CD **(FREE)** -GitLab CI/CD is a tool built into GitLab for software development -through the [continuous methodologies](introduction/index.md): +GitLab CI/CD is a tool for software development using the continuous methodologies: -- Continuous Integration (CI) -- Continuous Delivery (CD) -- Continuous Deployment (CD) +- [Continuous Integration (CI)](introduction/index.md#continuous-integration) +- [Continuous Delivery (CD)](introduction/index.md#continuous-delivery) +- [Continuous Deployment (CD)](introduction/index.md#continuous-deployment) NOTE: Out-of-the-box management systems can decrease hours spent on maintaining toolchains by 10% or more. Watch our ["Mastering continuous software development"](https://about.gitlab.com/webcast/mastering-ci-cd/) -webcast to learn about continuous methods and how the GitLab built-in CI can help you simplify and scale software development. +webcast to learn about continuous methods and how GitLab CI/CD can help you simplify and scale software development. -Continuous Integration works by pushing small code chunks to your -application's codebase hosted in a Git repository, and to every -push, run a pipeline of scripts to build, test, and validate the -code changes before merging them into the main branch. - -Continuous Delivery and Deployment consist of a step further CI, -deploying your application to production at every -push to the default branch of the repository. - -These methodologies allow you to catch bugs and errors early in -the development cycle, ensuring that all the code deployed to +Use GitLab CI/CD to catch bugs and errors early in +the development cycle. Ensure that all the code deployed to production complies with the code standards you established for your app. -GitLab can also automatically detect, build, test, deploy, and +GitLab CI/CD can automatically build, test, deploy, and monitor your applications by using [Auto DevOps](../topics/autodevops/index.md). For a complete overview of these methodologies and GitLab CI/CD, @@ -82,21 +72,20 @@ GitLab CI/CD supports numerous configuration options: Certain operations can only be performed according to the [user](../user/permissions.md#gitlab-cicd-permissions) and [job](../user/permissions.md#job-permissions) permissions. -## Feature set +## Features -Use the vast GitLab CI/CD to easily configure it for specific purposes. -Its feature set is listed on the table below according to DevOps stages. +GitLab CI/CD features, grouped by DevOps stage, include: | Feature | Description | |:------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------| | **Configure** | | | [Auto DevOps](../topics/autodevops/index.md) | Set up your app's entire lifecycle. | -| [ChatOps](chatops/index.md) | Trigger CI jobs from chat, with results sent back to the channel. | +| [ChatOps](chatops/index.md) | Trigger CI jobs from chat, with results sent back to the channel. | |-------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------| | **Verify** | | | [Browser Performance Testing](../user/project/merge_requests/browser_performance_testing.md) | Quickly determine the browser performance impact of pending code changes. | | [Load Performance Testing](../user/project/merge_requests/load_performance_testing.md) | Quickly determine the server performance impact of pending code changes. | -| [CI services](services/index.md) | Link Docker containers with your base image. | +| [CI services](services/index.md) | Link Docker containers with your base image. | | [Code Quality](../user/project/merge_requests/code_quality.md) | Analyze your source code quality. | | [GitLab CI/CD for external repositories](ci_cd_for_external_repos/index.md) **(PREMIUM)** | Get the benefits of GitLab CI/CD combined with repositories in GitHub and Bitbucket Cloud. | | [Interactive Web Terminals](interactive_web_terminal/index.md) **(FREE SELF)** | Open an interactive web terminal to debug the running jobs. | @@ -122,28 +111,27 @@ Its feature set is listed on the table below according to DevOps stages. ## Examples -Find example project code and tutorials for using GitLab CI/CD with a variety of app frameworks, languages, and platforms -on the [CI Examples](examples/README.md) page. +See the [CI/CD examples](examples/README.md) page for example project code and tutorials for +using GitLab CI/CD with various: -## Administration **(FREE SELF)** +- App frameworks +- Languages +- Platforms -As a GitLab administrator, you can change the default behavior -of GitLab CI/CD for: +## Administration -- An [entire GitLab instance](../user/admin_area/settings/continuous_integration.md). -- Specific projects, using [pipelines settings](pipelines/settings.md). +You can change the default behavior of GitLab CI/CD for: + +- An entire GitLab instance in the [CI/CD administration settings](../administration/index.md#cicd-settings). +- Specific projects in the [pipelines settings](pipelines/settings.md). See also: - [Enable or disable GitLab CI/CD in a project](enable_or_disable_ci.md). -- [Disable GitLab CI/CD by default in new projects](../administration/cicd.md). **(FREE SELF)** -- Other [CI administration settings](../administration/index.md#cicd-settings). ## References -### Why GitLab CI/CD? - -Learn more about: +Learn more about GitLab CI/CD: - [Why you might choose GitLab CI/CD](https://about.gitlab.com/blog/2016/10/17/gitlab-ci-oohlala/). - [Reasons you might migrate from another platform](https://about.gitlab.com/blog/2016/07/22/building-our-web-app-on-gitlab-ci/). @@ -151,10 +139,10 @@ Learn more about: See also the [Why CI/CD?](https://docs.google.com/presentation/d/1OGgk2Tcxbpl7DJaIOzCX4Vqg3dlwfELC3u2jEeCBbDk) presentation. -### Breaking changes +### Major version changes (breaking) As GitLab CI/CD has evolved, certain breaking changes have -been necessary. These are: +been necessary. #### 13.0 diff --git a/doc/ci/migration/jenkins.md b/doc/ci/migration/jenkins.md index 1a987a0ce47..a83ce81a35c 100644 --- a/doc/ci/migration/jenkins.md +++ b/doc/ci/migration/jenkins.md @@ -199,7 +199,7 @@ GitLab takes advantage of our connected ecosystem to automatically pull these ki your Merge Requests, pipeline details pages, and other locations. You may find that you actually don't need to configure anything to have these appear. -If they aren't working as expected, or if you'd like to see what's available, our [CI feature index](../index.md#feature-set) has the full list +If they aren't working as expected, or if you'd like to see what's available, our [CI feature index](../index.md#features) has the full list of bundled features and links to the documentation for each. ### Templates diff --git a/doc/ci/quick_start/index.md b/doc/ci/quick_start/index.md index 7d106641819..e8e0bf50840 100644 --- a/doc/ci/quick_start/index.md +++ b/doc/ci/quick_start/index.md @@ -7,8 +7,7 @@ type: reference # Get started with GitLab CI/CD **(FREE)** -Use this document to get started with -GitLab [continuous integration](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/). +Use this document to get started with [GitLab CI/CD](../index.md). Before you start, make sure you have: diff --git a/lib/gitlab/database/load_balancing.rb b/lib/gitlab/database/load_balancing.rb index 08f108eb8e4..c967072e422 100644 --- a/lib/gitlab/database/load_balancing.rb +++ b/lib/gitlab/database/load_balancing.rb @@ -102,7 +102,9 @@ module Gitlab def self.start_service_discovery return unless service_discovery_enabled? - ServiceDiscovery.new(service_discovery_configuration).start + ServiceDiscovery + .new(proxy.load_balancer, **service_discovery_configuration) + .start end # Configures proxying of requests. @@ -111,7 +113,9 @@ module Gitlab # Populate service discovery immediately if it is configured if service_discovery_enabled? - ServiceDiscovery.new(service_discovery_configuration).perform_service_discovery + ServiceDiscovery + .new(proxy.load_balancer, **service_discovery_configuration) + .perform_service_discovery end end diff --git a/lib/gitlab/database/load_balancing/service_discovery.rb b/lib/gitlab/database/load_balancing/service_discovery.rb index d22134379da..f04ecfa5e72 100644 --- a/lib/gitlab/database/load_balancing/service_discovery.rb +++ b/lib/gitlab/database/load_balancing/service_discovery.rb @@ -49,14 +49,14 @@ module Gitlab # use_tcp - Use TCP instaed of UDP to look up resources # load_balancer - The load balancer instance to use def initialize( + load_balancer, nameserver:, port:, record:, record_type: 'A', interval: 60, disconnect_timeout: 120, - use_tcp: false, - load_balancer: LoadBalancing.proxy.load_balancer + use_tcp: false ) @nameserver = nameserver @port = port diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 3437935d2fe..56966bbfa18 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -36085,6 +36085,9 @@ msgstr "" msgid "UsageQuota|Snippets" msgstr "" +msgid "UsageQuota|Something went wrong while fetching project storage statistics" +msgstr "" + msgid "UsageQuota|Storage" msgstr "" diff --git a/package.json b/package.json index 3f3a2a2fb2e..187707811b9 100644 --- a/package.json +++ b/package.json @@ -65,16 +65,16 @@ "@rails/ujs": "6.1.3-2", "@sentry/browser": "5.26.0", "@sourcegraph/code-host-integration": "0.0.59", - "@tiptap/core": "^2.0.0-beta.86", + "@tiptap/core": "^2.0.0-beta.101", "@tiptap/extension-blockquote": "^2.0.0-beta.15", "@tiptap/extension-bold": "^2.0.0-beta.15", "@tiptap/extension-bullet-list": "^2.0.0-beta.15", "@tiptap/extension-code": "^2.0.0-beta.16", - "@tiptap/extension-code-block-lowlight": "2.0.0-beta.32", + "@tiptap/extension-code-block-lowlight": "2.0.0-beta.35", "@tiptap/extension-document": "^2.0.0-beta.13", - "@tiptap/extension-dropcursor": "^2.0.0-beta.18", + "@tiptap/extension-dropcursor": "^2.0.0-beta.19", "@tiptap/extension-gapcursor": "^2.0.0-beta.19", - "@tiptap/extension-hard-break": "^2.0.0-beta.14", + "@tiptap/extension-hard-break": "^2.0.0-beta.15", "@tiptap/extension-heading": "^2.0.0-beta.15", "@tiptap/extension-history": "^2.0.0-beta.16", "@tiptap/extension-horizontal-rule": "^2.0.0-beta.19", @@ -94,7 +94,7 @@ "@tiptap/extension-task-item": "^2.0.0-beta.17", "@tiptap/extension-task-list": "^2.0.0-beta.17", "@tiptap/extension-text": "^2.0.0-beta.13", - "@tiptap/vue-2": "^2.0.0-beta.39", + "@tiptap/vue-2": "^2.0.0-beta.48", "@toast-ui/editor": "^2.5.2", "@toast-ui/vue-editor": "^2.5.2", "apollo-cache-inmemory": "^1.6.6", @@ -163,7 +163,7 @@ "prismjs": "^1.21.0", "prosemirror-inputrules": "^1.1.3", "prosemirror-markdown": "^1.5.1", - "prosemirror-model": "^1.13.3", + "prosemirror-model": "^1.14.3", "prosemirror-state": "^1.3.4", "prosemirror-tables": "^1.1.1", "raphael": "^2.2.7", @@ -180,8 +180,8 @@ "three-orbit-controls": "^82.1.0", "three-stl-loader": "^1.0.4", "timeago.js": "^4.0.2", - "tiptap": "^1.32.1", - "tiptap-extensions": "^1.35.1", + "tiptap": "^1.32.2", + "tiptap-extensions": "^1.35.2", "url-loader": "^4.1.1", "uuid": "8.1.0", "visibilityjs": "^1.2.4", diff --git a/spec/features/clusters/cluster_health_dashboard_spec.rb b/spec/features/clusters/cluster_health_dashboard_spec.rb index e4a36f654e5..88d6976c2be 100644 --- a/spec/features/clusters/cluster_health_dashboard_spec.rb +++ b/spec/features/clusters/cluster_health_dashboard_spec.rb @@ -80,8 +80,8 @@ RSpec.describe 'Cluster Health board', :js, :kubeclient, :use_clean_rails_memory expect(page).to have_content('Avg') end - it 'focuses the single panel on toggle', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338341' do - click_button('More actions') + it 'focuses the single panel on toggle' do + click_button('More actions', match: :first) click_button('Expand panel') expect(page).to have_css('.prometheus-graph', count: 1) diff --git a/spec/frontend/projects/storage_counter/app_spec.js b/spec/frontend/projects/storage_counter/app_spec.js index cf71a782f21..9b044350b10 100644 --- a/spec/frontend/projects/storage_counter/app_spec.js +++ b/spec/frontend/projects/storage_counter/app_spec.js @@ -1,13 +1,42 @@ -import { shallowMount } from '@vue/test-utils'; +import { GlAlert } from '@gitlab/ui'; +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import VueApollo from 'vue-apollo'; +import createMockApollo from 'helpers/mock_apollo_helper'; import StorageCounterApp from '~/projects/storage_counter/components/app.vue'; +import getProjectStorageCount from '~/projects/storage_counter/queries/project_storage.query.graphql'; + +const localVue = createLocalVue(); describe('Storage counter app', () => { let wrapper; - const createComponent = (propsData = {}) => { - wrapper = shallowMount(StorageCounterApp, { propsData }); + const createMockApolloProvider = () => { + localVue.use(VueApollo); + + const requestHandlers = [ + [getProjectStorageCount, jest.fn().mockRejectedValue(new Error('GraphQL error'))], + ]; + + return createMockApollo(requestHandlers); }; + const createComponent = ({ provide = {}, mockApollo } = {}) => { + const defaultProvideValues = { + projectPath: 'test-project', + }; + + wrapper = shallowMount(StorageCounterApp, { + localVue, + apolloProvider: mockApollo, + provide: { + ...defaultProvideValues, + ...provide, + }, + }); + }; + + const findAlert = () => wrapper.findComponent(GlAlert); + beforeEach(() => { createComponent(); }); @@ -19,4 +48,17 @@ describe('Storage counter app', () => { it('renders app successfully', () => { expect(wrapper.text()).toBe('Usage'); }); + + describe('handling apollo fetching error', () => { + let mockApollo; + + beforeEach(() => { + mockApollo = createMockApolloProvider(); + createComponent({ mockApollo }); + }); + + it('renders gl-alert if there is an error', () => { + expect(findAlert().exists()).toBe(true); + }); + }); }); diff --git a/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb b/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb index c1a8a612254..c3f7cf5059f 100644 --- a/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb +++ b/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb @@ -6,10 +6,10 @@ RSpec.describe Gitlab::Database::LoadBalancing::ServiceDiscovery do let(:load_balancer) { Gitlab::Database::LoadBalancing::LoadBalancer.new([]) } let(:service) do described_class.new( + load_balancer, nameserver: 'localhost', port: 8600, - record: 'foo', - load_balancer: load_balancer + record: 'foo' ) end @@ -26,11 +26,11 @@ RSpec.describe Gitlab::Database::LoadBalancing::ServiceDiscovery do describe ':record_type' do subject do described_class.new( + load_balancer, nameserver: 'localhost', port: 8600, record: 'foo', - record_type: record_type, - load_balancer: load_balancer + record_type: record_type ) end @@ -217,11 +217,11 @@ RSpec.describe Gitlab::Database::LoadBalancing::ServiceDiscovery do describe '#addresses_from_dns' do let(:service) do described_class.new( + load_balancer, nameserver: 'localhost', port: 8600, record: 'foo', - record_type: record_type, - load_balancer: load_balancer + record_type: record_type ) end diff --git a/spec/lib/gitlab/database/load_balancing_spec.rb b/spec/lib/gitlab/database/load_balancing_spec.rb index 6ec8e0516f6..08dc449ec60 100644 --- a/spec/lib/gitlab/database/load_balancing_spec.rb +++ b/spec/lib/gitlab/database/load_balancing_spec.rb @@ -204,9 +204,11 @@ RSpec.describe Gitlab::Database::LoadBalancing do end describe '.configure_proxy' do - it 'configures the connection proxy' do + before do allow(ActiveRecord::Base).to receive(:load_balancing_proxy=) + end + it 'configures the connection proxy' do described_class.configure_proxy expect(ActiveRecord::Base).to have_received(:load_balancing_proxy=) @@ -214,15 +216,22 @@ RSpec.describe Gitlab::Database::LoadBalancing do end context 'when service discovery is enabled' do - let(:service_discovery) { double(Gitlab::Database::LoadBalancing::ServiceDiscovery) } - it 'runs initial service discovery when configuring the connection proxy' do + discover = instance_spy(Gitlab::Database::LoadBalancing::ServiceDiscovery) + allow(described_class) .to receive(:configuration) .and_return('discover' => { 'record' => 'foo' }) - expect(Gitlab::Database::LoadBalancing::ServiceDiscovery).to receive(:new).and_return(service_discovery) - expect(service_discovery).to receive(:perform_service_discovery) + expect(Gitlab::Database::LoadBalancing::ServiceDiscovery) + .to receive(:new) + .with( + an_instance_of(Gitlab::Database::LoadBalancing::LoadBalancer), + an_instance_of(Hash) + ) + .and_return(discover) + + expect(discover).to receive(:perform_service_discovery) described_class.configure_proxy end @@ -297,10 +306,16 @@ RSpec.describe Gitlab::Database::LoadBalancing do .and_return(true) instance = double(:instance) + lb = instance_spy(Gitlab::Database::LoadBalancing::LoadBalancer) + proxy = double(:proxy, load_balancer: lb) + + allow(Gitlab::Database::LoadBalancing) + .to receive(:proxy) + .and_return(proxy) expect(Gitlab::Database::LoadBalancing::ServiceDiscovery) .to receive(:new) - .with(an_instance_of(Hash)) + .with(lb, an_instance_of(Hash)) .and_return(instance) expect(instance) diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index c439b8e9a53..d47f0857f98 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -2274,19 +2274,27 @@ RSpec.describe Group do end describe '.groups_including_descendants_by' do - it 'returns the expected groups for a group and its descendants' do - parent_group1 = create(:group) - child_group1 = create(:group, parent: parent_group1) - child_group2 = create(:group, parent: parent_group1) + let_it_be(:parent_group1) { create(:group) } + let_it_be(:parent_group2) { create(:group) } + let_it_be(:extra_group) { create(:group) } + let_it_be(:child_group1) { create(:group, parent: parent_group1) } + let_it_be(:child_group2) { create(:group, parent: parent_group1) } + let_it_be(:child_group3) { create(:group, parent: parent_group2) } - parent_group2 = create(:group) - child_group3 = create(:group, parent: parent_group2) + subject { described_class.groups_including_descendants_by([parent_group2.id, parent_group1.id]) } - create(:group) + shared_examples 'returns the expected groups for a group and its descendants' do + specify { is_expected.to contain_exactly(parent_group1, parent_group2, child_group1, child_group2, child_group3) } + end - groups = described_class.groups_including_descendants_by([parent_group2.id, parent_group1.id]) + it_behaves_like 'returns the expected groups for a group and its descendants' - expect(groups).to contain_exactly(parent_group1, parent_group2, child_group1, child_group2, child_group3) + context 'when :linear_group_including_descendants_by feature flag is disabled' do + before do + stub_feature_flags(linear_group_including_descendants_by: false) + end + + it_behaves_like 'returns the expected groups for a group and its descendants' end end diff --git a/spec/workers/expire_job_cache_worker_spec.rb b/spec/workers/expire_job_cache_worker_spec.rb index e5a78f7b0ef..e09d3c73839 100644 --- a/spec/workers/expire_job_cache_worker_spec.rb +++ b/spec/workers/expire_job_cache_worker_spec.rb @@ -33,7 +33,6 @@ RSpec.describe ExpireJobCacheWorker do it_behaves_like 'worker with data consistency', described_class, - feature_flag: :load_balancing_for_expire_job_cache_worker, data_consistency: :delayed end diff --git a/yarn.lock b/yarn.lock index 77057dbbd69..d57d789385f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1467,15 +1467,15 @@ dom-accessibility-api "^0.5.1" pretty-format "^26.4.2" -"@tiptap/core@^2.0.0-beta.86": - version "2.0.0-beta.86" - resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.86.tgz#11b575aee4ad2f30f73114c786da5cd13dde30e0" - integrity sha512-EeR6euRTJV9LhUog1PuiN1oLYRsz0SCEU5cQnGElzRzbd8dMnmFVc9cs81fbfjR8R1bfiarOJExrU2+OPHKXDw== +"@tiptap/core@^2.0.0-beta.101": + version "2.0.0-beta.101" + resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.101.tgz#e882836fcbe2b65d851039ddaa0401275a4afe9c" + integrity sha512-IhU+uZ+2F2jTKm2qoIxhzkef6OLYvuTuARhCRoZO7xhOMh314hps/QBC25X6OUqU57S/rn8jLMcyTo0V8Qv7og== dependencies: "@types/prosemirror-commands" "^1.0.4" "@types/prosemirror-inputrules" "^1.0.4" "@types/prosemirror-keymap" "^1.0.4" - "@types/prosemirror-model" "^1.13.1" + "@types/prosemirror-model" "^1.13.2" "@types/prosemirror-schema-list" "^1.0.3" "@types/prosemirror-state" "^1.2.7" "@types/prosemirror-transform" "^1.1.4" @@ -1483,11 +1483,11 @@ prosemirror-commands "^1.1.10" prosemirror-inputrules "^1.1.3" prosemirror-keymap "^1.1.3" - prosemirror-model "^1.14.2" + prosemirror-model "^1.14.3" prosemirror-schema-list "^1.1.5" prosemirror-state "^1.3.4" prosemirror-transform "^1.3.2" - prosemirror-view "^1.18.8" + prosemirror-view "^1.19.3" "@tiptap/extension-blockquote@^2.0.0-beta.15": version "2.0.0-beta.15" @@ -1501,13 +1501,13 @@ resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.15.tgz#cf9ddb3fc316be9707753ad4e497bfb8a3ebb0c2" integrity sha512-jKyV6iiwhxwa0+7uuKD74jNDVNLNOS1GmU14MgaA95pY5e1fyaRBPPX8Gtt89niz2CLOY711AV17RPZTe/e60w== -"@tiptap/extension-bubble-menu@^2.0.0-beta.24": - version "2.0.0-beta.24" - resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.24.tgz#e6db5bc0386ccdbd483e57296b22eb6dd55914ba" - integrity sha512-u1btwasgaidUr9JLQwFQwf9oeXUYPv9TyBzUn/soj9F8qKrWxQxTi/EQUsudvjumzsQOX+tZQIj/YtO5EzR+hA== +"@tiptap/extension-bubble-menu@^2.0.0-beta.31": + version "2.0.0-beta.31" + resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.31.tgz#0bf1bf3bc9d1e89830abe0af2f6796bcda87d66a" + integrity sha512-O0U12A+4tWZo97MRWOhGrZ+Z0DWYHPzLP3rbUMl1bClvOoggKgMZnSdvgjC7LmP5h/8Y+qB92swk5LVYvrOcDQ== dependencies: prosemirror-state "^1.3.4" - prosemirror-view "^1.18.8" + prosemirror-view "^1.19.3" tippy.js "^6.3.1" "@tiptap/extension-bullet-list@^2.0.0-beta.15": @@ -1517,19 +1517,19 @@ dependencies: prosemirror-inputrules "^1.1.3" -"@tiptap/extension-code-block-lowlight@2.0.0-beta.32": - version "2.0.0-beta.32" - resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.32.tgz#ef9ff6883f2d669e6be79c69f26749641462e1ea" - integrity sha512-RnKAlE981k7VYIUUZ2jYZVGzZJalzrRw6dCf0rfgPvSY3T+ih9gVjKr+APGTuX3tsSR+s3UHs6YUI9+83pje3A== +"@tiptap/extension-code-block-lowlight@2.0.0-beta.35": + version "2.0.0-beta.35" + resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.35.tgz#a08e98d7c2fcc4a80f927766842bfc9980e5b55e" + integrity sha512-lPjrZg9bJp83O7EJaDU2Ial15JU0SNX9zbXpdpatbzxFOKsXpgMuRPrYxMYelbIq2XuhEOdu/Q9cc6+vtqmfFQ== dependencies: - "@tiptap/extension-code-block" "^2.0.0-beta.16" + "@tiptap/extension-code-block" "^2.0.0-beta.17" "@types/lowlight" "^0.0.3" lowlight "^1.20.0" - prosemirror-model "^1.14.2" + prosemirror-model "^1.14.3" prosemirror-state "^1.3.4" - prosemirror-view "^1.18.8" + prosemirror-view "^1.19.3" -"@tiptap/extension-code-block@^2.0.0-beta.16": +"@tiptap/extension-code-block@^2.0.0-beta.17": version "2.0.0-beta.17" resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.17.tgz#b12ab35561da08b359f4d8dced2b8c30eb62fcdb" integrity sha512-u3RY991mXtjuw+trVaDwbAhuPPlU8l6kS4rXIxWJ5W/sNElbmfHLVu7RP++YwM8KOQrCrQl8TJbZTEIekMw61w== @@ -1546,21 +1546,21 @@ resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.0.0-beta.13.tgz#8cfb29d4de64bf4a790817f730c05b4f9b7167b2" integrity sha512-nrufdKziA/wovaY4DjGkc8OGuIZi8CH8CW3+yYfeWbruwFKkyZHlZy9nplFWSEqBHPAeqD+px9r91yGMW3ontA== -"@tiptap/extension-dropcursor@^2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.18.tgz#25f0676b0cae6900ac18e11a2e1ea2627904dfa3" - integrity sha512-P9cMKO7YXsqp62WA2sliWA6TZThO0yoQprv8Em5BPnW53ttZn9RR9sZaeLL/y02cl/aLVtqdLtl2CPSER43ieA== +"@tiptap/extension-dropcursor@^2.0.0-beta.19": + version "2.0.0-beta.19" + resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.19.tgz#8a37ffe27e484eb44dd18297830d1fd8ce0c50ce" + integrity sha512-rslIcVvD42NNh5sEbkCkG03DWMFBrS5KoK+lDOdIcC1DjmTtpVgcLvvE01btzaB3ljx+UVqI2Zaxa6VOiTeEMw== dependencies: - "@types/prosemirror-dropcursor" "^1.0.2" + "@types/prosemirror-dropcursor" "^1.0.3" prosemirror-dropcursor "^1.3.5" -"@tiptap/extension-floating-menu@^2.0.0-beta.18": - version "2.0.0-beta.18" - resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.18.tgz#4d9b7f58c73f6c718a74503c5ff514b06f615e27" - integrity sha512-1fCRGdTxCiRm5DV91GwKYn9yu43oonq6iuRAlgcTZ2ON03MAAG55j+cDA2S3JSwbsA7Vr49ijmXBY/fEdU/fiQ== +"@tiptap/extension-floating-menu@^2.0.0-beta.25": + version "2.0.0-beta.25" + resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.25.tgz#9b8dcbdd6f844d077483d6c631800c29f57273e6" + integrity sha512-nXBi1eA3Kji8tk+gOIyxXKsaTpGBgXSX9hHTgIvbBMMvfP9onLKuZIAKG/cBUMBzt+CKns1XooE71UqyMESDhQ== dependencies: prosemirror-state "^1.3.4" - prosemirror-view "^1.18.8" + prosemirror-view "^1.19.3" tippy.js "^6.3.1" "@tiptap/extension-gapcursor@^2.0.0-beta.19": @@ -1571,7 +1571,7 @@ "@types/prosemirror-gapcursor" "^1.0.4" prosemirror-gapcursor "^1.1.5" -"@tiptap/extension-hard-break@^2.0.0-beta.14": +"@tiptap/extension-hard-break@^2.0.0-beta.15": version "2.0.0-beta.15" resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.15.tgz#ce00dd40f5abeaff8574f2288ade6815ab696c94" integrity sha512-MS7MjGOtKtC1bVNAShwCetFRuk8nPr/j18OOzKChNrJFrZXWNJrid3dUojwDLqCraYdzSTmiOmMgU+yoUe/gnw== @@ -1687,14 +1687,14 @@ resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.13.tgz#da0af8d9a3f149d20076e15d88c6af21fb6d940f" integrity sha512-0EtAwuRldCAoFaL/iXgkRepEeOd55rPg5N4FQUN1xTwZT7PDofukP0DG/2jff/Uj17x4uTaJAa9qlFWuNnDvjw== -"@tiptap/vue-2@^2.0.0-beta.39": - version "2.0.0-beta.39" - resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.39.tgz#f6d75af99b072848381f0c443b50ec09186eb43b" - integrity sha512-O8hCzrAZTbjebcD3XWsbUieudnD7rvDFGmHSRmb0igg//ARO43IWe2xdu2Hlx1MT9b+83YjgDhRyMjHcsKRtzw== +"@tiptap/vue-2@^2.0.0-beta.48": + version "2.0.0-beta.48" + resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.48.tgz#ee0bfec8819ab588c558dfa39f56269099a226bf" + integrity sha512-Cx8n8a2UwuJKyAheZKmAQe4s3gCmmPsgzZeh3FYtomp0xmf12H+dZbejqbv/w8pnCc/ATMdl3szf7NKA4hNz1Q== dependencies: - "@tiptap/extension-bubble-menu" "^2.0.0-beta.24" - "@tiptap/extension-floating-menu" "^2.0.0-beta.18" - prosemirror-view "^1.18.8" + "@tiptap/extension-bubble-menu" "^2.0.0-beta.31" + "@tiptap/extension-floating-menu" "^2.0.0-beta.25" + prosemirror-view "^1.19.3" "@toast-ui/editor@^2.5.2": version "2.5.2" @@ -1877,7 +1877,7 @@ "@types/prosemirror-state" "*" "@types/prosemirror-view" "*" -"@types/prosemirror-dropcursor@^1.0.2": +"@types/prosemirror-dropcursor@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@types/prosemirror-dropcursor/-/prosemirror-dropcursor-1.0.3.tgz#49250849b8a0b86e8c29eb1ba70a463e53e46947" integrity sha512-b0/8njnJ4lwyHKcGuCMf3x7r1KjxyugB1R/c2iMCjplsJHSC7UY9+OysqgJR5uUXRekUSGniiLgBtac/lvH6wg== @@ -1918,7 +1918,7 @@ "@types/prosemirror-state" "*" "@types/prosemirror-view" "*" -"@types/prosemirror-model@*", "@types/prosemirror-model@^1.13.1": +"@types/prosemirror-model@*", "@types/prosemirror-model@^1.13.2": version "1.13.2" resolved "https://registry.yarnpkg.com/@types/prosemirror-model/-/prosemirror-model-1.13.2.tgz#2adad3ec478f83204f155d7fb94c9dfde2fc3296" integrity sha512-a2rDB0aZ+7aIP7uBqQq1wLb4Hg4qqEvpkCqvhsgT/gG8IWC0peCAZfQ24sgTco0qSJLeDgIbtPeU6mgr869/kg== @@ -10078,7 +10078,7 @@ prosemirror-markdown@^1.5.1: markdown-it "^10.0.0" prosemirror-model "^1.0.0" -prosemirror-model@^1.0.0, prosemirror-model@^1.13.1, prosemirror-model@^1.13.3, prosemirror-model@^1.14.2, prosemirror-model@^1.14.3, prosemirror-model@^1.2.0, prosemirror-model@^1.8.1: +prosemirror-model@^1.0.0, prosemirror-model@^1.13.1, prosemirror-model@^1.14.3, prosemirror-model@^1.2.0, prosemirror-model@^1.8.1: version "1.14.3" resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.14.3.tgz#a9c250d3c4023ddf10ecb41a0a7a130e9741d37e" integrity sha512-yzZlBaSxfUPIIP6U5Edh5zKxJPZ5f7bwZRhiCuH3UYkWhj+P3d8swHsbuAMOu/iDatDc5J/Qs5Mb3++mZf+CvQ== @@ -10131,7 +10131,7 @@ prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transfor dependencies: prosemirror-model "^1.0.0" -prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.18.8, prosemirror-view@^1.19.3: +prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.19.3: version "1.19.3" resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.19.3.tgz#8d9bc91705bcf9cb5ae3b4de2668f73c7b93fa14" integrity sha512-YP/ZzVwqPPwbHbJi97U2/CeyZ8PIHmLJt0gIhZWP8XfnuBRGG3y+jwLzUoBVmiuoUCy3R6PSB+pOATliGzLfPg== @@ -11913,7 +11913,7 @@ tiptap-commands@^1.17.1: prosemirror-tables "^1.1.1" tiptap-utils "^1.13.1" -tiptap-extensions@^1.35.1: +tiptap-extensions@^1.35.2: version "1.35.2" resolved "https://registry.yarnpkg.com/tiptap-extensions/-/tiptap-extensions-1.35.2.tgz#83dd6ee703ae8c83b58c7608f97253fcc4f1a94c" integrity sha512-TIMbHVJe0/3aVeTeCmqGbatDkfxduPYFOffNCmuKR+h6oQNzTu6rLVhRzoNqktfxIoi/b44SiDPorTjSN72dCw== @@ -11939,7 +11939,7 @@ tiptap-utils@^1.13.1: prosemirror-state "^1.3.3" prosemirror-tables "^1.1.1" -tiptap@^1.32.1, tiptap@^1.32.2: +tiptap@^1.32.2: version "1.32.2" resolved "https://registry.yarnpkg.com/tiptap/-/tiptap-1.32.2.tgz#cd6259e853652bfc6860758ff44ebb695d5edd1c" integrity sha512-5IwVj8nGo8y5V3jbdtoEd7xNUsi8Q0N6WV2Nfs70olqz3fldXkiImBrDhZJ4Anx8vhyP6PIBttrg0prFVmwIvw==