From ad1e76fb4d1392c890c8b5e218a256a416d5a50b Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 1 Mar 2023 18:07:43 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- .gitlab/ci/database.gitlab-ci.yml | 7 +-- .../behaviors/markdown/render_observability.js | 2 +- app/assets/javascripts/diffs/components/app.vue | 5 ++ app/assets/javascripts/diffs/index.js | 2 + app/assets/javascripts/diffs/store/actions.js | 2 + .../javascripts/diffs/store/modules/diff_state.js | 1 + app/assets/javascripts/diffs/store/mutations.js | 2 + .../components/invite_modal_base.vue | 41 +++++++++++-- .../components/states/nothing_to_merge.vue | 18 +++--- app/graphql/mutations/issues/bulk_update.rb | 23 +++++++- .../types/issuable_subscription_event_enum.rb | 11 ++++ app/helpers/merge_requests_helper.rb | 1 + app/mailers/emails/issues.rb | 13 +---- app/mailers/emails/shared.rb | 20 +++++++ app/mailers/emails/work_items.rb | 4 ++ app/mailers/notify.rb | 1 + app/models/group.rb | 1 - app/models/members/member_role.rb | 11 ++++ .../clusters/agent_tokens/create_service.rb | 4 +- .../clusters/agent_tokens/revoke_service.rb | 13 +++++ .../agents/create_activity_event_service.rb | 4 ++ app/services/work_items/export_csv_service.rb | 2 +- app/views/notify/_issuable_csv_export.html.haml | 6 +- app/views/notify/_issuable_csv_export.text.erb | 7 +++ .../notify/export_work_items_csv_email.html.haml | 1 + .../notify/export_work_items_csv_email.text.erb | 1 + app/views/notify/issues_csv_email.text.erb | 6 +- app/views/notify/merge_requests_csv_email.text.erb | 6 +- app/views/projects/artifacts/browse.html.haml | 2 +- app/views/shared/icons/_mr_widget_empty_state.svg | 1 - config/application.rb | 2 +- doc/api/graphql/reference/index.md | 17 +++++- doc/api/product_analytics.md | 3 +- doc/user/product_analytics/index.md | 4 +- lib/tasks/gitlab/tw/codeowners.rake | 3 +- locale/gitlab.pot | 13 ++--- spec/features/markdown/observability_spec.rb | 2 +- .../markdown/render_observability_spec.js | 4 +- .../forms/components/integration_form_spec.js | 31 ++++------ spec/frontend/diffs/components/app_spec.js | 1 + spec/frontend/diffs/store/actions_spec.js | 4 ++ .../components/invite_groups_modal_spec.js | 12 ++-- .../components/invite_members_modal_spec.js | 27 ++++----- .../components/invite_modal_base_spec.js | 27 +++++---- .../components/dropdown/dropdown_widget_spec.js | 4 -- spec/mailers/emails/issues_spec.rb | 36 +----------- spec/mailers/emails/work_items_spec.rb | 17 ++++++ spec/models/members/member_role_spec.rb | 24 ++++++++ .../graphql/mutations/issues/bulk_update_spec.rb | 68 +++++++++++----------- .../clusters/agent_tokens/revoke_service_spec.rb | 32 +++++++--- .../agents/create_activity_event_service_spec.rb | 13 ++++- .../services/work_items/export_csv_service_spec.rb | 5 +- .../mailers/export_csv_shared_examples.rb | 37 ++++++++++++ workhorse/go.mod | 2 +- workhorse/go.sum | 4 +- 55 files changed, 402 insertions(+), 208 deletions(-) create mode 100644 app/graphql/types/issuable_subscription_event_enum.rb create mode 100644 app/mailers/emails/shared.rb create mode 100644 app/views/notify/_issuable_csv_export.text.erb create mode 100644 app/views/notify/export_work_items_csv_email.html.haml create mode 100644 app/views/notify/export_work_items_csv_email.text.erb delete mode 100644 app/views/shared/icons/_mr_widget_empty_state.svg create mode 100644 spec/mailers/emails/work_items_spec.rb create mode 100644 spec/support/shared_examples/mailers/export_csv_shared_examples.rb diff --git a/.gitlab/ci/database.gitlab-ci.yml b/.gitlab/ci/database.gitlab-ci.yml index 6fd9ef62953..941cb9224fb 100644 --- a/.gitlab/ci/database.gitlab-ci.yml +++ b/.gitlab/ci/database.gitlab-ci.yml @@ -36,8 +36,8 @@ db:rollback: - .db-job-base - .rails:rules:db-rollback script: - - scripts/db_tasks db:migrate VERSION=20220502173045 # 14.10 (last 14.x version) - - scripts/db_tasks db:migrate + - bundle exec rake db:migrate VERSION=20220502173045 # 14.10 (last 14.x version) + - bundle exec rake db:migrate db:rollback single-db: extends: @@ -61,8 +61,7 @@ db:check-schema: - .db-job-base - .rails:rules:ee-mr-and-default-branch-only script: - - run_timed_command "bundle exec rake db:drop db:create" - - run_timed_command "scripts/db_tasks db:migrate" + - run_timed_command "bundle exec rake db:drop db:create db:migrate" db:check-schema-single-db: extends: diff --git a/app/assets/javascripts/behaviors/markdown/render_observability.js b/app/assets/javascripts/behaviors/markdown/render_observability.js index 704d85cf22e..85aae6f53c4 100644 --- a/app/assets/javascripts/behaviors/markdown/render_observability.js +++ b/app/assets/javascripts/behaviors/markdown/render_observability.js @@ -3,7 +3,7 @@ import { darkModeEnabled } from '~/lib/utils/color_utils'; import { setUrlParams } from '~/lib/utils/url_utility'; export function getFrameSrc(url) { - return `${setUrlParams({ theme: darkModeEnabled() ? 'dark' : 'light' }, url)}&kiosk`; + return `${setUrlParams({ theme: darkModeEnabled() ? 'dark' : 'light' }, url)}&kiosk=inline-embed`; } const mountVueComponent = (element) => { diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue index 2b5670bd9c7..9a6b36ad2e8 100644 --- a/app/assets/javascripts/diffs/components/app.vue +++ b/app/assets/javascripts/diffs/components/app.vue @@ -95,6 +95,10 @@ export default { type: String, required: true, }, + endpointDiffForPath: { + type: String, + required: true, + }, endpointCoverage: { type: String, required: false, @@ -322,6 +326,7 @@ export default { endpoint: this.endpoint, endpointMetadata: this.endpointMetadata, endpointBatch: this.endpointBatch, + endpointDiffForPath: this.endpointDiffForPath, endpointCoverage: this.endpointCoverage, endpointUpdateUser: this.endpointUpdateUser, projectPath: this.projectPath, diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js index 7da5ef54b80..f6865056b05 100644 --- a/app/assets/javascripts/diffs/index.js +++ b/app/assets/javascripts/diffs/index.js @@ -25,6 +25,7 @@ export default function initDiffsApp(store = notesStore) { endpoint: dataset.endpoint, endpointMetadata: dataset.endpointMetadata || '', endpointBatch: dataset.endpointBatch || '', + endpointDiffForPath: dataset.endpointDiffForPath || '', endpointCoverage: dataset.endpointCoverage || '', endpointCodequality: dataset.endpointCodequality || '', endpointUpdateUser: dataset.updateCurrentUserPath, @@ -86,6 +87,7 @@ export default function initDiffsApp(store = notesStore) { endpoint: this.endpoint, endpointMetadata: this.endpointMetadata, endpointBatch: this.endpointBatch, + endpointDiffForPath: this.endpointDiffForPath, endpointCoverage: this.endpointCoverage, endpointCodequality: this.endpointCodequality, endpointUpdateUser: this.endpointUpdateUser, diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js index e06c15bc1b4..561e2a4f134 100644 --- a/app/assets/javascripts/diffs/store/actions.js +++ b/app/assets/javascripts/diffs/store/actions.js @@ -69,6 +69,7 @@ export const setBaseConfig = ({ commit }, options) => { endpoint, endpointMetadata, endpointBatch, + endpointDiffForPath, endpointCoverage, endpointUpdateUser, projectPath, @@ -82,6 +83,7 @@ export const setBaseConfig = ({ commit }, options) => { endpoint, endpointMetadata, endpointBatch, + endpointDiffForPath, endpointCoverage, endpointUpdateUser, projectPath, diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js index 329db1fe2cf..593c28f20ec 100644 --- a/app/assets/javascripts/diffs/store/modules/diff_state.js +++ b/app/assets/javascripts/diffs/store/modules/diff_state.js @@ -16,6 +16,7 @@ export default () => ({ removedLines: null, endpoint: '', endpointUpdateUser: '', + endpointDiffForPath: '', basePath: '', commit: null, startVersion: null, // Null unless a target diff is selected for comparison that is not the "base" diff diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js index d2b798245fc..04f08e86955 100644 --- a/app/assets/javascripts/diffs/store/mutations.js +++ b/app/assets/javascripts/diffs/store/mutations.js @@ -33,6 +33,7 @@ export default { endpoint, endpointMetadata, endpointBatch, + endpointDiffForPath, endpointCoverage, endpointUpdateUser, projectPath, @@ -46,6 +47,7 @@ export default { endpoint, endpointMetadata, endpointBatch, + endpointDiffForPath, endpointCoverage, endpointUpdateUser, projectPath, diff --git a/app/assets/javascripts/invite_members/components/invite_modal_base.vue b/app/assets/javascripts/invite_members/components/invite_modal_base.vue index 1e3b6093f0b..20dc32b3c9b 100644 --- a/app/assets/javascripts/invite_members/components/invite_modal_base.vue +++ b/app/assets/javascripts/invite_members/components/invite_modal_base.vue @@ -1,5 +1,14 @@ @@ -38,9 +31,12 @@ export default {
- +

diff --git a/app/graphql/mutations/issues/bulk_update.rb b/app/graphql/mutations/issues/bulk_update.rb index 3d80f119079..9c9dd3cf2fc 100644 --- a/app/graphql/mutations/issues/bulk_update.rb +++ b/app/graphql/mutations/issues/bulk_update.rb @@ -14,7 +14,8 @@ module Mutations argument :parent_id, ::Types::GlobalIDType[::IssueParent], required: true, - description: 'Global ID of the parent that the bulk update will be scoped to . ' \ + description: 'Global ID of the parent to which the bulk update will be scoped. ' \ + 'The parent can be a project **(FREE)** or a group **(PREMIUM)**. ' \ 'Example `IssueParentID` are `"gid://gitlab/Project/1"` and `"gid://gitlab/Group/1"`.' argument :ids, [::Types::GlobalIDType[::Issue]], @@ -31,6 +32,22 @@ module Mutations required: false, description: 'Global ID of the milestone that will be assigned to the issues.' + argument :state_event, Types::IssueStateEventEnum, + description: 'Close or reopen an issue.', + required: false + + argument :add_label_ids, [::Types::GlobalIDType[::Label]], + description: 'Global ID array of the labels that will be added to the issues. ', + required: false + + argument :remove_label_ids, [::Types::GlobalIDType[::Label]], + description: 'Global ID array of the labels that will be removed from the issues. ', + required: false + + argument :subscription_event, Types::IssuableSubscriptionEventEnum, + description: 'Subscribe to or unsubscribe from issue notifications.', + required: false + field :updated_issue_count, GraphQL::Types::Int, null: true, description: 'Number of issues that were successfully updated.' @@ -74,7 +91,7 @@ module Mutations end def prepared_params(attributes, ids) - prepared = { issuable_ids: model_ids_from(ids).uniq } + prepared = attributes.except(*global_id_arguments).merge(issuable_ids: model_ids_from(ids).uniq) global_id_arguments.each do |argument| next unless attributes.key?(argument) @@ -92,7 +109,7 @@ module Mutations end def global_id_arguments - %i[assignee_ids milestone_id] + %i[assignee_ids milestone_id add_label_ids remove_label_ids] end def model_ids_from(attributes) diff --git a/app/graphql/types/issuable_subscription_event_enum.rb b/app/graphql/types/issuable_subscription_event_enum.rb new file mode 100644 index 00000000000..0f56fab8b46 --- /dev/null +++ b/app/graphql/types/issuable_subscription_event_enum.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Types + class IssuableSubscriptionEventEnum < BaseEnum + graphql_name 'IssuableSubscriptionEvent' + description 'Values for subscribing and unsubscribing from issuables' + + value 'SUBSCRIBE', 'Subscribe to an issuable.', value: 'subscribe' + value 'UNSUBSCRIBE', 'Unsubscribe from an issuable.', value: 'unsubscribe' + end +end diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index ec395baef9e..590659be0cb 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -185,6 +185,7 @@ module MergeRequestsHelper endpoint_metadata: @endpoint_metadata_url, endpoint_batch: diffs_batch_project_json_merge_request_path(project, merge_request, 'json', params), endpoint_coverage: @coverage_path, + endpoint_diff_for_path: diff_for_path_namespace_project_merge_request_path(format: 'json', id: merge_request.iid, namespace_id: project.namespace.path, project_id: project.path), help_page_path: help_page_path('user/project/merge_requests/reviews/suggestions.md'), current_user_data: @current_user_data, update_current_user_path: @update_current_user_path, diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb index 58843435fa0..e053fc0453c 100644 --- a/app/mailers/emails/issues.rb +++ b/app/mailers/emails/issues.rb @@ -100,18 +100,7 @@ module Emails end def issues_csv_email(user, project, csv_data, export_status) - @project = project - @count = export_status.fetch(:rows_expected) - @written_count = export_status.fetch(:rows_written) - @truncated = export_status.fetch(:truncated) - @size_limit = ActiveSupport::NumberHelper - .number_to_human_size(ExportCsv::BaseService::TARGET_FILESIZE) - - filename = "#{project.full_path.parameterize}_issues_#{Date.today.iso8601}.csv" - attachments[filename] = { content: csv_data, mime_type: 'text/csv' } - email_with_layout( - to: user.notification_email_for(@project.group), - subject: subject("Exported issues")) + csv_email(user, project, csv_data, export_status, 'issues') end private diff --git a/app/mailers/emails/shared.rb b/app/mailers/emails/shared.rb new file mode 100644 index 00000000000..09876c0960a --- /dev/null +++ b/app/mailers/emails/shared.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Emails + module Shared + def csv_email(user, project, csv_data, export_status, type) + @project = project + @count = export_status.fetch(:rows_expected) + @written_count = export_status.fetch(:rows_written) + @truncated = export_status.fetch(:truncated) + @size_limit = ActiveSupport::NumberHelper + .number_to_human_size(ExportCsv::BaseService::TARGET_FILESIZE) + + filename = "#{project.full_path.parameterize}_#{type}_#{Date.today.iso8601}.csv" + attachments[filename] = { content: csv_data, mime_type: 'text/csv' } + email_with_layout( + to: user.notification_email_for(@project.group), + subject: subject("Exported #{type.humanize.downcase}")) + end + end +end diff --git a/app/mailers/emails/work_items.rb b/app/mailers/emails/work_items.rb index fe669fdbedc..a243158d82f 100644 --- a/app/mailers/emails/work_items.rb +++ b/app/mailers/emails/work_items.rb @@ -11,5 +11,9 @@ module Emails to: @user.notification_email_for(@project), subject: subject('Imported work items')) end + + def export_work_items_csv_email(user, project, csv_data, export_status) + csv_email(user, project, csv_data, export_status, 'work_items') + end end end diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index 0465887cdc6..2d6b2a3099c 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -7,6 +7,7 @@ class Notify < ApplicationMailer include ReminderEmailsHelper include IssuablesHelper + include Emails::Shared include Emails::Issues include Emails::MergeRequests include Emails::Notes diff --git a/app/models/group.rb b/app/models/group.rb index d325d1d351a..0dcc35b2a39 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -21,7 +21,6 @@ class Group < Namespace include ChronicDurationAttribute include RunnerTokenExpirationInterval include Todoable - include IssueParent extend ::Gitlab::Utils::Override diff --git a/app/models/members/member_role.rb b/app/models/members/member_role.rb index 42ce228c318..77e97a35b6d 100644 --- a/app/models/members/member_role.rb +++ b/app/models/members/member_role.rb @@ -4,12 +4,15 @@ class MemberRole < ApplicationRecord # rubocop:disable Gitlab/NamespacedClass include IgnorableColumns ignore_column :download_code, remove_with: '15.9', remove_after: '2023-01-22' + MAX_COUNT_PER_GROUP_HIERARCHY = 10 + has_many :members belongs_to :namespace validates :namespace, presence: true validates :base_access_level, presence: true validate :belongs_to_top_level_namespace + validate :max_count_per_group_hierarchy, on: :create validate :validate_namespace_locked, on: :update validate :attributes_locked_after_member_associated, on: :update @@ -25,6 +28,14 @@ class MemberRole < ApplicationRecord # rubocop:disable Gitlab/NamespacedClass errors.add(:namespace, s_("MemberRole|must be top-level namespace")) end + def max_count_per_group_hierarchy + return unless namespace + return if namespace.member_roles.count < MAX_COUNT_PER_GROUP_HIERARCHY + + errors.add(:namespace, s_("MemberRole|maximum number of Member Roles are already in use by the group hierarchy. "\ + "Please delete an existing Member Role.")) + end + def validate_namespace_locked return unless namespace_id_changed? diff --git a/app/services/clusters/agent_tokens/create_service.rb b/app/services/clusters/agent_tokens/create_service.rb index e0c0b613adc..66a3cb04d98 100644 --- a/app/services/clusters/agent_tokens/create_service.rb +++ b/app/services/clusters/agent_tokens/create_service.rb @@ -19,7 +19,7 @@ module Clusters token = ::Clusters::AgentToken.new(filtered_params.merge(agent_id: agent.id, created_by_user: current_user)) if token.save - log_activity_event!(token) + log_activity_event(token) ServiceResponse.success(payload: { secret: token.token, token: token }) else @@ -37,7 +37,7 @@ module Clusters params.slice(*ALLOWED_PARAMS) end - def log_activity_event!(token) + def log_activity_event(token) Clusters::Agents::CreateActivityEventService.new( token.agent, kind: :token_created, diff --git a/app/services/clusters/agent_tokens/revoke_service.rb b/app/services/clusters/agent_tokens/revoke_service.rb index 247cedb8e38..5d89b405969 100644 --- a/app/services/clusters/agent_tokens/revoke_service.rb +++ b/app/services/clusters/agent_tokens/revoke_service.rb @@ -14,6 +14,8 @@ module Clusters return error_no_permissions unless current_user.can?(:create_cluster, token.agent.project) if token.update(status: token.class.statuses[:revoked]) + log_activity_event(token) + ServiceResponse.success else ServiceResponse.error(message: token.errors.full_messages) @@ -26,6 +28,17 @@ module Clusters ServiceResponse.error( message: s_('ClusterAgent|User has insufficient permissions to revoke the token for this project')) end + + def log_activity_event(token) + Clusters::Agents::CreateActivityEventService.new( + token.agent, + kind: :token_revoked, + level: :info, + recorded_at: token.updated_at, + user: current_user, + agent_token: token + ).execute + end end end end diff --git a/app/services/clusters/agents/create_activity_event_service.rb b/app/services/clusters/agents/create_activity_event_service.rb index 886dddf1a52..87554f0e495 100644 --- a/app/services/clusters/agents/create_activity_event_service.rb +++ b/app/services/clusters/agents/create_activity_event_service.rb @@ -14,6 +14,10 @@ module Clusters DeleteExpiredEventsWorker.perform_at(schedule_cleanup_at, agent.id) ServiceResponse.success + rescue StandardError => e + Gitlab::ErrorTracking.track_exception(e, agent_id: agent.id) + + ServiceResponse.error(message: e.message) end private diff --git a/app/services/work_items/export_csv_service.rb b/app/services/work_items/export_csv_service.rb index 9bef75e2c40..a715aab1b30 100644 --- a/app/services/work_items/export_csv_service.rb +++ b/app/services/work_items/export_csv_service.rb @@ -11,7 +11,7 @@ module WorkItems end def email(mail_to_user) - # TODO - will be implemented as part of https://gitlab.com/gitlab-org/gitlab/-/issues/379082 + Notify.export_work_items_csv_email(mail_to_user, resource_parent, csv_data, csv_builder.status).deliver_now end private diff --git a/app/views/notify/_issuable_csv_export.html.haml b/app/views/notify/_issuable_csv_export.html.haml index 3b1fe90eaee..f7c6168ecb6 100644 --- a/app/views/notify/_issuable_csv_export.html.haml +++ b/app/views/notify/_issuable_csv_export.html.haml @@ -1,6 +1,8 @@ +- type = type.to_s.humanize.downcase + %p{ style: 'font-size:18px; text-align:center; line-height:30px;' } - project_link = link_to(@project.full_name, project_url(@project), style: "color:#3777b0; text-decoration:none; display:block;") - = _('Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment.').html_safe % { count: pluralize(@written_count, type.to_s.titleize.downcase), project_link: project_link } + = _('Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment.').html_safe % { count: pluralize(@written_count, type.titleize.downcase), project_link: project_link } - if @truncated %p - = _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{count} %{issuables} have been included. Consider re-exporting with a narrower selection of %{issuables}.') % { written_count: @written_count, count: @count, issuables: type.to_s.pluralize, size_limit: @size_limit } + = _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{count} %{issuables} have been included. Consider re-exporting with a narrower selection of %{issuables}.') % { written_count: @written_count, count: @count, issuables: type.pluralize, size_limit: @size_limit } diff --git a/app/views/notify/_issuable_csv_export.text.erb b/app/views/notify/_issuable_csv_export.text.erb new file mode 100644 index 00000000000..a6e908803f5 --- /dev/null +++ b/app/views/notify/_issuable_csv_export.text.erb @@ -0,0 +1,7 @@ +<% type = type.to_s.humanize.downcase %> + +<%= _('Your CSV export of %{exported_objects} from project %{project_name} (%{project_url}) has been added to this email as an attachment.') % { exported_objects: pluralize(@written_count, type), project_name: @project.full_name, project_url: project_url(@project) } %> + +<% if @truncated %> + <%= _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{total_count} %{object_type} have been included. Consider re-exporting with a narrower selection of %{object_type}.') % { written_count: @written_count, total_count: @count, size_limit: @size_limit, object_type: type.pluralize } %> +<% end %> diff --git a/app/views/notify/export_work_items_csv_email.html.haml b/app/views/notify/export_work_items_csv_email.html.haml new file mode 100644 index 00000000000..db842262049 --- /dev/null +++ b/app/views/notify/export_work_items_csv_email.html.haml @@ -0,0 +1 @@ += render 'issuable_csv_export', type: :work_item diff --git a/app/views/notify/export_work_items_csv_email.text.erb b/app/views/notify/export_work_items_csv_email.text.erb new file mode 100644 index 00000000000..ec4aaa38886 --- /dev/null +++ b/app/views/notify/export_work_items_csv_email.text.erb @@ -0,0 +1 @@ +<%= render 'issuable_csv_export', type: :work_item %> diff --git a/app/views/notify/issues_csv_email.text.erb b/app/views/notify/issues_csv_email.text.erb index cf2910c4014..5b6c151e4ce 100644 --- a/app/views/notify/issues_csv_email.text.erb +++ b/app/views/notify/issues_csv_email.text.erb @@ -1,5 +1 @@ -<%= _('Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment.') % { written_count: pluralize(@written_count, 'issue'), project_name: @project.full_name, project_url: project_url(@project) } %> - -<% if @truncated %> - <%= _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues.') % { written_count: @written_count, issues_count: @issues_count, size_limit: @size_limit } %> -<% end %> +<%= render 'issuable_csv_export', type: :issue %> diff --git a/app/views/notify/merge_requests_csv_email.text.erb b/app/views/notify/merge_requests_csv_email.text.erb index 78d11dde69f..c5dec164a4d 100644 --- a/app/views/notify/merge_requests_csv_email.text.erb +++ b/app/views/notify/merge_requests_csv_email.text.erb @@ -1,5 +1 @@ -<%= _('Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment.') % { written_count: pluralize(@written_count, 'merge request'), project_name: @project.full_name, project_url: project_url(@project) } %> - -<% if @truncated %> - <%= _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{merge_requests_count} merge requests have been included. Consider re-exporting with a narrower selection of merge requests.') % { written_count: @written_count, merge_requests_count: @merge_requests_count, size_limit: @size_limit} %> -<% end %> +<%= render 'issuable_csv_export', type: :merge_request %> diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml index 3359ea5f63b..ccda06c7e4c 100644 --- a/app/views/projects/artifacts/browse.html.haml +++ b/app/views/projects/artifacts/browse.html.haml @@ -12,7 +12,7 @@ .nav-block %ul.breadcrumb.repo-breadcrumb %li.breadcrumb-item - = link_to 'Artifacts', browse_project_job_artifacts_path(@project, @build) + = link_to _('Artifacts'), browse_project_job_artifacts_path(@project, @build) - path_breadcrumbs do |title, path| %li.breadcrumb-item = link_to truncate(title, length: 40), browse_project_job_artifacts_path(@project, @build, path) diff --git a/app/views/shared/icons/_mr_widget_empty_state.svg b/app/views/shared/icons/_mr_widget_empty_state.svg deleted file mode 100644 index a75eee846c9..00000000000 --- a/app/views/shared/icons/_mr_widget_empty_state.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/config/application.rb b/config/application.rb index a9008e387cf..94195be4481 100644 --- a/config/application.rb +++ b/config/application.rb @@ -405,7 +405,7 @@ module Gitlab config.middleware.insert_before ActionDispatch::RemoteIp, ::Gitlab::Middleware::HandleIpSpoofAttackError - config.middleware.insert_after ActionDispatch::ActionableExceptions, ::Gitlab::Middleware::HandleMalformedStrings + config.middleware.insert_after Rails::Rack::Logger, ::Gitlab::Middleware::HandleMalformedStrings config.middleware.insert_after Rack::Sendfile, ::Gitlab::Middleware::RackMultipartTempfileFactory diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index ebeaca6b5b5..e0f34da8fbd 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -3673,12 +3673,18 @@ Input type: `IssuesBulkUpdateInput` | Name | Type | Description | | ---- | ---- | ----------- | +| `addLabelIds` | [`[LabelID!]`](#labelid) | Global ID array of the labels that will be added to the issues. | | `assigneeIds` | [`[UserID!]`](#userid) | Global ID array of the users that will be assigned to the given issues. Existing assignees will be replaced with the ones on this list. | | `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `epicId` | [`EpicID`](#epicid) | Global ID of the epic that will be assigned to the issues. | +| `healthStatus` | [`HealthStatus`](#healthstatus) | Health status that will be assigned to the issues. | | `ids` | [`[IssueID!]!`](#issueid) | Global ID array of the issues that will be updated. IDs that the user can't update will be ignored. A max of 100 can be provided. | | `iterationId` | [`IterationID`](#iterationid) | Global ID of the iteration that will be assigned to the issues. | | `milestoneId` | [`MilestoneID`](#milestoneid) | Global ID of the milestone that will be assigned to the issues. | -| `parentId` | [`IssueParentID!`](#issueparentid) | Global ID of the parent that the bulk update will be scoped to . Example `IssueParentID` are `"gid://gitlab/Project/1"` and `"gid://gitlab/Group/1"`. | +| `parentId` | [`IssueParentID!`](#issueparentid) | Global ID of the parent to which the bulk update will be scoped. The parent can be a project **(FREE)** or a group **(PREMIUM)**. Example `IssueParentID` are `"gid://gitlab/Project/1"` and `"gid://gitlab/Group/1"`. | +| `removeLabelIds` | [`[LabelID!]`](#labelid) | Global ID array of the labels that will be removed from the issues. | +| `stateEvent` | [`IssueStateEvent`](#issuestateevent) | Close or reopen an issue. | +| `subscriptionEvent` | [`IssuableSubscriptionEvent`](#issuablesubscriptionevent) | Subscribe to or unsubscribe from issue notifications. | #### Fields @@ -23035,6 +23041,15 @@ State of a GitLab issue or merge request. | `locked` | Discussion has been locked. | | `opened` | In open state. | +### `IssuableSubscriptionEvent` + +Values for subscribing and unsubscribing from issuables. + +| Value | Description | +| ----- | ----------- | +| `SUBSCRIBE` | Subscribe to an issuable. | +| `UNSUBSCRIBE` | Unsubscribe from an issuable. | + ### `IssueCreationIterationWildcardId` Iteration ID wildcard values for issue creation. diff --git a/doc/api/product_analytics.md b/doc/api/product_analytics.md index c687acdb5db..8eda24d1c65 100644 --- a/doc/api/product_analytics.md +++ b/doc/api/product_analytics.md @@ -6,7 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Product analytics API **(ULTIMATE)** -> Introduced in GitLab 15.4 [with a flag](../administration/feature_flags.md) named `cube_api_proxy`. Disabled by default. +> - Introduced in GitLab 15.4 [with a flag](../administration/feature_flags.md) named `cube_api_proxy`. Disabled by default. +> - `cube_api_proxy` removed and replaced with `product_analytics_internal_preview` in GitLab 15.10. FLAG: On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `cube_api_proxy`. diff --git a/doc/user/product_analytics/index.md b/doc/user/product_analytics/index.md index 51259f1677d..1a6ad4edf02 100644 --- a/doc/user/product_analytics/index.md +++ b/doc/user/product_analytics/index.md @@ -8,9 +8,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w > - Introduced in GitLab 15.4 as an [Alpha](../../policy/alpha-beta-support.md#alpha-features) feature [with a flag](../../administration/feature_flags.md) named `cube_api_proxy`. Disabled by default. > - `cube_api_proxy` revised to only reference the [Product Analytics API](../../api/product_analytics.md) in GitLab 15.6. +> - `cube_api_proxy` removed and replaced with `product_analytics_internal_preview` in GitLab 15.10. FLAG: -On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `cube_api_proxy`. +On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `product_analytics_internal_preview`. On GitLab.com, this feature is not available. This feature is not ready for production use. @@ -50,6 +51,7 @@ Product Analytics uses several tools: > - Introduced in GitLab 15.6 behind the [feature flag](../../administration/feature_flags.md) named `cube_api_proxy`. Disabled by default. > - Moved to be behind the [feature flag](../../administration/feature_flags.md) named `product_analytics_admin_settings` in GitLab 15.7. Disabled by default. +> - `cube_api_proxy` removed and replaced with `product_analytics_internal_preview` in GitLab 15.10. FLAG: On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `product_analytics_admin_settings`. diff --git a/lib/tasks/gitlab/tw/codeowners.rake b/lib/tasks/gitlab/tw/codeowners.rake index e6bbbc55cb1..742f13063c9 100644 --- a/lib/tasks/gitlab/tw/codeowners.rake +++ b/lib/tasks/gitlab/tw/codeowners.rake @@ -24,7 +24,6 @@ namespace :tw do CodeOwnerRule.new('Certify', '@msedlakjakubowski'), CodeOwnerRule.new('Code Review', '@aqualls'), CodeOwnerRule.new('Compliance', '@eread'), - CodeOwnerRule.new('Commerce Integrations', '@drcatherinepope'), CodeOwnerRule.new('Composition Analysis', '@rdickenson'), CodeOwnerRule.new('Configure', '@phillipwells'), CodeOwnerRule.new('Container Registry', '@marcel.amirault'), @@ -73,7 +72,7 @@ namespace :tw do CodeOwnerRule.new('Static Analysis', '@rdickenson'), CodeOwnerRule.new('Style Guide', '@sselhorn'), CodeOwnerRule.new('Testing', '@eread'), - CodeOwnerRule.new('Threat Insights', '@dianalogan'), + CodeOwnerRule.new('Threat Insights', '@rdickenson'), CodeOwnerRule.new('Tutorials', '@kpaizee'), CodeOwnerRule.new('Utilization', '@fneill'), CodeOwnerRule.new('Vulnerability Research', '@dianalogan'), diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d6ad6c4ad20..266717412a6 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -26447,6 +26447,9 @@ msgstr "" msgid "MemberRole|cannot be deleted because it is already assigned to a user. Please disassociate the member role from all users before deletion." msgstr "" +msgid "MemberRole|maximum number of Member Roles are already in use by the group hierarchy. Please delete an existing Member Role." +msgstr "" + msgid "MemberRole|must be top-level namespace" msgstr "" @@ -43961,13 +43964,7 @@ msgstr "" msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{count} %{issuables} have been included. Consider re-exporting with a narrower selection of %{issuables}." msgstr "" -msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues." -msgstr "" - -msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{merge_requests_count} merge requests have been included. Consider re-exporting with a narrower selection of merge requests." -msgstr "" - -msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{requirements_count} requirements have been included. Consider re-exporting with a narrower selection of requirements." +msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{total_count} %{object_type} have been included. Consider re-exporting with a narrower selection of %{object_type}." msgstr "" msgid "This block is self-referential" @@ -49805,7 +49802,7 @@ msgstr "" msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment." msgstr "" -msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment." +msgid "Your CSV export of %{exported_objects} from project %{project_name} (%{project_url}) has been added to this email as an attachment." msgstr "" msgid "Your CSV import for project" diff --git a/spec/features/markdown/observability_spec.rb b/spec/features/markdown/observability_spec.rb index e57bfafe05e..0c5aba5326f 100644 --- a/spec/features/markdown/observability_spec.rb +++ b/spec/features/markdown/observability_spec.rb @@ -9,7 +9,7 @@ RSpec.describe 'Observability rendering', :js, feature_category: :metrics do let_it_be(:observable_url) { "https://observe.gitlab.com/#{group.id}/some-dashboard" } let_it_be(:expected) do - %(