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--.rubocop_todo/style/inline_disable_annotation.yml1
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.checksum7
-rw-r--r--Gemfile.lock16
-rw-r--r--app/models/analytics/cycle_analytics/aggregation.rb19
-rw-r--r--app/models/concerns/analytics/cycle_analytics/parentable.rb11
-rw-r--r--app/models/resource_label_event.rb6
-rw-r--r--db/post_migrate/20231225070431_async_validate_finding_id_on_vulnerabilities.rb17
-rw-r--r--db/schema_migrations/202312250704311
-rw-r--r--doc/development/feature_development.md1
-rw-r--r--doc/development/remote_development/index.md16
-rw-r--r--doc/user/workspace/index.md1
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/models/analytics/cycle_analytics/aggregation_spec.rb57
-rw-r--r--spec/models/resource_label_event_spec.rb62
-rw-r--r--spec/support/helpers/cycle_analytics_helpers.rb4
-rw-r--r--spec/support/shared_examples/analytics/cycle_analytics/parentable_examples.rb13
17 files changed, 171 insertions, 66 deletions
diff --git a/.rubocop_todo/style/inline_disable_annotation.yml b/.rubocop_todo/style/inline_disable_annotation.yml
index 1a6226514e6..db42f855d1a 100644
--- a/.rubocop_todo/style/inline_disable_annotation.yml
+++ b/.rubocop_todo/style/inline_disable_annotation.yml
@@ -390,7 +390,6 @@ Style/InlineDisableAnnotation:
- 'app/models/commit.rb'
- 'app/models/commit_collection.rb'
- 'app/models/commit_status.rb'
- - 'app/models/concerns/analytics/cycle_analytics/parentable.rb'
- 'app/models/concerns/approvable.rb'
- 'app/models/concerns/async_devise_email.rb'
- 'app/models/concerns/atomic_internal_id.rb'
diff --git a/Gemfile b/Gemfile
index 551a845f90f..2dbd5e20ef6 100644
--- a/Gemfile
+++ b/Gemfile
@@ -288,7 +288,7 @@ gem 'redis-namespace', '~> 1.10.0' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'connection_pool', '~> 2.4' # rubocop:todo Gemfile/MissingFeatureCategory
# Redis session store
-gem 'redis-actionpack', '~> 5.3.0' # rubocop:todo Gemfile/MissingFeatureCategory
+gem 'redis-actionpack', '~> 5.4.0' # rubocop:todo Gemfile/MissingFeatureCategory
# Discord integration
gem 'discordrb-webhooks', '~> 3.4', require: false, feature_category: :integrations
diff --git a/Gemfile.checksum b/Gemfile.checksum
index e545531d857..73998da5c88 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -482,6 +482,7 @@
{"name":"rack-oauth2","version":"1.21.3","platform":"ruby","checksum":"4e72a79dd6a866692e84422a552b27c38a5a1918ded06661e04910f2bbe676ba"},
{"name":"rack-protection","version":"2.2.2","platform":"ruby","checksum":"fd41414dbabbec274af0bdb1f72a48504449de4d979782c9af38cbb5dfff3299"},
{"name":"rack-proxy","version":"0.7.7","platform":"ruby","checksum":"446a4b57001022145d5c3ba73b775f66a2260eaf7420c6907483141900395c8a"},
+{"name":"rack-session","version":"1.0.2","platform":"ruby","checksum":"a02115e5420b4de036839b9811e3f7967d73446a554b42aa45106af335851d76"},
{"name":"rack-test","version":"2.1.0","platform":"ruby","checksum":"0c61fc61904049d691922ea4bb99e28004ed3f43aa5cfd495024cc345f125dfb"},
{"name":"rack-timeout","version":"0.6.3","platform":"ruby","checksum":"1754892eacc124d405e7f1145731ec9b7421ebd1bee5d51ddc18b72c204d0ab3"},
{"name":"rails","version":"7.0.8","platform":"ruby","checksum":"8e43af921acf766fb429126f020ec90c3b25809631f8fbdff95c3553828d5867"},
@@ -512,10 +513,10 @@
{"name":"recursive-open-struct","version":"1.1.3","platform":"ruby","checksum":"a3538a72552fcebcd0ada657bdff313641a4a5fbc482c08cfb9a65acb1c9de5a"},
{"name":"redcarpet","version":"3.6.0","platform":"ruby","checksum":"8ad1889c0355ff4c47174af14edd06d62f45a326da1da6e8a121d59bdcd2e9e9"},
{"name":"redis","version":"4.8.0","platform":"ruby","checksum":"2000cf5014669c9dc821704b6d322a35a9a33852a95208911d9175d63b448a44"},
-{"name":"redis-actionpack","version":"5.3.0","platform":"ruby","checksum":"3fb1ad0a8fd9d26a289c9399bb609dcaef38bf37711e6f677a53ca728fc19140"},
+{"name":"redis-actionpack","version":"5.4.0","platform":"ruby","checksum":"f10cf649ab05914716d63334d7f709221ecc883b87cf348f90ecfe0c35ea3540"},
{"name":"redis-namespace","version":"1.10.0","platform":"ruby","checksum":"2c1c6ea7c6c5e343e75b9bee3aa4c265e364a5b9966507397467af2bb3758d94"},
-{"name":"redis-rack","version":"2.1.4","platform":"ruby","checksum":"0872eecb303e483c3863d6bd0d47323d230640d41c1a4ac4a2c7596ec0b1774c"},
-{"name":"redis-store","version":"1.9.1","platform":"ruby","checksum":"7b4c7438d46f7b7ce8f67fc0eda3a04fc67d32d28cf606cc98a5df4d2b77071d"},
+{"name":"redis-rack","version":"3.0.0","platform":"ruby","checksum":"abb50b82ae10ad4d11ca2e4901bfc2b98256cdafbbd95f80c86fc9e001478380"},
+{"name":"redis-store","version":"1.10.0","platform":"ruby","checksum":"f258894f9f7e82834308a3d86242294f0cff2c9db9ae66e5cb4c553a5ec8b09e"},
{"name":"regexp_parser","version":"2.6.0","platform":"ruby","checksum":"f163ba463a45ca2f2730e0902f2475bb0eefcd536dfc2f900a86d1e5a7d7a556"},
{"name":"regexp_property_values","version":"1.0.0","platform":"java","checksum":"5e26782b01241616855c4ee7bb8a62fce9387e484f2d3eaf04f2a0633708222e"},
{"name":"regexp_property_values","version":"1.0.0","platform":"ruby","checksum":"162499dc0bba1e66d334273a059f207a61981cc8cc69d2ca743594e7886d080f"},
diff --git a/Gemfile.lock b/Gemfile.lock
index 77c866875b2..c543ecffc6c 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1297,6 +1297,8 @@ GEM
rack
rack-proxy (0.7.7)
rack
+ rack-session (1.0.2)
+ rack (< 3)
rack-test (2.1.0)
rack (>= 1.3)
rack-timeout (0.6.3)
@@ -1352,17 +1354,17 @@ GEM
recursive-open-struct (1.1.3)
redcarpet (3.6.0)
redis (4.8.0)
- redis-actionpack (5.3.0)
+ redis-actionpack (5.4.0)
actionpack (>= 5, < 8)
- redis-rack (>= 2.1.0, < 3)
+ redis-rack (>= 2.1.0, < 4)
redis-store (>= 1.1.0, < 2)
redis-namespace (1.10.0)
redis (>= 4)
- redis-rack (2.1.4)
- rack (>= 2.0.8, < 3)
+ redis-rack (3.0.0)
+ rack-session (>= 0.2.0)
redis-store (>= 1.2, < 2)
- redis-store (1.9.1)
- redis (>= 4, < 5)
+ redis-store (1.10.0)
+ redis (>= 4, < 6)
regexp_parser (2.6.0)
regexp_property_values (1.0.0)
representable (3.2.0)
@@ -2035,7 +2037,7 @@ DEPENDENCIES
re2 (= 2.5.0)
recaptcha (~> 5.12)
redis (~> 4.8.0)
- redis-actionpack (~> 5.3.0)
+ redis-actionpack (~> 5.4.0)
redis-namespace (~> 1.10.0)
request_store (~> 1.5.1)
responders (~> 3.0)
diff --git a/app/models/analytics/cycle_analytics/aggregation.rb b/app/models/analytics/cycle_analytics/aggregation.rb
index 0f8e184933e..5ac5437a442 100644
--- a/app/models/analytics/cycle_analytics/aggregation.rb
+++ b/app/models/analytics/cycle_analytics/aggregation.rb
@@ -59,19 +59,26 @@ class Analytics::CycleAnalytics::Aggregation < ApplicationRecord
estimation < 1 ? nil : estimation.from_now
end
- def self.safe_create_for_namespace(group_or_project_namespace)
+ def self.safe_create_for_namespace(target_namespace)
# Namespaces::ProjectNamespace has no root_ancestor
# Related: https://gitlab.com/gitlab-org/gitlab/-/issues/386124
- group = group_or_project_namespace.is_a?(Group) ? group_or_project_namespace : group_or_project_namespace.parent
- top_level_group = group.root_ancestor
- aggregation = find_by(group_id: top_level_group.id)
+ namespace = if target_namespace.is_a?(Group) || target_namespace.is_a?(Namespaces::UserNamespace)
+ target_namespace
+ else
+ target_namespace.parent
+ end
+ # personal namespace projects and associated ProjectNamespace respond to `namespace`
+ # and this is close enough to "root ancestor"
+ top_level_namespace =
+ target_namespace.respond_to?(:root_ancestor) ? namespace.root_ancestor : namespace.namespace
+ aggregation = find_by(group_id: top_level_namespace.id)
return aggregation if aggregation&.enabled?
# At this point we're sure that the group is licensed, we can always enable the aggregation.
# This re-enables the aggregation in case the group downgraded and later upgraded the license.
- upsert({ group_id: top_level_group.id, enabled: true })
+ upsert({ group_id: top_level_namespace.id, enabled: true })
- find(top_level_group.id)
+ find(top_level_namespace.id)
end
private
diff --git a/app/models/concerns/analytics/cycle_analytics/parentable.rb b/app/models/concerns/analytics/cycle_analytics/parentable.rb
index 785f6eea6bf..90a38e3c58c 100644
--- a/app/models/concerns/analytics/cycle_analytics/parentable.rb
+++ b/app/models/concerns/analytics/cycle_analytics/parentable.rb
@@ -6,16 +6,7 @@ module Analytics
extend ActiveSupport::Concern
included do
- belongs_to :namespace, class_name: 'Namespace', foreign_key: :group_id, optional: false # rubocop: disable Rails/InverseOf
-
- validate :ensure_namespace_type
-
- def ensure_namespace_type
- return if namespace.nil?
- return if namespace.is_a?(::Namespaces::ProjectNamespace) || namespace.is_a?(::Group)
-
- errors.add(:namespace, s_('CycleAnalytics|the assigned object is not supported'))
- end
+ belongs_to :namespace, class_name: 'Namespace', foreign_key: :group_id, optional: false # rubocop: disable Rails/InverseOf -- this relation is not present on Namespace
end
end
end
diff --git a/app/models/resource_label_event.rb b/app/models/resource_label_event.rb
index ad1ce740c89..e912e57f39e 100644
--- a/app/models/resource_label_event.rb
+++ b/app/models/resource_label_event.rb
@@ -45,7 +45,7 @@ class ResourceLabelEvent < ResourceEvent
end
def group
- issuable.group if issuable.respond_to?(:group)
+ issuable.resource_parent if issuable.resource_parent.is_a?(Group)
end
def outdated_markdown?
@@ -93,7 +93,9 @@ class ResourceLabelEvent < ResourceEvent
end
def label_url_method
- issuable.is_a?(MergeRequest) ? :project_merge_requests_url : :project_issues_url
+ return :project_merge_requests_url if issuable.is_a?(MergeRequest)
+
+ issuable.project_id.nil? ? :group_work_items_url : :project_issues_url
end
def broadcast_notes_changed
diff --git a/db/post_migrate/20231225070431_async_validate_finding_id_on_vulnerabilities.rb b/db/post_migrate/20231225070431_async_validate_finding_id_on_vulnerabilities.rb
new file mode 100644
index 00000000000..dfab0d6eab0
--- /dev/null
+++ b/db/post_migrate/20231225070431_async_validate_finding_id_on_vulnerabilities.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AsyncValidateFindingIdOnVulnerabilities < Gitlab::Database::Migration[2.2]
+ # obtained by running `\d vulnerabilities` on https://console.postgres.ai
+ FK_NAME = :fk_4e64972902
+
+ milestone '16.8'
+
+ # TODO: FK to be validated synchronously in https://gitlab.com/gitlab-org/gitlab/-/issues/425409
+ def up
+ prepare_async_foreign_key_validation :vulnerabilities, :finding_id, name: FK_NAME
+ end
+
+ def down
+ unprepare_async_foreign_key_validation :vulnerabilities, :finding_id, name: FK_NAME
+ end
+end
diff --git a/db/schema_migrations/20231225070431 b/db/schema_migrations/20231225070431
new file mode 100644
index 00000000000..7cbc466473b
--- /dev/null
+++ b/db/schema_migrations/20231225070431
@@ -0,0 +1 @@
+1298d9dd3c6b909a3129b5375477b466b7970347cf65d0654bf3076f87658fd0 \ No newline at end of file
diff --git a/doc/development/feature_development.md b/doc/development/feature_development.md
index a5a6439b420..59785554ce6 100644
--- a/doc/development/feature_development.md
+++ b/doc/development/feature_development.md
@@ -97,6 +97,7 @@ Consult these topics for information on contributing to specific GitLab features
- [Application limits](application_limits.md)
- [AI features](ai_features/index.md)
- [Application settings](application_settings.md)
+- [Remote Development](remote_development/index.md)
### Import and Export
diff --git a/doc/development/remote_development/index.md b/doc/development/remote_development/index.md
new file mode 100644
index 00000000000..a4026e21315
--- /dev/null
+++ b/doc/development/remote_development/index.md
@@ -0,0 +1,16 @@
+---
+stage: Create
+group: Web IDE
+info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
+---
+
+# Remote Development
+
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105783) in GitLab 16.0.
+
+## Workspaces Feature Developer Documentation
+
+Currently, the majority of the developer documentation for the [Remote Development Workspaces feature](../../user/workspace/index.md)
+is located in the separate [`gitlab-remote-development-docs` project](https://gitlab.com/gitlab-org/remote-development/gitlab-remote-development-docs/-/blob/main/README.md).
+
+Parts of that documentation will eventually be migrated here.
diff --git a/doc/user/workspace/index.md b/doc/user/workspace/index.md
index d24102afcf9..309c5d19a51 100644
--- a/doc/user/workspace/index.md
+++ b/doc/user/workspace/index.md
@@ -181,3 +181,4 @@ For more information, see the
## Related topics
- [GitLab workspaces demo](https://go.gitlab.com/qtu66q)
+- [Developer documentation](../../development/remote_development/index.md)]
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 3c34d2ff287..f3ae0a1e487 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -15294,9 +15294,6 @@ msgstr ""
msgid "CycleAnalytics|project dropdown filter"
msgstr ""
-msgid "CycleAnalytics|the assigned object is not supported"
-msgstr ""
-
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
diff --git a/spec/models/analytics/cycle_analytics/aggregation_spec.rb b/spec/models/analytics/cycle_analytics/aggregation_spec.rb
index e69093f454a..5494df84d68 100644
--- a/spec/models/analytics/cycle_analytics/aggregation_spec.rb
+++ b/spec/models/analytics/cycle_analytics/aggregation_spec.rb
@@ -131,39 +131,52 @@ RSpec.describe Analytics::CycleAnalytics::Aggregation, type: :model, feature_cat
end
describe '#safe_create_for_namespace' do
- let_it_be(:group) { create(:group) }
- let_it_be(:subgroup) { create(:group, parent: group) }
+ context 'when group namespace is provided' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: group) }
- it 'creates the aggregation record' do
- record = described_class.safe_create_for_namespace(group)
-
- expect(record).to be_persisted
- end
-
- context 'when non top-level group is given' do
- it 'creates the aggregation record for the top-level group' do
- record = described_class.safe_create_for_namespace(subgroup)
+ it 'creates the aggregation record' do
+ record = described_class.safe_create_for_namespace(group)
expect(record).to be_persisted
end
- end
- context 'when the record is already present' do
- it 'does nothing' do
- described_class.safe_create_for_namespace(group)
+ context 'when non top-level group is given' do
+ it 'creates the aggregation record for the top-level group' do
+ record = described_class.safe_create_for_namespace(subgroup)
+
+ expect(record).to be_persisted
+ end
+ end
- expect do
+ context 'when the record is already present' do
+ it 'does nothing' do
described_class.safe_create_for_namespace(group)
- described_class.safe_create_for_namespace(subgroup)
- end.not_to change { described_class.count }
+
+ expect do
+ described_class.safe_create_for_namespace(group)
+ described_class.safe_create_for_namespace(subgroup)
+ end.not_to change { described_class.count }
+ end
+ end
+
+ context 'when the aggregation was disabled for some reason' do
+ it 're-enables the aggregation' do
+ create(:cycle_analytics_aggregation, enabled: false, namespace: group)
+
+ aggregation = described_class.safe_create_for_namespace(group)
+
+ expect(aggregation).to be_enabled
+ end
end
end
- context 'when the aggregation was disabled for some reason' do
- it 're-enables the aggregation' do
- create(:cycle_analytics_aggregation, enabled: false, namespace: group)
+ context 'when personal namespace is provided' do
+ let_it_be(:user2) { create(:user) }
+ let_it_be(:project) { create(:project, :public, namespace: user2.namespace) }
- aggregation = described_class.safe_create_for_namespace(group)
+ it 'is successful' do
+ aggregation = described_class.safe_create_for_namespace(user2.namespace)
expect(aggregation).to be_enabled
end
diff --git a/spec/models/resource_label_event_spec.rb b/spec/models/resource_label_event_spec.rb
index 8cc89578e0e..27a39672994 100644
--- a/spec/models/resource_label_event_spec.rb
+++ b/spec/models/resource_label_event_spec.rb
@@ -3,12 +3,13 @@
require 'spec_helper'
RSpec.describe ResourceLabelEvent, feature_category: :team_planning, type: :model do
- let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :repository, group: group) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:merge_request) { create(:merge_request, source_project: project) }
let_it_be(:label) { create(:label, project: project) }
- subject { build(:resource_label_event, issue: issue, label: label) }
+ subject(:resource_label_event) { build(:resource_label_event, issue: issue, label: label) }
it_behaves_like 'having unique enum values'
@@ -95,6 +96,63 @@ RSpec.describe ResourceLabelEvent, feature_category: :team_planning, type: :mode
end
end
+ describe '#reference_html' do
+ subject { Nokogiri::HTML.fragment(label_event.reference_html).css('a').first.attr('href') }
+
+ before do
+ label_event.refresh_invalid_reference
+ end
+
+ context 'when resource event belongs to a group level issue' do
+ let(:group_label) { create(:group_label, group: group) }
+ let(:label_event) do
+ group_issue = create(:issue, :group_level, namespace: group)
+
+ create(:resource_label_event, issue: group_issue, label: group_label)
+ end
+
+ it { is_expected.to eq(Gitlab::Routing.url_helpers.group_work_items_path(group, label_name: group_label.title)) }
+ end
+
+ context 'when resource event belongs to a project level issue' do
+ let(:label_event) { resource_label_event }
+
+ it { is_expected.to eq(Gitlab::Routing.url_helpers.project_issues_path(project, label_name: label.title)) }
+ end
+
+ context 'when resource event belongs to a merge request' do
+ let(:label_event) { create(:resource_label_event, merge_request: merge_request, label: label) }
+
+ it do
+ is_expected.to eq(Gitlab::Routing.url_helpers.project_merge_requests_path(project, label_name: label.title))
+ end
+ end
+ end
+
+ describe '#group' do
+ subject { build_stubbed(:resource_label_event, **issuable_attributes).group }
+
+ context 'when issuable is a merge request' do
+ let(:issuable_attributes) { { merge_request: merge_request } }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when issuable is an issue' do
+ context 'when issue exists at the project level' do
+ let(:issuable_attributes) { { issue: issue } }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when issue exists at the group level' do
+ let(:issuable_attributes) { { issue: build_stubbed(:issue, :group_level, namespace: group) } }
+
+ it { is_expected.to eq(group) }
+ end
+ end
+ end
+
describe '.visible_to_user?' do
let_it_be(:user) { create(:user) }
let_it_be(:issue_project) { create(:project) }
diff --git a/spec/support/helpers/cycle_analytics_helpers.rb b/spec/support/helpers/cycle_analytics_helpers.rb
index e4683cbf3c0..3f04d984e55 100644
--- a/spec/support/helpers/cycle_analytics_helpers.rb
+++ b/spec/support/helpers/cycle_analytics_helpers.rb
@@ -94,8 +94,8 @@ module CycleAnalyticsHelpers
wait_for_requests
end
- def create_value_stream_aggregation(group_or_project_namespace)
- aggregation = Analytics::CycleAnalytics::Aggregation.safe_create_for_namespace(group_or_project_namespace)
+ def create_value_stream_aggregation(namespace)
+ aggregation = Analytics::CycleAnalytics::Aggregation.safe_create_for_namespace(namespace)
Analytics::CycleAnalytics::AggregatorService.new(aggregation: aggregation).execute
end
diff --git a/spec/support/shared_examples/analytics/cycle_analytics/parentable_examples.rb b/spec/support/shared_examples/analytics/cycle_analytics/parentable_examples.rb
index 5fd0e685c67..a6f028a5a04 100644
--- a/spec/support/shared_examples/analytics/cycle_analytics/parentable_examples.rb
+++ b/spec/support/shared_examples/analytics/cycle_analytics/parentable_examples.rb
@@ -14,15 +14,14 @@ RSpec.shared_examples 'value stream analytics namespace models' do
end
end
- context 'when Namespace is given' do
- it 'fails' do
- namespace = create(:namespace)
+ context 'when personal namespace is given' do
+ it 'is valid' do
+ namespace = create(:namespace, owner: create(:user))
model = build(factory_name, namespace: namespace)
- expect(model).to be_invalid
-
- error_message = s_('CycleAnalytics|the assigned object is not supported')
- expect(model.errors.messages_for(:namespace)).to eq([error_message])
+ expect(model).to be_valid
+ expect(model.save).to be(true)
+ expect(model.namespace).to eq(namespace)
end
end
end