Skip to content

Commit aa068e9

Browse files
author
GitLab Bot
committed
Add latest changes from gitlab-org/gitlab@master
1 parent fe1e276 commit aa068e9

File tree

84 files changed

+911
-141
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+911
-141
lines changed

.rubocop_todo/layout/line_continuation_spacing.yml

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# Cop supports --autocorrect.
33
Layout/LineContinuationSpacing:
44
Exclude:
5-
- 'app/helpers/application_settings_helper.rb'
65
- 'app/helpers/projects_helper.rb'
76
- 'app/helpers/tags_helper.rb'
87
- 'app/helpers/tree_helper.rb'

.rubocop_todo/rspec/multiple_memoized_helpers.yml

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ RSpec/MultipleMemoizedHelpers:
2525
- 'spec/requests/api/issues/issues_spec.rb'
2626
- 'spec/requests/api/issues/put_projects_issues_spec.rb'
2727
- 'spec/requests/api/maven_packages_spec.rb'
28+
- 'spec/requests/api/todos_spec.rb'
2829
- 'spec/requests/api/users_spec.rb'
2930
- 'spec/services/boards/issues/list_service_spec.rb'
3031
- 'spec/services/labels/promote_service_spec.rb'

app/graphql/mutations/work_items/bulk_update.rb

-4
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@ class BulkUpdate < BaseMutation
3333
description: 'Number of work items that were successfully updated.'
3434

3535
def ready?(**args)
36-
if Feature.disabled?(:bulk_update_work_items_mutation, parent_for!(args[:parent_id]))
37-
raise_resource_not_available_error!('`bulk_update_work_items_mutation` feature flag is disabled.')
38-
end
39-
4036
if args[:ids].size > MAX_WORK_ITEMS
4137
raise Gitlab::Graphql::Errors::ArgumentError,
4238
format(

app/helpers/application_settings_helper.rb

+10-10
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ def repository_storages_options_json
193193
end
194194

195195
def external_authorization_description
196-
s_("ExternalAuthorization|Access to projects is validated on an external service "\
196+
s_("ExternalAuthorization|Access to projects is validated on an external service " \
197197
"using their classification label.")
198198
end
199199

@@ -202,39 +202,39 @@ def external_authorization_allow_token_help_text
202202
end
203203

204204
def external_authorization_timeout_help_text
205-
s_("ExternalAuthorization|Period GitLab waits for a response from the external "\
205+
s_("ExternalAuthorization|Period GitLab waits for a response from the external " \
206206
"service. If there is no response, access is denied. Default: 0.5 seconds.")
207207
end
208208

209209
def external_authorization_url_help_text
210-
s_("ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project "\
211-
"features are available and can still specify classification "\
210+
s_("ExternalAuthorization|URL to which the projects make authorization requests. If the URL is blank, cross-project " \
211+
"features are available and can still specify classification " \
212212
"labels for projects.")
213213
end
214214

215215
def external_authorization_client_certificate_help_text
216-
s_("ExternalAuthorization|Certificate used to authenticate with the external authorization service. "\
216+
s_("ExternalAuthorization|Certificate used to authenticate with the external authorization service. " \
217217
"If blank, the server certificate is validated when accessing over HTTPS.")
218218
end
219219

220220
def external_authorization_client_key_help_text
221-
s_("ExternalAuthorization|Private key of client authentication certificate. "\
221+
s_("ExternalAuthorization|Private key of client authentication certificate. " \
222222
"Encrypted when stored.")
223223
end
224224

225225
def external_authorization_client_pass_help_text
226-
s_("ExternalAuthorization|Passphrase required to decrypt the private key. "\
226+
s_("ExternalAuthorization|Passphrase required to decrypt the private key. " \
227227
"Encrypted when stored.")
228228
end
229229

230230
def external_authorization_client_url_help_text
231-
s_("ExternalAuthorization|Classification label to use when requesting authorization if no specific "\
231+
s_("ExternalAuthorization|Classification label to use when requesting authorization if no specific " \
232232
"label is defined on the project.")
233233
end
234234

235235
def sidekiq_job_limiter_mode_help_text
236-
_("How the job limiter handles jobs exceeding the thresholds specified below. "\
237-
"The 'track' mode only logs the jobs. The 'compress' mode compresses the jobs and "\
236+
_("How the job limiter handles jobs exceeding the thresholds specified below. " \
237+
"The 'track' mode only logs the jobs. The 'compress' mode compresses the jobs and " \
238238
"raises an exception if the compressed size exceeds the limit.")
239239
end
240240

app/helpers/groups_helper.rb

+11-3
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,22 @@ def group_confirm_modal_data(group:, remove_form_id: nil, permanently_remove: fa
8686
}
8787
end
8888

89-
# Overridden in EE
9089
def remove_group_message(group, permanently_remove)
90+
return permanently_delete_group_message(group) if permanently_remove
91+
return permanently_delete_group_message(group) unless group.adjourned_deletion?
92+
return permanently_delete_group_message(group) if group.marked_for_deletion?
93+
94+
date = permanent_deletion_date_formatted(Date.current)
95+
96+
_("The contents of this group, its subgroups and projects will be permanently deleted after %{deletion_adjourned_period} days on %{date}. After this point, your data cannot be recovered.") %
97+
{ date: date, deletion_adjourned_period: group.deletion_adjourned_period }
98+
end
99+
100+
def permanently_delete_group_message(group)
91101
content = ''.html_safe
92102
content << content_tag(:span, format(_("You are about to delete the group %{group_name}."), group_name: group.name))
93-
94103
additional_content = additional_removed_items(group)
95104
content << additional_content if additional_content.present?
96-
97105
content << remove_group_warning
98106
end
99107

app/mailers/emails/groups.rb

+14
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
module Emails
44
module Groups
5+
include NamespacesHelper
6+
57
def group_was_exported_email(current_user, group)
68
group_email(current_user, group, _('Group was exported'))
79
end
@@ -15,6 +17,18 @@ def group_email(current_user, group, subj, errors: nil)
1517
@errors = errors
1618
mail_with_locale(to: current_user.notification_email_for(@group), subject: subject(subj))
1719
end
20+
21+
def group_scheduled_for_deletion(recipient_id, group_id)
22+
@group = ::Group.find(group_id)
23+
@user = ::User.find(recipient_id)
24+
@deletion_due_in_days = ::Gitlab::CurrentSettings.deletion_adjourned_period.days
25+
@deletion_date = permanent_deletion_date_formatted(@group.marked_for_deletion_on, format: '%B %-d, %Y')
26+
27+
email_with_layout(
28+
to: @user.email,
29+
subject: subject('Group scheduled for deletion')
30+
)
31+
end
1832
end
1933
end
2034

app/mailers/previews/notify_preview.rb

+11
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,17 @@ def project_scheduled_for_deletion
443443
end
444444
end
445445

446+
def group_scheduled_for_deletion
447+
cleanup do
448+
group.create_deletion_schedule!(
449+
marked_for_deletion_on: Time.current,
450+
deleting_user: user
451+
)
452+
453+
::Notify.group_scheduled_for_deletion(user.id, group.id).message
454+
end
455+
end
456+
446457
private
447458

448459
def project

app/services/groups/mark_for_deletion_service.rb

+6-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@ def execute(licensed: false)
1818

1919
private
2020

21-
# overridden in EE
22-
def send_group_deletion_notification; end
21+
def send_group_deletion_notification
22+
return unless ::Feature.enabled?(:group_deletion_notification_email, group) &&
23+
group.adjourned_deletion?
24+
25+
::NotificationService.new.group_scheduled_for_deletion(group)
26+
end
2327

2428
def create_deletion_schedule
2529
deletion_schedule = group.build_deletion_schedule(deletion_schedule_params)

app/services/notification_service.rb

+13
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,19 @@ def project_scheduled_for_deletion(project)
801801
end
802802
end
803803

804+
def group_scheduled_for_deletion(group)
805+
return if group.emails_disabled?
806+
807+
recipients = group.members.active_without_invites_and_requests.owners.map(&:user)
808+
809+
recipients.each do |recipient|
810+
mailer.group_scheduled_for_deletion(
811+
recipient.id,
812+
group.id
813+
).deliver_later
814+
end
815+
end
816+
804817
protected
805818

806819
def new_resource_email(target, current_user, method)

app/services/projects/mark_for_deletion_service.rb

+1-3
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@ def execute(licensed: false)
2929
private
3030

3131
def send_project_deletion_notification
32-
return unless ::Feature.enabled?(:project_deletion_notification_email, project) &&
33-
project.adjourned_deletion? &&
34-
project.marked_for_deletion?
32+
return unless project.adjourned_deletion? && project.marked_for_deletion?
3533

3634
::NotificationService.new.project_scheduled_for_deletion(project)
3735
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
%p
2+
= _('Hi %{username}!') % { username: sanitize_name(@user.name) }
3+
%p
4+
= _('Your group %{group_name} has been marked for deletion and will be removed in %{days}.').html_safe % { group_name: link_to(@group.full_name, group_url(@group)), days: pluralize((@deletion_due_in_days / 1.day).to_i, _('day')) }
5+
%p
6+
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: url_for(controller: 'groups', action: 'edit', id: @group.full_path, anchor: 'js-advanced-settings', only_path: false) }
7+
= _('If this was a mistake, you can %{link_start}retain the group%{link_end} before %{deletion_date}.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe, deletion_date: @deletion_date }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<%= _('Hi %{username}!') % { username: sanitize_name(@user.name) } %>
2+
<%= _('Your group %{group_name} has been marked for deletion and will be removed in %{days}.') % { group_name: @group.full_name, days: pluralize((@deletion_due_in_days / 1.day).to_i, _('day')) } %>
3+
<%= _('View your group: %{group_url}') % { group_url: group_url(@group) } %>
4+
<%= _('If this was a mistake, you can retain the group before %{deletion_date}: %{retention_url}') % { retention_url: url_for(controller: 'groups', action: 'edit', id: @group.full_path, anchor: 'js-advanced-settings', only_path: false), deletion_date: @deletion_date } %>

config/feature_flags/beta/bulk_update_work_items_mutation.yml

-9
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
---
2-
name: project_deletion_notification_email
2+
name: group_deletion_notification_email
33
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/522883
4-
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/184026
5-
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/525979
4+
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/185270
5+
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/526037
66
milestone: '17.11'
77
group: group::authorization
88
type: gitlab_com_derisk
99
default_enabled: false
10-
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
table_name: work_item_custom_lifecycle_statuses
3+
classes:
4+
- WorkItems::Statuses::Custom::LifecycleStatus
5+
feature_categories:
6+
- team_planning
7+
description: Stores the association between custom lifecycles and statuses with position
8+
information for ordering
9+
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/186050
10+
milestone: '17.11'
11+
gitlab_schema: gitlab_main_cell
12+
sharding_key:
13+
namespace_id: namespaces
14+
table_size: small
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
table_name: work_item_custom_lifecycles
3+
classes:
4+
- WorkItems::Statuses::Custom::Lifecycle
5+
feature_categories:
6+
- team_planning
7+
description: Stores namespace-level custom lifecycle configurations with default statuses for open, closed, and duplicate states
8+
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/186050
9+
milestone: '17.11'
10+
gitlab_schema: gitlab_main_cell
11+
sharding_key:
12+
namespace_id: namespaces
13+
table_size: small

db/docs/work_item_custom_statuses.yml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
table_name: work_item_custom_statuses
3+
classes:
4+
- WorkItems::Statuses::Custom::Status
5+
feature_categories:
6+
- team_planning
7+
description: Stores namespace-level custom status definitions for work items
8+
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/186050
9+
milestone: '17.11'
10+
gitlab_schema: gitlab_main_cell
11+
sharding_key:
12+
namespace_id: namespaces
13+
table_size: small
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
table_name: work_item_type_custom_lifecycles
3+
classes:
4+
- WorkItems::TypeCustomLifecycle
5+
feature_categories:
6+
- team_planning
7+
description: Associates work item types with custom lifecycles within a namespace
8+
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/186050
9+
milestone: '17.11'
10+
gitlab_schema: gitlab_main_cell
11+
sharding_key:
12+
namespace_id: namespaces
13+
table_size: small
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# frozen_string_literal: true
2+
3+
class CreateWorkItemCustomStatuses < Gitlab::Database::Migration[2.2]
4+
milestone '17.11'
5+
6+
def change
7+
# Factory: /ee/spec/factories/work_items/statuses/custom/statuses.rb
8+
create_table :work_item_custom_statuses do |t| # rubocop:disable Migration/EnsureFactoryForTable -- reason above
9+
t.bigint :namespace_id, null: false
10+
t.timestamps_with_timezone null: false
11+
t.integer :category, null: false, default: 1, limit: 1
12+
t.text :name, null: false, limit: 255
13+
t.text :description, limit: 255
14+
t.text :color, null: false, limit: 7
15+
16+
t.index [:namespace_id, :name], unique: true
17+
end
18+
end
19+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# frozen_string_literal: true
2+
3+
class AddNamespaceFkToWorkItemCustomStatuses < Gitlab::Database::Migration[2.2]
4+
disable_ddl_transaction!
5+
milestone '17.11'
6+
7+
def up
8+
add_concurrent_foreign_key :work_item_custom_statuses, :namespaces,
9+
column: :namespace_id, on_delete: :cascade
10+
end
11+
12+
def down
13+
remove_foreign_key_if_exists :work_item_custom_statuses, column: :namespace_id
14+
end
15+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# frozen_string_literal: true
2+
3+
class CreateWorkItemCustomLifecycles < Gitlab::Database::Migration[2.2]
4+
milestone '17.11'
5+
6+
def change
7+
# Factory: /ee/spec/factories/work_items/statuses/custom/lifecycles.rb
8+
create_table :work_item_custom_lifecycles do |t| # rubocop:disable Migration/EnsureFactoryForTable -- reason above
9+
t.bigint :namespace_id, null: false
10+
t.bigint :default_open_status_id, null: false,
11+
index: { name: 'idx_wi_custom_lifecycles_on_open_status_id' }
12+
t.bigint :default_closed_status_id, null: false,
13+
index: { name: 'idx_wi_custom_lifecycles_on_closed_status_id' }
14+
t.bigint :default_duplicate_status_id, null: false,
15+
index: { name: 'idx_wi_custom_lifecycles_on_duplicate_status_id' }
16+
t.timestamps_with_timezone null: false
17+
t.text :name, null: false, limit: 255
18+
19+
t.index [:namespace_id, :name], unique: true
20+
end
21+
end
22+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# frozen_string_literal: true
2+
3+
class AddNamespaceFkToWorkItemCustomLifecycles < Gitlab::Database::Migration[2.2]
4+
disable_ddl_transaction!
5+
milestone '17.11'
6+
7+
def up
8+
add_concurrent_foreign_key :work_item_custom_lifecycles, :namespaces,
9+
column: :namespace_id, on_delete: :cascade
10+
end
11+
12+
def down
13+
remove_foreign_key_if_exists :work_item_custom_lifecycles, column: :namespace_id
14+
end
15+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# frozen_string_literal: true
2+
3+
class AddOpenStatusFkToWorkItemCustomLifecycles < Gitlab::Database::Migration[2.2]
4+
disable_ddl_transaction!
5+
milestone '17.11'
6+
7+
def up
8+
add_concurrent_foreign_key :work_item_custom_lifecycles, :work_item_custom_statuses,
9+
column: :default_open_status_id, on_delete: :cascade
10+
end
11+
12+
def down
13+
remove_foreign_key_if_exists :work_item_custom_lifecycles, column: :default_open_status_id
14+
end
15+
end

0 commit comments

Comments
 (0)