From d134089c5e1b2b5bc4af1433deecce5916e75973 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 19 Jun 2024 12:23:23 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .gitlab/ci/rules.gitlab-ci.yml | 1 + GITLAB_ELASTICSEARCH_INDEXER_VERSION | 2 +- app/assets/javascripts/emoji/index.js | 58 ++-- .../emoji/queries/custom_emoji.query.graphql | 8 +- .../components/service_desk_root.vue | 7 + .../components/service_desk_setting.vue | 69 +++++ .../projects/settings_service_desk/index.js | 2 + .../design_preview/design_toolbar.vue | 10 + .../components/work_item_detail.vue | 24 +- .../groups/work_items_controller.rb | 1 + app/controllers/groups_controller.rb | 1 + app/controllers/projects/issues_controller.rb | 1 + .../projects/work_items_controller.rb | 1 + app/controllers/projects_controller.rb | 1 + app/controllers/search_controller.rb | 10 +- app/mailers/notify.rb | 4 + app/models/ci/pipeline_message.rb | 3 + .../projects/_service_desk_settings.html.haml | 2 + ...and_work_item_associations_unification.yml | 9 + ...ility_findings_remediations_project_id.yml | 9 + .../vulnerability_findings_remediations.yml | 1 + ..._to_vulnerability_findings_remediations.rb | 9 + ...d_default_value_for_ci_pipeline_message.rb | 12 + ...ity_findings_remediations_on_project_id.rb | 16 ++ ...ity_findings_remediations_project_id_fk.rb | 16 ++ ...indings_remediations_project_id_trigger.rb | 25 ++ ...bility_findings_remediations_project_id.rb | 40 +++ db/schema_migrations/20240605080835 | 1 + db/schema_migrations/20240618121517 | 1 + db/schema_migrations/20240618121518 | 1 + db/schema_migrations/20240618121519 | 1 + db/schema_migrations/20240618121520 | 1 + db/schema_migrations/20240618121521 | 1 + db/structure.sql | 28 +- doc/api/graphql/reference/index.md | 65 +++++ doc/api/pipelines.md | 180 +++++++------ doc/api/runners.md | 12 +- .../blueprints/runner_tokens/index.md | 2 +- doc/ci/jobs/job_rules.md | 37 ++- doc/ci/variables/predefined_variables.md | 6 +- doc/development/ai_features/embeddings.md | 78 ++++++ .../vulnerability_report/pipeline.md | 31 +++ doc/user/compliance/audit_event_types.md | 2 + doc/user/project/service_desk/configure.md | 27 ++ doc/user/shortcuts.md | 2 - ...bility_findings_remediations_project_id.rb | 10 + lib/users/internal.rb | 2 +- locale/gitlab.pot | 20 +- package.json | 2 +- spec/controllers/search_controller_spec.rb | 30 +++ spec/frontend/behaviors/gl_emoji_spec.js | 5 +- spec/frontend/emoji/index_spec.js | 81 ++++-- .../components/service_desk_root_spec.js | 6 + .../components/service_desk_setting_spec.js | 84 ++++++ .../design_preview/design_toolbar_spec.js | 8 +- .../components/work_item_detail_spec.js | 15 +- ...y_findings_remediations_project_id_spec.rb | 15 ++ spec/lib/users/internal_spec.rb | 12 +- ...y_findings_remediations_project_id_spec.rb | 33 +++ .../mailers/notify_shared_examples.rb | 9 +- yarn.lock | 248 +++++++++--------- 61 files changed, 1107 insertions(+), 291 deletions(-) create mode 100644 config/feature_flags/wip/epic_and_work_item_associations_unification.yml create mode 100644 db/docs/batched_background_migrations/backfill_vulnerability_findings_remediations_project_id.yml create mode 100644 db/migrate/20240618121517_add_project_id_to_vulnerability_findings_remediations.rb create mode 100644 db/post_migrate/20240605080835_remove_partition_id_default_value_for_ci_pipeline_message.rb create mode 100644 db/post_migrate/20240618121518_index_vulnerability_findings_remediations_on_project_id.rb create mode 100644 db/post_migrate/20240618121519_add_vulnerability_findings_remediations_project_id_fk.rb create mode 100644 db/post_migrate/20240618121520_add_vulnerability_findings_remediations_project_id_trigger.rb create mode 100644 db/post_migrate/20240618121521_queue_backfill_vulnerability_findings_remediations_project_id.rb create mode 100644 db/schema_migrations/20240605080835 create mode 100644 db/schema_migrations/20240618121517 create mode 100644 db/schema_migrations/20240618121518 create mode 100644 db/schema_migrations/20240618121519 create mode 100644 db/schema_migrations/20240618121520 create mode 100644 db/schema_migrations/20240618121521 create mode 100644 doc/development/ai_features/embeddings.md create mode 100644 lib/gitlab/background_migration/backfill_vulnerability_findings_remediations_project_id.rb create mode 100644 spec/lib/gitlab/background_migration/backfill_vulnerability_findings_remediations_project_id_spec.rb create mode 100644 spec/migrations/20240618121521_queue_backfill_vulnerability_findings_remediations_project_id_spec.rb diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index 89b4391d5b1..ff76c43d63b 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -667,6 +667,7 @@ .audit-events-patterns: &audit-events-patterns - "{,ee/}config/audit_events/types/*.yml" - "doc/administration/audit_event_types.md" + - "doc/user/compliance/audit_event_types.md" - "tooling/audit_events/docs/templates/audit_event_types.md.erb" - "lib/tasks/gitlab/audit_event_types/audit_event_types.rake" - "lib/tasks/gitlab/audit_event_types/check_docs_task.rb" diff --git a/GITLAB_ELASTICSEARCH_INDEXER_VERSION b/GITLAB_ELASTICSEARCH_INDEXER_VERSION index 0062ac97180..831446cbd27 100644 --- a/GITLAB_ELASTICSEARCH_INDEXER_VERSION +++ b/GITLAB_ELASTICSEARCH_INDEXER_VERSION @@ -1 +1 @@ -5.0.0 +5.1.0 diff --git a/app/assets/javascripts/emoji/index.js b/app/assets/javascripts/emoji/index.js index 810a2fe9c4e..16eb41f914e 100644 --- a/app/assets/javascripts/emoji/index.js +++ b/app/assets/javascripts/emoji/index.js @@ -77,32 +77,46 @@ async function loadEmojiWithNames() { } export async function loadCustomEmojiWithNames() { - const emojiData = { emojis: {}, names: [] }; + return new Promise((resolve) => { + const emojiData = { emojis: {}, names: [] }; - if (document.body?.dataset?.groupFullPath) { - const client = createApolloClient(); - const { data } = await client.query({ - query: customEmojiQuery, - variables: { - groupPath: document.body.dataset.groupFullPath, - }, - }); + if (document.body?.dataset?.groupFullPath) { + const client = createApolloClient(); + const fetchEmojis = async (after = '') => { + const { data } = await client.query({ + query: customEmojiQuery, + variables: { + groupPath: document.body.dataset.groupFullPath, + after, + }, + }); + const { pageInfo } = data?.group?.customEmoji || {}; - data?.group?.customEmoji?.nodes?.forEach((e) => { - // Map the custom emoji into the format of the normal emojis - emojiData.emojis[e.name] = { - c: 'custom', - d: e.name, - e: undefined, - name: e.name, - src: e.url, - u: 'custom', + data?.group?.customEmoji?.nodes?.forEach((e) => { + // Map the custom emoji into the format of the normal emojis + emojiData.emojis[e.name] = { + c: 'custom', + d: e.name, + e: undefined, + name: e.name, + src: e.url, + u: 'custom', + }; + emojiData.names.push(e.name); + }); + + if (pageInfo?.hasNextPage) { + return fetchEmojis(pageInfo.endCursor); + } + + return resolve(emojiData); }; - emojiData.names.push(e.name); - }); - } - return emojiData; + fetchEmojis(); + } else { + resolve(emojiData); + } + }); } async function prepareEmojiMap() { diff --git a/app/assets/javascripts/emoji/queries/custom_emoji.query.graphql b/app/assets/javascripts/emoji/queries/custom_emoji.query.graphql index ba3911ab091..e90cbda6dec 100644 --- a/app/assets/javascripts/emoji/queries/custom_emoji.query.graphql +++ b/app/assets/javascripts/emoji/queries/custom_emoji.query.graphql @@ -1,7 +1,11 @@ -query getCustomEmoji($groupPath: ID!) { +query getCustomEmoji($groupPath: ID!, $after: String) { group(fullPath: $groupPath) { id - customEmoji(includeAncestorGroups: true) { + customEmoji(after: $after, includeAncestorGroups: true) { + pageInfo { + hasNextPage + endCursor + } nodes { id name diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue index a9dca81b9f4..a870c8fadad 100644 --- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue +++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue @@ -53,6 +53,9 @@ export default { projectKey: { default: '', }, + areTicketsConfidentialByDefault: { + default: false, + }, reopenIssueOnExternalParticipantNote: { default: false, }, @@ -118,6 +121,7 @@ export default { fileTemplateProjectId, outgoingName, projectKey, + areTicketsConfidentialByDefault, reopenIssueOnExternalParticipantNote, addExternalParticipantsFromCc, }) { @@ -127,6 +131,7 @@ export default { issue_template_key: selectedTemplate, outgoing_name: outgoingName, project_key: projectKey, + tickets_confidential_by_default: areTicketsConfidentialByDefault, reopen_issue_on_external_participant_note: reopenIssueOnExternalParticipantNote, add_external_participants_from_cc: addExternalParticipantsFromCc, service_desk_enabled: this.isEnabled, @@ -200,8 +205,10 @@ export default { :initial-selected-file-template-project-id="selectedFileTemplateProjectId" :initial-outgoing-name="outgoingName" :initial-project-key="projectKey" + :initial-are-tickets-confidential-by-default="areTicketsConfidentialByDefault" :initial-reopen-issue-on-external-participant-note="reopenIssueOnExternalParticipantNote" :initial-add-external-participants-from-cc="addExternalParticipantsFromCc" + :public-project="publicProject" :templates="templates" :is-template-saving="isTemplateSaving" @save="onSaveTemplate" diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue index 28dc9759df6..c5fbf66fdf3 100644 --- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue +++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue @@ -20,9 +20,25 @@ import ServiceDeskTemplateDropdown from './service_desk_template_dropdown.vue'; export default { i18n: { toggleLabel: __('Activate Service Desk'), + headlines: { + ticketVisibility: s__('ServiceDesk|Ticket visibility'), + externalParticipants: s__('ServiceDesk|External participants'), + }, issueTrackerEnableMessage: __( 'To use Service Desk in this project, you must %{linkStart}activate the issue tracker%{linkEnd}.', ), + areTicketsConfidentialByDefault: { + label: s__('ServiceDesk|New tickets are confidential by default'), + help: { + publicProject: s__( + 'ServiceDesk|On public projects, tickets are always confidential by default.', + ), + confidential: s__( + 'ServiceDesk|Only project members with at least the Reporter role can view new tickets.', + ), + nonConfidential: s__('ServiceDesk|Any project member can view new tickets.'), + }, + }, reopenIssueOnExternalParticipantNote: { label: s__('ServiceDesk|Reopen issues when an external participant comments'), help: s__( @@ -97,6 +113,11 @@ export default { required: false, default: '', }, + initialAreTicketsConfidentialByDefault: { + type: Boolean, + required: false, + default: true, + }, initialReopenIssueOnExternalParticipantNote: { type: Boolean, required: false, @@ -107,6 +128,11 @@ export default { required: false, default: false, }, + publicProject: { + type: Boolean, + required: false, + default: false, + }, templates: { type: Array, required: false, @@ -124,6 +150,12 @@ export default { selectedFileTemplateProjectId: this.initialSelectedFileTemplateProjectId, outgoingName: this.initialOutgoingName || __('GitLab Support Bot'), projectKey: this.initialProjectKey, + // Tickets will always be confidential for public projects by default. Reflect that also in the frontend + // although the backend setting might be `false`. The value will be persisted on save. + // Refactoring issue: https://gitlab.com/gitlab-org/gitlab/-/issues/467547 + areTicketsConfidentialByDefault: this.publicProject + ? true + : this.initialAreTicketsConfidentialByDefault, reopenIssueOnExternalParticipantNote: this.initialReopenIssueOnExternalParticipantNote, addExternalParticipantsFromCc: this.initialAddExternalParticipantsFromCc, searchTerm: '', @@ -131,6 +163,9 @@ export default { }; }, computed: { + showAreTicketsConfidentialByDefault() { + return this.glFeatures.serviceDeskTicketsConfidentiality; + }, showAddExternalParticipantsFromCC() { return this.glFeatures.issueEmailParticipants; }, @@ -158,6 +193,17 @@ export default { anchor: 'configure-project-visibility-features-and-permissions', }); }, + areTicketsConfidentialByDefaultHelp() { + if (this.publicProject) { + return this.$options.i18n.areTicketsConfidentialByDefault.help.publicProject; + } + + if (this.areTicketsConfidentialByDefault) { + return this.$options.i18n.areTicketsConfidentialByDefault.help.confidential; + } + + return this.$options.i18n.areTicketsConfidentialByDefault.help.nonConfidential; + }, }, methods: { onCheckboxToggle(isChecked) { @@ -168,6 +214,7 @@ export default { selectedTemplate: this.selectedTemplate, outgoingName: this.outgoingName, projectKey: this.projectKey, + areTicketsConfidentialByDefault: this.areTicketsConfidentialByDefault, reopenIssueOnExternalParticipantNote: this.reopenIssueOnExternalParticipantNote, addExternalParticipantsFromCc: this.addExternalParticipantsFromCc, fileTemplateProjectId: this.selectedFileTemplateProjectId, @@ -335,10 +382,32 @@ export default { +
+
{{ $options.i18n.headlines.ticketVisibility }}
+ + + {{ $options.i18n.areTicketsConfidentialByDefault.label }} + + + +
+ +
{{ $options.i18n.headlines.externalParticipants }}
+ {{ $options.i18n.reopenIssueOnExternalParticipantNote.label }} diff --git a/app/assets/javascripts/projects/settings_service_desk/index.js b/app/assets/javascripts/projects/settings_service_desk/index.js index a3c310ec501..7f5fab4efa7 100644 --- a/app/assets/javascripts/projects/settings_service_desk/index.js +++ b/app/assets/javascripts/projects/settings_service_desk/index.js @@ -21,6 +21,7 @@ export default () => { incomingEmail, outgoingName, projectKey, + ticketsConfidentialByDefault, reopenIssueOnExternalParticipantNote, addExternalParticipantsFromCc, selectedTemplate, @@ -41,6 +42,7 @@ export default () => { isIssueTrackerEnabled: parseBoolean(issueTrackerEnabled), outgoingName, projectKey, + areTicketsConfidentialByDefault: parseBoolean(ticketsConfidentialByDefault), reopenIssueOnExternalParticipantNote: parseBoolean(reopenIssueOnExternalParticipantNote), addExternalParticipantsFromCc: parseBoolean(addExternalParticipantsFromCc), selectedTemplate, diff --git a/app/assets/javascripts/work_items/components/design_management/design_preview/design_toolbar.vue b/app/assets/javascripts/work_items/components/design_management/design_preview/design_toolbar.vue index efd134e5176..438d76af4af 100644 --- a/app/assets/javascripts/work_items/components/design_management/design_preview/design_toolbar.vue +++ b/app/assets/javascripts/work_items/components/design_management/design_preview/design_toolbar.vue @@ -8,6 +8,7 @@ import DesignNavigation from './design_navigation.vue'; export default { i18n: { + downloadButtonLabel: s__('DesignManagement|Download design'), hideCommentsButtonLabel: s__('DesignManagement|Hide comments'), showCommentsButtonLabel: s__('DesignManagement|Show comments'), }, @@ -84,6 +85,15 @@ export default {
+
- +
" }.join(',') + # Based on RFC 8058 one-click unsubscribe functionality should + # be signalled with using the List-Unsubscribe-Post header + # See https://datatracker.ietf.org/doc/html/rfc8058 + headers['List-Unsubscribe-Post'] = 'List-Unsubscribe=One-Click' @unsubscribe_url = unsubscribe_sent_notification_url(@sent_notification) end diff --git a/app/models/ci/pipeline_message.rb b/app/models/ci/pipeline_message.rb index fedbc57258d..fa08f21271b 100644 --- a/app/models/ci/pipeline_message.rb +++ b/app/models/ci/pipeline_message.rb @@ -3,6 +3,9 @@ module Ci class PipelineMessage < Ci::ApplicationRecord include Ci::Partitionable + include SafelyChangeColumnDefault + + columns_changing_default :partition_id MAX_CONTENT_LENGTH = 10_000 diff --git a/app/views/projects/_service_desk_settings.html.haml b/app/views/projects/_service_desk_settings.html.haml index d6b28e94645..0dc6be89a63 100644 --- a/app/views/projects/_service_desk_settings.html.haml +++ b/app/views/projects/_service_desk_settings.html.haml @@ -8,6 +8,7 @@ %p.gl-text-secondary= _('Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}.').html_safe % { link_start: link_start, link_end: ''.html_safe } .settings-content - if ::Gitlab::ServiceDesk.supported? + -# Data attributes refactoring issue: https://gitlab.com/gitlab-org/gitlab/-/issues/467547 .js-service-desk-setting-root{ data: { endpoint: project_service_desk_path(@project), enabled: "#{@project.service_desk_enabled}", issue_tracker_enabled: "#{@project.project_feature.issues_enabled?}", @@ -18,6 +19,7 @@ selected_file_template_project_id: "#{@project.service_desk_setting&.file_template_project_id}", outgoing_name: "#{@project.service_desk_setting&.outgoing_name}", project_key: "#{@project.service_desk_setting&.project_key}", + tickets_confidential_by_default: "#{@project.service_desk_setting.nil? ? true : @project.service_desk_setting&.tickets_confidential_by_default}", reopen_issue_on_external_participant_note: "#{@project.service_desk_setting&.reopen_issue_on_external_participant_note}", add_external_participants_from_cc: "#{@project.service_desk_setting&.add_external_participants_from_cc}", templates: available_service_desk_templates_for(@project), diff --git a/config/feature_flags/wip/epic_and_work_item_associations_unification.yml b/config/feature_flags/wip/epic_and_work_item_associations_unification.yml new file mode 100644 index 00000000000..27e12b7b346 --- /dev/null +++ b/config/feature_flags/wip/epic_and_work_item_associations_unification.yml @@ -0,0 +1,9 @@ +--- +name: epic_and_work_item_associations_unification +feature_issue_url: +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/156691 +rollout_issue_url: +milestone: '17.1' +group: group::product planning +type: wip +default_enabled: false diff --git a/db/docs/batched_background_migrations/backfill_vulnerability_findings_remediations_project_id.yml b/db/docs/batched_background_migrations/backfill_vulnerability_findings_remediations_project_id.yml new file mode 100644 index 00000000000..e7f13924555 --- /dev/null +++ b/db/docs/batched_background_migrations/backfill_vulnerability_findings_remediations_project_id.yml @@ -0,0 +1,9 @@ +--- +migration_job_name: BackfillVulnerabilityFindingsRemediationsProjectId +description: Backfills sharding key `vulnerability_findings_remediations.project_id` from `vulnerability_occurrences`. +feature_category: vulnerability_management +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/156634 +milestone: '17.2' +queued_migration_version: 20240618121521 +finalize_after: '2024-08-22' +finalized_by: # version of the migration that finalized this BBM diff --git a/db/docs/vulnerability_findings_remediations.yml b/db/docs/vulnerability_findings_remediations.yml index 051cfd1ba39..2261f35ef47 100644 --- a/db/docs/vulnerability_findings_remediations.yml +++ b/db/docs/vulnerability_findings_remediations.yml @@ -17,3 +17,4 @@ desired_sharding_key: table: vulnerability_occurrences sharding_key: project_id belongs_to: finding +desired_sharding_key_migration_job_name: BackfillVulnerabilityFindingsRemediationsProjectId diff --git a/db/migrate/20240618121517_add_project_id_to_vulnerability_findings_remediations.rb b/db/migrate/20240618121517_add_project_id_to_vulnerability_findings_remediations.rb new file mode 100644 index 00000000000..661e8061109 --- /dev/null +++ b/db/migrate/20240618121517_add_project_id_to_vulnerability_findings_remediations.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddProjectIdToVulnerabilityFindingsRemediations < Gitlab::Database::Migration[2.2] + milestone '17.2' + + def change + add_column :vulnerability_findings_remediations, :project_id, :bigint + end +end diff --git a/db/post_migrate/20240605080835_remove_partition_id_default_value_for_ci_pipeline_message.rb b/db/post_migrate/20240605080835_remove_partition_id_default_value_for_ci_pipeline_message.rb new file mode 100644 index 00000000000..115fbaaba0f --- /dev/null +++ b/db/post_migrate/20240605080835_remove_partition_id_default_value_for_ci_pipeline_message.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class RemovePartitionIdDefaultValueForCiPipelineMessage < Gitlab::Database::Migration[2.2] + milestone '17.2' + + TABLE_NAME = :ci_pipeline_messages + COLUM_NAME = :partition_id + + def change + change_column_default(TABLE_NAME, COLUM_NAME, from: 100, to: nil) + end +end diff --git a/db/post_migrate/20240618121518_index_vulnerability_findings_remediations_on_project_id.rb b/db/post_migrate/20240618121518_index_vulnerability_findings_remediations_on_project_id.rb new file mode 100644 index 00000000000..79e37d4a0bc --- /dev/null +++ b/db/post_migrate/20240618121518_index_vulnerability_findings_remediations_on_project_id.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class IndexVulnerabilityFindingsRemediationsOnProjectId < Gitlab::Database::Migration[2.2] + milestone '17.2' + disable_ddl_transaction! + + INDEX_NAME = 'index_vulnerability_findings_remediations_on_project_id' + + def up + add_concurrent_index :vulnerability_findings_remediations, :project_id, name: INDEX_NAME + end + + def down + remove_concurrent_index_by_name :vulnerability_findings_remediations, INDEX_NAME + end +end diff --git a/db/post_migrate/20240618121519_add_vulnerability_findings_remediations_project_id_fk.rb b/db/post_migrate/20240618121519_add_vulnerability_findings_remediations_project_id_fk.rb new file mode 100644 index 00000000000..65d03e758de --- /dev/null +++ b/db/post_migrate/20240618121519_add_vulnerability_findings_remediations_project_id_fk.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class AddVulnerabilityFindingsRemediationsProjectIdFk < Gitlab::Database::Migration[2.2] + milestone '17.2' + disable_ddl_transaction! + + def up + add_concurrent_foreign_key :vulnerability_findings_remediations, :projects, column: :project_id, on_delete: :cascade + end + + def down + with_lock_retries do + remove_foreign_key :vulnerability_findings_remediations, column: :project_id + end + end +end diff --git a/db/post_migrate/20240618121520_add_vulnerability_findings_remediations_project_id_trigger.rb b/db/post_migrate/20240618121520_add_vulnerability_findings_remediations_project_id_trigger.rb new file mode 100644 index 00000000000..90f705037d7 --- /dev/null +++ b/db/post_migrate/20240618121520_add_vulnerability_findings_remediations_project_id_trigger.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class AddVulnerabilityFindingsRemediationsProjectIdTrigger < Gitlab::Database::Migration[2.2] + milestone '17.2' + + def up + install_sharding_key_assignment_trigger( + table: :vulnerability_findings_remediations, + sharding_key: :project_id, + parent_table: :vulnerability_occurrences, + parent_sharding_key: :project_id, + foreign_key: :vulnerability_occurrence_id + ) + end + + def down + remove_sharding_key_assignment_trigger( + table: :vulnerability_findings_remediations, + sharding_key: :project_id, + parent_table: :vulnerability_occurrences, + parent_sharding_key: :project_id, + foreign_key: :vulnerability_occurrence_id + ) + end +end diff --git a/db/post_migrate/20240618121521_queue_backfill_vulnerability_findings_remediations_project_id.rb b/db/post_migrate/20240618121521_queue_backfill_vulnerability_findings_remediations_project_id.rb new file mode 100644 index 00000000000..4618892c2a3 --- /dev/null +++ b/db/post_migrate/20240618121521_queue_backfill_vulnerability_findings_remediations_project_id.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +class QueueBackfillVulnerabilityFindingsRemediationsProjectId < Gitlab::Database::Migration[2.2] + milestone '17.2' + restrict_gitlab_migration gitlab_schema: :gitlab_main_cell + + MIGRATION = "BackfillVulnerabilityFindingsRemediationsProjectId" + DELAY_INTERVAL = 2.minutes + BATCH_SIZE = 1000 + SUB_BATCH_SIZE = 100 + + def up + queue_batched_background_migration( + MIGRATION, + :vulnerability_findings_remediations, + :id, + :project_id, + :vulnerability_occurrences, + :project_id, + :vulnerability_occurrence_id, + job_interval: DELAY_INTERVAL, + batch_size: BATCH_SIZE, + sub_batch_size: SUB_BATCH_SIZE + ) + end + + def down + delete_batched_background_migration( + MIGRATION, + :vulnerability_findings_remediations, + :id, + [ + :project_id, + :vulnerability_occurrences, + :project_id, + :vulnerability_occurrence_id + ] + ) + end +end diff --git a/db/schema_migrations/20240605080835 b/db/schema_migrations/20240605080835 new file mode 100644 index 00000000000..38225722e94 --- /dev/null +++ b/db/schema_migrations/20240605080835 @@ -0,0 +1 @@ +27c7b399872c197d8238e688fe42c09f8df86964812ea7a4ae59f38bfa018400 \ No newline at end of file diff --git a/db/schema_migrations/20240618121517 b/db/schema_migrations/20240618121517 new file mode 100644 index 00000000000..f14f9edcf2d --- /dev/null +++ b/db/schema_migrations/20240618121517 @@ -0,0 +1 @@ +98d2934a8067678b201fb45a9361f78f45263c3800600e580f7e34ead39ea052 \ No newline at end of file diff --git a/db/schema_migrations/20240618121518 b/db/schema_migrations/20240618121518 new file mode 100644 index 00000000000..2684d002d1b --- /dev/null +++ b/db/schema_migrations/20240618121518 @@ -0,0 +1 @@ +808154ef3dde0e14e82d86702e7e4e807e9b1f9858feef6efdef66f0f47fb3a9 \ No newline at end of file diff --git a/db/schema_migrations/20240618121519 b/db/schema_migrations/20240618121519 new file mode 100644 index 00000000000..6a7de8a51ba --- /dev/null +++ b/db/schema_migrations/20240618121519 @@ -0,0 +1 @@ +8e6fc4e2d1477908ca7995f5f98127d202ed21ae3cbfcb8d7de86c4500fc4797 \ No newline at end of file diff --git a/db/schema_migrations/20240618121520 b/db/schema_migrations/20240618121520 new file mode 100644 index 00000000000..d3bee58840c --- /dev/null +++ b/db/schema_migrations/20240618121520 @@ -0,0 +1 @@ +0a9dce38fe804d84fa7ac6c1d65bdff5ac6c88e3df57a0812ccd291dfd2c147a \ No newline at end of file diff --git a/db/schema_migrations/20240618121521 b/db/schema_migrations/20240618121521 new file mode 100644 index 00000000000..543123b71fd --- /dev/null +++ b/db/schema_migrations/20240618121521 @@ -0,0 +1 @@ +47c824811fde371acee3547b45cceb29157c1a5a9339df22348935d89c457933 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 8cdf92d7b94..aee35efca00 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1313,6 +1313,22 @@ RETURN NEW; END $$; +CREATE FUNCTION trigger_9e137c16de79() RETURNS trigger + LANGUAGE plpgsql + AS $$ +BEGIN +IF NEW."project_id" IS NULL THEN + SELECT "project_id" + INTO NEW."project_id" + FROM "vulnerability_occurrences" + WHERE "vulnerability_occurrences"."id" = NEW."vulnerability_occurrence_id"; +END IF; + +RETURN NEW; + +END +$$; + CREATE FUNCTION trigger_a1bc7c70cbdf() RETURNS trigger LANGUAGE plpgsql AS $$ @@ -7601,7 +7617,7 @@ CREATE TABLE ci_pipeline_messages ( severity smallint DEFAULT 0 NOT NULL, content text NOT NULL, pipeline_id bigint NOT NULL, - partition_id bigint DEFAULT 100 NOT NULL, + partition_id bigint NOT NULL, CONSTRAINT check_58ca2981b2 CHECK ((char_length(content) <= 10000)) ); @@ -18661,7 +18677,8 @@ CREATE TABLE vulnerability_findings_remediations ( vulnerability_occurrence_id bigint, vulnerability_remediation_id bigint, created_at timestamp with time zone NOT NULL, - updated_at timestamp with time zone NOT NULL + updated_at timestamp with time zone NOT NULL, + project_id bigint ); CREATE SEQUENCE vulnerability_findings_remediations_id_seq @@ -29060,6 +29077,8 @@ CREATE INDEX index_vulnerability_finding_signatures_on_finding_id ON vulnerabili CREATE INDEX index_vulnerability_finding_signatures_on_signature_sha ON vulnerability_finding_signatures USING btree (signature_sha); +CREATE INDEX index_vulnerability_findings_remediations_on_project_id ON vulnerability_findings_remediations USING btree (project_id); + CREATE INDEX index_vulnerability_findings_remediations_on_remediation_id ON vulnerability_findings_remediations USING btree (vulnerability_remediation_id); CREATE UNIQUE INDEX index_vulnerability_findings_remediations_on_unique_keys ON vulnerability_findings_remediations USING btree (vulnerability_occurrence_id, vulnerability_remediation_id); @@ -31194,6 +31213,8 @@ CREATE TRIGGER trigger_96a76ee9f147 BEFORE INSERT OR UPDATE ON design_management CREATE TRIGGER trigger_98ad3a4c1d35 BEFORE INSERT OR UPDATE ON merge_request_review_llm_summaries FOR EACH ROW EXECUTE FUNCTION trigger_98ad3a4c1d35(); +CREATE TRIGGER trigger_9e137c16de79 BEFORE INSERT OR UPDATE ON vulnerability_findings_remediations FOR EACH ROW EXECUTE FUNCTION trigger_9e137c16de79(); + CREATE TRIGGER trigger_a1bc7c70cbdf BEFORE INSERT OR UPDATE ON vulnerability_user_mentions FOR EACH ROW EXECUTE FUNCTION trigger_a1bc7c70cbdf(); CREATE TRIGGER trigger_a253cb3cacdf BEFORE INSERT OR UPDATE ON dora_daily_metrics FOR EACH ROW EXECUTE FUNCTION trigger_a253cb3cacdf(); @@ -31984,6 +32005,9 @@ ALTER TABLE p_ci_builds ALTER TABLE ONLY approval_group_rules_users ADD CONSTRAINT fk_888a0df3b7 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; +ALTER TABLE ONLY vulnerability_findings_remediations + ADD CONSTRAINT fk_88a2923914 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; + ALTER TABLE ONLY bulk_import_entities ADD CONSTRAINT fk_88c725229f FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE; diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 4d797154fcb..313d0416d31 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -2018,6 +2018,52 @@ Input type: `AuditEventsInstanceDestinationEventsDeleteInput` | `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | | `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | +### `Mutation.auditEventsInstanceDestinationNamespaceFilterCreate` + +DETAILS: +**Introduced** in GitLab 17.2. +**Status**: Experiment. + +Input type: `AuditEventsInstanceDestinationNamespaceFilterCreateInput` + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `destinationId` | [`AuditEventsInstanceExternalStreamingDestinationID!`](#auditeventsinstanceexternalstreamingdestinationid) | Destination ID. | +| `namespacePath` | [`String`](#string) | Full path of the namespace. Project or group namespaces only. | + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | +| `namespaceFilter` | [`InstanceAuditEventNamespaceFilter`](#instanceauditeventnamespacefilter) | Namespace filter to be created. | + +### `Mutation.auditEventsInstanceDestinationNamespaceFilterDelete` + +DETAILS: +**Introduced** in GitLab 17.2. +**Status**: Experiment. + +Input type: `AuditEventsInstanceDestinationNamespaceFilterDeleteInput` + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `namespaceFilterId` | [`AuditEventsInstanceNamespaceFilterID!`](#auditeventsinstancenamespacefilterid) | Namespace filter ID. | + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | + ### `Mutation.auditEventsStreamingDestinationEventsAdd` Input type: `AuditEventsStreamingDestinationEventsAddInput` @@ -23392,6 +23438,18 @@ Stores instance level Amazon S3 configurations for audit event streaming. | `id` | [`ID!`](#id) | ID of the configuration. | | `name` | [`String!`](#string) | Name of the external destination to send audit events to. | +### `InstanceAuditEventNamespaceFilter` + +Represents a subgroup or project filter that belongs to an instance level external audit event streaming destination. + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `externalStreamingDestination` | [`InstanceAuditEventStreamingDestination!`](#instanceauditeventstreamingdestination) | Destination to which the filter belongs. | +| `id` | [`ID!`](#id) | ID of the filter. | +| `namespace` | [`Namespace!`](#namespace) | Group or project namespace the filter belongs to. | + ### `InstanceAuditEventStreamingDestination` Represents an external destination to stream instance level audit events. @@ -23405,6 +23463,7 @@ Represents an external destination to stream instance level audit events. | `eventTypeFilters` | [`[String!]!`](#string) | List of event type filters added for streaming. | | `id` | [`ID!`](#id) | ID of the destination. | | `name` | [`String!`](#string) | Name of the external destination to send audit events to. | +| `namespaceFilters` | [`[InstanceAuditEventNamespaceFilter!]`](#instanceauditeventnamespacefilter) | List of subgroup or project filters for the destination. | ### `InstanceExternalAuditEventDestination` @@ -36280,6 +36339,12 @@ A `AuditEventsInstanceGoogleCloudLoggingConfigurationID` is a global ID. It is e An example `AuditEventsInstanceGoogleCloudLoggingConfigurationID` is: `"gid://gitlab/AuditEvents::Instance::GoogleCloudLoggingConfiguration/1"`. +### `AuditEventsInstanceNamespaceFilterID` + +A `AuditEventsInstanceNamespaceFilterID` is a global ID. It is encoded as a string. + +An example `AuditEventsInstanceNamespaceFilterID` is: `"gid://gitlab/AuditEvents::Instance::NamespaceFilter/1"`. + ### `AuditEventsStreamingHTTPNamespaceFilterID` A `AuditEventsStreamingHTTPNamespaceFilterID` is a global ID. It is encoded as a string. diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md index 6c204813bbb..e9ad5520f19 100644 --- a/doc/api/pipelines.md +++ b/doc/api/pipelines.md @@ -44,7 +44,7 @@ GET /projects/:id/pipelines | `scope` | string | No | The scope of pipelines, one of: `running`, `pending`, `finished`, `branches`, `tags` | | `sha` | string | No | The SHA of pipelines | | `sort` | string | No | Sort pipelines in `asc` or `desc` order (default: `desc`) | -| `source` | string | No | Returns how the pipeline was triggered, one of: `api`, `chat`, `external`, `external_pull_request_event`, `merge_request_event`, `ondemand_dast_scan`, `ondemand_dast_validation`, `parent_pipeline`, `pipeline`, `push`, `schedule`, `security_orchestration_policy`, `trigger`, `web`, or `webide`. | +| `source` | string | No | The [pipeline source](../ci/jobs/job_rules.md#ci_pipeline_source-predefined-variable). | | `status` | string | No | The status of pipelines, one of: `created`, `waiting_for_resource`, `preparing`, `pending`, `running`, `success`, `failed`, `canceled`, `skipped`, `manual`, `scheduled` | | `updated_after` | datetime | No | Return pipelines updated after the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | | `updated_before` | datetime | No | Return pipelines updated before the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | @@ -115,33 +115,110 @@ Example of response ```json { - "id": 46, - "iid": 11, - "project_id": 1, + "id": 287, + "iid": 144, + "project_id": 21, "name": "Build pipeline", - "status": "success", + "sha": "50f0acb76a40e34a4ff304f7347dcc6587da8a14", "ref": "main", - "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", - "before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", + "status": "success", + "source": "push", + "created_at": "2022-09-21T01:05:07.200Z", + "updated_at": "2022-09-21T01:05:50.185Z", + "web_url": "http://127.0.0.1:3000/test-group/test-project/-/pipelines/287", + "before_sha": "8a24fb3c5877a6d0b611ca41fc86edc174593e2b", "tag": false, "yaml_errors": null, "user": { - "name": "Administrator", - "username": "root", "id": 1, + "username": "root", + "name": "Administrator", "state": "active", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", - "web_url": "http://localhost:3000/root" + "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "http://127.0.0.1:3000/root" }, - "created_at": "2016-08-11T11:28:34.085Z", - "updated_at": "2016-08-11T11:32:35.169Z", - "started_at": null, - "finished_at": "2016-08-11T11:32:35.145Z", + "started_at": "2022-09-21T01:05:14.197Z", + "finished_at": "2022-09-21T01:05:50.175Z", "committed_at": null, - "duration": 123.65, - "queued_duration": 0.010, - "coverage": "30.0", - "web_url": "https://example.com/foo/bar/pipelines/46" + "duration": 34, + "queued_duration": 6, + "coverage": null, + "detailed_status": { + "icon": "status_success", + "text": "passed", + "label": "passed", + "group": "success", + "tooltip": "passed", + "has_details": false, + "details_path": "/test-group/test-project/-/pipelines/287", + "illustration": null, + "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png" + } +} +``` + +### Get the latest pipeline + +> - `name` in response [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115310) in GitLab 15.11 [with a flag](../administration/feature_flags.md) named `pipeline_name_in_api`. Disabled by default. +> - `name` in response [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/398131) in GitLab 16.3. Feature flag `pipeline_name_in_api` removed. + +Get the latest pipeline for the most recent commit on a specific ref in a project. If no pipeline exists for the commit, a `403` status code is returned. + +```plaintext +GET /projects/:id/pipelines/latest +``` + +| Attribute | Type | Required | Description | +|-----------|--------|----------|-------------| +| `ref` | string | No | The branch or tag to check for the latest pipeline. Defaults to the default branch when not specified. | + +```shell +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/latest" +``` + +Example of response + +```json +{ + "id": 287, + "iid": 144, + "project_id": 21, + "name": "Build pipeline", + "sha": "50f0acb76a40e34a4ff304f7347dcc6587da8a14", + "ref": "main", + "status": "success", + "source": "push", + "created_at": "2022-09-21T01:05:07.200Z", + "updated_at": "2022-09-21T01:05:50.185Z", + "web_url": "http://127.0.0.1:3000/test-group/test-project/-/pipelines/287", + "before_sha": "8a24fb3c5877a6d0b611ca41fc86edc174593e2b", + "tag": false, + "yaml_errors": null, + "user": { + "id": 1, + "username": "root", + "name": "Administrator", + "state": "active", + "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "http://127.0.0.1:3000/root" + }, + "started_at": "2022-09-21T01:05:14.197Z", + "finished_at": "2022-09-21T01:05:50.175Z", + "committed_at": null, + "duration": 34, + "queued_duration": 6, + "coverage": null, + "detailed_status": { + "icon": "status_success", + "text": "passed", + "label": "passed", + "group": "success", + "tooltip": "passed", + "has_details": false, + "details_path": "/test-group/test-project/-/pipelines/287", + "illustration": null, + "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png" + } } ``` @@ -281,71 +358,6 @@ Sample response: } ``` -## Get the latest pipeline - -> - `name` in response [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115310) in GitLab 15.11 [with a flag](../administration/feature_flags.md) named `pipeline_name_in_api`. Disabled by default. -> - `name` in response [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/398131) in GitLab 16.3. Feature flag `pipeline_name_in_api` removed. - -Get the latest pipeline for the most recent commit on a specific ref in a project. If no pipeline exists for the commit, a `403` status code is returned. - -```plaintext -GET /projects/:id/pipelines/latest -``` - -| Attribute | Type | Required | Description | -|-----------|--------|----------|-------------| -| `ref` | string | No | The branch or tag to check for the latest pipeline. Defaults to the default branch when not specified. | - -```shell -curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipelines/latest" -``` - -Example of response - -```json -{ - "id": 287, - "iid": 144, - "project_id": 21, - "name": "Build pipeline", - "sha": "50f0acb76a40e34a4ff304f7347dcc6587da8a14", - "ref": "main", - "status": "success", - "source": "push", - "created_at": "2022-09-21T01:05:07.200Z", - "updated_at": "2022-09-21T01:05:50.185Z", - "web_url": "http://127.0.0.1:3000/test-group/test-project/-/pipelines/287", - "before_sha": "8a24fb3c5877a6d0b611ca41fc86edc174593e2b", - "tag": false, - "yaml_errors": null, - "user": { - "id": 1, - "username": "root", - "name": "Administrator", - "state": "active", - "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", - "web_url": "http://127.0.0.1:3000/root" - }, - "started_at": "2022-09-21T01:05:14.197Z", - "finished_at": "2022-09-21T01:05:50.175Z", - "committed_at": null, - "duration": 34, - "queued_duration": 6, - "coverage": null, - "detailed_status": { - "icon": "status_success", - "text": "passed", - "label": "passed", - "group": "success", - "tooltip": "passed", - "has_details": false, - "details_path": "/test-group/test-project/-/pipelines/287", - "illustration": null, - "favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png" - } -} -``` - ## Create a new pipeline > - `iid` in response [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/342223) in GitLab 14.6. diff --git a/doc/api/runners.md b/doc/api/runners.md index a8d91dee956..7667f4f69bb 100644 --- a/doc/api/runners.md +++ b/doc/api/runners.md @@ -29,7 +29,7 @@ There are two tokens to take into account when connecting a runner with GitLab. | Token | Description | | ----- | ----------- | | Registration token | Token used to [register the runner](https://docs.gitlab.com/runner/register/). It can be [obtained through GitLab](../ci/runners/index.md). | -| Authentication token | Token used to authenticate the runner with the GitLab instance. It is obtained automatically when you [register a runner](https://docs.gitlab.com/runner/register/) or by the Runner API when you manually [register a runner](#create-an-instance-runner) or [reset the authentication token](#reset-runners-authentication-token-by-using-the-runner-id). You can also obtain the authentication token using [Create a runner](users.md#create-a-runner-linked-to-a-user) API method. | +| Authentication token | Token used to authenticate the runner with the GitLab instance. The token is obtained automatically when you [register a runner](https://docs.gitlab.com/runner/register/) or by the Runners API when you manually [register a runner](#create-a-runner) or [reset the authentication token](#reset-runners-authentication-token-by-using-the-runner-id). You can also obtain the token by using the [`POST /user/runners`](users.md#create-a-runner-linked-to-a-user) endpoint. | Here's an example of how the two tokens are used in runner registration: @@ -776,9 +776,15 @@ Example response: ] ``` -## Create an instance runner +## Create a runner -Create a runner for the instance. +WARNING: +This endpoint returns an `HTTP 410 Gone` status code if registration with runner registration tokens +is disabled in the project or group settings. If registration with runner registration tokens +is disabled, use the [`POST /user/runners`](users.md#create-a-runner-linked-to-a-user) endpoint +to create and register runners instead. + +Create a runner with a runner registration token. ```plaintext POST /runners diff --git a/doc/architecture/blueprints/runner_tokens/index.md b/doc/architecture/blueprints/runner_tokens/index.md index ea9adb691f2..d078b5babbb 100644 --- a/doc/architecture/blueprints/runner_tokens/index.md +++ b/doc/architecture/blueprints/runner_tokens/index.md @@ -419,7 +419,7 @@ scope. | Component | Milestone | Changes | |------------------|----------:|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | GitLab Rails app | `%16.0` | Adapt `register_{group|project}_runner` permissions to take [application setting](https://gitlab.com/gitlab-org/gitlab/-/issues/386712) in consideration. | -| GitLab Rails app | `%16.1` | Make [`POST /api/v4/runners` endpoint](../../../api/runners.md#create-an-instance-runner) permanently return `HTTP 410 Gone` if either `allow_runner_registration_token` setting disables registration tokens.
A future v5 version of the API should return `HTTP 404 Not Found`. | +| GitLab Rails app | `%16.1` | Make the [`POST /api/v4/runners`](../../../api/runners.md#create-a-runner) endpoint return `HTTP 410 Gone` permanently if either `allow_runner_registration_token` setting disables registration tokens. The Runners API v5 should return `HTTP 404 Not Found`. | | GitLab Rails app | `%16.1` | Add runner group metadata to the runner list. | | GitLab Rails app | `%16.11` | Add UI to allow disabling use of registration tokens in top-level group settings. | | GitLab Rails app | `%16.11` | Add UI to allow disabling use of registration tokens in admin panel. | diff --git a/doc/ci/jobs/job_rules.md b/doc/ci/jobs/job_rules.md index 1d97b5d20f4..3628236236f 100644 --- a/doc/ci/jobs/job_rules.md +++ b/doc/ci/jobs/job_rules.md @@ -139,7 +139,8 @@ You can use the `$` character for both variables and paths. For example, if the ## Common `if` clauses with predefined variables -`rules:if` clauses are commonly used with [predefined CI/CD variables](../variables/predefined_variables.md). +`rules:if` clauses are commonly used with [predefined CI/CD variables](../variables/predefined_variables.md), +especially the [`CI_PIPELINE_SOURCE` predefined variable](#ci_pipeline_source-predefined-variable). The following example runs the job as a manual job in scheduled pipelines or in push pipelines (to branches or tags), with `when: on_success` (default). It does not @@ -178,18 +179,13 @@ Other commonly used `if` clauses: - `if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_TITLE =~ /Merge branch.*/`: If the commit branch is the default branch and the commit message title matches a regular expression. For example, the default commit message for a merge commit starts with `Merge branch`. - - `if: $CUSTOM_VARIABLE == "value1"`: If the custom variable `CUSTOM_VARIABLE` is exactly `value1`. ### Run jobs only in specific pipeline types -You can use [predefined CI/CD variables](../variables/predefined_variables.md) to choose -which pipeline types jobs run in, with: - -- [`rules`](../yaml/index.md#rules) -- [`only:variables`](../yaml/index.md#onlyvariables--exceptvariables) -- [`except:variables`](../yaml/index.md#onlyvariables--exceptvariables) +You can use [predefined CI/CD variables](../variables/predefined_variables.md) with +[`rules`](../yaml/index.md#rules) to choose which pipeline types jobs should run for. The following table lists some of the variables that you can use, and the pipeline types the variables can control for: @@ -224,6 +220,31 @@ job1: when: never ``` +### `CI_PIPELINE_SOURCE` predefined variable + +Use the `CI_PIPELINE_SOURCE` variable to control when to add jobs for these pipeline types: + +| Value | Description | +|---------------------------------|-------------| +| `api` | For pipelines triggered by the [pipelines API](../../api/pipelines.md#create-a-new-pipeline). | +| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/index.md) command. | +| `external` | When you use CI services other than GitLab. | +| `external_pull_request_event` | When an [external pull request on GitHub](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests) is created or updated. | +| `merge_request_event` | For pipelines created when a merge request is created or updated. Required to enable [merge request pipelines](../pipelines/merge_request_pipelines.md), [merged results pipelines](../pipelines/merged_results_pipelines.md), and [merge trains](../pipelines/merge_trains.md). | +| `ondemand_dast_scan` | For [DAST on-demand scan](../../user/application_security/dast/on-demand_scan.md) pipelines. | +| `ondemand_dast_validation` | For [DAST on-demand validation](../../user/application_security/dast/on-demand_scan.md#site-profile-validation) pipelines | +| `parent_pipeline` | For pipelines triggered by a [parent/child pipeline](../pipelines/downstream_pipelines.md#parent-child-pipelines). Use this pipeline source in the child pipeline configuration so that it can be triggered by the parent pipeline. | +| `pipeline` | For [multi-project pipelines](../pipelines/downstream_pipelines.md#multi-project-pipelines) created by [using the API with `CI_JOB_TOKEN`](../pipelines/downstream_pipelines.md#trigger-a-multi-project-pipeline-by-using-the-api), or the [`trigger`](../yaml/index.md#trigger) keyword. | +| `push` | For pipelines triggered by a Git push event, including for branches and tags. | +| `schedule` | For [scheduled pipelines](../pipelines/schedules.md). | +| `security_orchestration_policy` | For [security orchestration policy](../../user/application_security/policies/index.md) pipelines. | +| `trigger` | For pipelines created by using a [trigger token](../triggers/index.md#configure-cicd-jobs-to-run-in-triggered-pipelines). | +| `web` | For pipelines created by selecting **Run pipeline** in the GitLab UI, from the project's **Build > Pipelines** section. | +| `webide` | For pipelines created by using the [WebIDE](../../user/project/web_ide/index.md). | + +These values are the same as returned for the `source` parameter when using the +[pipelines API endpoint](../../api/pipelines.md#list-project-pipelines). + ## Complex rules You can use all `rules` keywords, like `if`, `changes`, and `exists`, in the same diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md index 7624d04dd81..e85a346053b 100644 --- a/doc/ci/variables/predefined_variables.md +++ b/doc/ci/variables/predefined_variables.md @@ -71,7 +71,6 @@ as it can cause the pipeline to behave unexpectedly. | `CI_ENVIRONMENT_URL` | Pipeline | 9.3 | all | The URL of the environment for this job. Available if [`environment:url`](../yaml/index.md#environmenturl) is set. | | `CI_ENVIRONMENT_ACTION` | Pipeline | 13.11 | all | The action annotation specified for this job's environment. Available if [`environment:action`](../yaml/index.md#environmentaction) is set. Can be `start`, `prepare`, or `stop`. | | `CI_ENVIRONMENT_TIER` | Pipeline | 14.0 | all | The [deployment tier of the environment](../environments/index.md#deployment-tier-of-environments) for this job. | -| `CI_RELEASE_DESCRIPTION` | Pipeline | 15.5 | all | The description of the release. Available only on pipelines for tags. Description length is limited to first 1024 characters. | | `CI_GITLAB_FIPS_MODE` | Pipeline | 14.10 | all | Only available if [FIPS mode](../../development/fips_compliance.md) is enabled in the GitLab instance. `true` when available. | | `CI_HAS_OPEN_REQUIREMENTS` | Pipeline | 13.1 | all | Only available if the pipeline's project has an open [requirement](../../user/project/requirements/index.md). `true` when available. | | `CI_JOB_ID` | Jobs only | 9.0 | all | The internal ID of the job, unique across all jobs in the GitLab instance. | @@ -96,9 +95,8 @@ as it can cause the pipeline to behave unexpectedly. | `CI_PAGES_URL` | Pipeline | 11.8 | all | The URL for a GitLab Pages site. Always a subdomain of `CI_PAGES_DOMAIN`. | | `CI_PIPELINE_ID` | Jobs only | 8.10 | all | The instance-level ID of the current pipeline. This ID is unique across all projects on the GitLab instance. | | `CI_PIPELINE_IID` | Pipeline | 11.0 | all | The project-level IID (internal ID) of the current pipeline. This ID is unique only within the current project. | -| `CI_PIPELINE_SOURCE` | Pipeline | 10.0 | all | How the pipeline was triggered. Can be `push`, `web`, `schedule`, `api`, `external`, `chat`, `webide`, `merge_request_event`, `external_pull_request_event`, `parent_pipeline`, [`trigger`, or `pipeline`](../triggers/index.md#configure-cicd-jobs-to-run-in-triggered-pipelines). For a description of each value, see [Common `if` clauses for `rules`](../jobs/job_rules.md#common-if-clauses-with-predefined-variables), which uses this variable to control when jobs run. | +| `CI_PIPELINE_SOURCE` | Pipeline | 10.0 | all | How the pipeline was triggered. The value can be one of the [pipeline sources](../jobs/job_rules.md#ci_pipeline_source-predefined-variable). | | `CI_PIPELINE_TRIGGERED` | Pipeline | all | all | `true` if the job was [triggered](../triggers/index.md). | -| `CI_TRIGGER_SHORT_TOKEN` | Jobs only | 17.0 | all | First 4 characters of the [trigger token](../triggers/index.md#create-a-pipeline-trigger-token) of the current job. Only available if the pipeline was [triggered with a trigger token](../triggers/index.md). For example, for a trigger token of `glptt-dbf556605bcad4d9db3ec5fcef84f78f9b4fec28`, `CI_TRIGGER_SHORT_TOKEN` would be `dbf5`. | | `CI_PIPELINE_URL` | Jobs only | 11.1 | 0.5 | The URL for the pipeline details. | | `CI_PIPELINE_CREATED_AT` | Pipeline | 13.10 | all | The date and time when the pipeline was created, in [ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A) format. For example, `2022-01-31T16:47:55Z`. [UTC by default](../../administration/timezone.md). | | `CI_PIPELINE_NAME` | Pipeline | 16.3 | all | The pipeline name defined in [`workflow:name`](../yaml/index.md#workflowname) | @@ -120,6 +118,7 @@ as it can cause the pipeline to behave unexpectedly. | `CI_REGISTRY_IMAGE` | Pipeline | 8.10 | 0.5 | Base address for the container registry to push, pull, or tag project's images, formatted as `[:]/`. For example: `registry.gitlab.example.com/my_group/my_project`. Image names must follow the [container registry naming convention](../../user/packages/container_registry/index.md#naming-convention-for-your-container-images). Only available if the container registry is enabled for the project. | | `CI_REGISTRY_PASSWORD` | Jobs only | 9.0 | all | The password to push containers to the GitLab project's container registry. Only available if the container registry is enabled for the project. This password value is the same as the `CI_JOB_TOKEN` and is valid only as long as the job is running. Use the `CI_DEPLOY_PASSWORD` for long-lived access to the registry | | `CI_REGISTRY_USER` | Jobs only | 9.0 | all | The username to push containers to the project's GitLab container registry. Only available if the container registry is enabled for the project. | +| `CI_RELEASE_DESCRIPTION` | Pipeline | 15.5 | all | The description of the release. Available only on pipelines for tags. Description length is limited to first 1024 characters. | | `CI_REPOSITORY_URL` | Jobs only | 9.0 | all | The full path to Git clone (HTTP) the repository with a [CI/CD job token](../jobs/ci_job_token.md), in the format `https://gitlab-ci-token:$CI_JOB_TOKEN@gitlab.example.com/my-group/my-project.git`. | | `CI_RUNNER_DESCRIPTION` | Jobs only | 8.10 | 0.5 | The description of the runner. | | `CI_RUNNER_EXECUTABLE_ARCH` | Jobs only | all | 10.6 | The OS/architecture of the GitLab Runner executable. Might not be the same as the environment of the executor. | @@ -147,6 +146,7 @@ as it can cause the pipeline to behave unexpectedly. | `CI_SERVER` | Jobs only | all | all | Available for all jobs executed in CI/CD. `yes` when available. | | `CI_SHARED_ENVIRONMENT` | Pipeline | all | 10.1 | Only available if the job is executed in a shared environment (something that is persisted across CI/CD invocations, like the `shell` or `ssh` executor). `true` when available. | | `CI_TEMPLATE_REGISTRY_HOST` | Pipeline | 15.3 | all | The host of the registry used by CI/CD templates. Defaults to `registry.gitlab.com`. | +| `CI_TRIGGER_SHORT_TOKEN` | Jobs only | 17.0 | all | First 4 characters of the [trigger token](../triggers/index.md#create-a-pipeline-trigger-token) of the current job. Only available if the pipeline was [triggered with a trigger token](../triggers/index.md). For example, for a trigger token of `glptt-dbf556605bcad4d9db3ec5fcef84f78f9b4fec28`, `CI_TRIGGER_SHORT_TOKEN` would be `dbf5`. | | `GITLAB_CI` | Pipeline | all | all | Available for all jobs executed in CI/CD. `true` when available. | | `GITLAB_FEATURES` | Pipeline | 10.6 | all | The comma-separated list of licensed features available for the GitLab instance and license. | | `GITLAB_USER_EMAIL` | Pipeline | 8.12 | all | The email of the user who started the pipeline, unless the job is a manual job. In manual jobs, the value is the email of the user who started the job. | diff --git a/doc/development/ai_features/embeddings.md b/doc/development/ai_features/embeddings.md new file mode 100644 index 00000000000..7da6565a444 --- /dev/null +++ b/doc/development/ai_features/embeddings.md @@ -0,0 +1,78 @@ +--- +stage: Data Stores +group: Global Search +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. +--- + +# Embeddings + +Embeddings are a way of representing data in a vectorised format, making it easy and efficient to find similar documents. + +Currently embeddings are only generated for issues which allows for features such as + +- [Issue search](https://gitlab.com/gitlab-org/gitlab/-/issues/440424) +- [Find similar issues](https://gitlab.com/gitlab-org/gitlab/-/issues/407385) +- [Find duplicate issues](https://gitlab.com/gitlab-org/gitlab/-/issues/407385) +- [Find similar/related issues for Zendesk tickets](https://gitlab.com/gitlab-org/gitlab/-/issues/411847) +- [Auto-Categorize Service Desk issues](https://gitlab.com/gitlab-org/gitlab/-/issues/409646) + +## Architecture + +Embeddings are stored in Elasticsearch which is also used for [Advanced Search](../advanced_search.md). + +```mermaid +graph LR + A[database record] --> B[ActiveRecord callback] + B --> C[build embedding reference] + C -->|add to queue| N[queue] + E[cron worker every minute] <-->|pull from queue| N + E --> G[deserialize reference] + G --> H[generate embedding] + H <--> I[AI Gateway] + I <--> J[Vertex API] + H --> K[upsert document with embedding] + K --> L[Elasticsearch] +``` + +The process is driven by `Search::Elastic::ProcessEmbeddingBookkeepingService` which adds and pulls from a Redis queue. + +### Adding to the embedding queue + +The following process description uses issues as an example. + +An issue embedding is generated from the content `"issue with title '#{issue.title}' and description '#{issue.description}'"`. + +Using ActiveRecord callbacks defined in [`Search::Elastic::IssuesSearch`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/models/concerns/search/elastic/issues_search.rb), an [embedding reference](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/search/elastic/references/embedding.rb) is added to the embedding queue if it is created or if the title or description is updated and if [embedding generation is available](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/models/concerns/search/elastic/issues_search.rb#L38-47) for the issue. + +### Pulling from the embedding queue + +A `Search::ElasticIndexEmbeddingBulkCronWorker` cron worker runs every minute and does the following: + +```mermaid +graph LR + A[cron] --> B{endpoint throttled?} + B -->|no| C[schedule 16 workers] + C ..->|each worker| D{endpoint throttled?} + D -->|no| E[fetch 19 references from queue] + E ..->|each reference| F[increment endpoint] + F --> G{endpoint throttled?} + G -->|no| H[call AI Gateway to generate embedding] +``` + +Therefore we always make sure that we don't exceed the rate limit setting of 450 embeddings per minute even with 16 concurrent processes generating embeddings at the same time. + +### Backfilling + +An [Advanced Search migration](../search/advanced_search_migration_styleguide.md) is used to perform the backfill. It essentially adds references to the queue in batches which are then processed by the cron worker as described above. + +## Adding a new embedding type + +The following process outlines the steps to get embeddings generated and stored in Elasticsearch. + +1. Do a cost and resource calculation to see if the Elasticsearch cluster can handle embedding generation or if it needs additional resources. +1. Decide where to store embeddings. Look at the [existing indices in Elasticsearch](../../integration/advanced_search/elasticsearch.md#advanced-search-index-scopes) and if there isn't a suitable existing index, [create a new index](../advanced_search.md#add-a-new-document-type-to-elasticsearch). +1. Add embedding fields to the index: [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/149209). +1. Update the way [content](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/search/elastic/references/embedding.rb#L75-77) is generated to accommodate the new type. +1. Add a new unit primitive: [here](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/-/merge_requests/918) and [here](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/155835). +1. Use `Elastic::ApplicationVersionedSearch` to access callbacks and add the necessary checks for when to generate embeddings. See [`Search::Elastic::IssuesSearch`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/models/concerns/search/elastic/issues_search.rb) for an example. +1. Backfill embeddings: [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154940). diff --git a/doc/user/application_security/vulnerability_report/pipeline.md b/doc/user/application_security/vulnerability_report/pipeline.md index 64b85b627fb..34148ef4c9b 100644 --- a/doc/user/application_security/vulnerability_report/pipeline.md +++ b/doc/user/application_security/vulnerability_report/pipeline.md @@ -210,5 +210,36 @@ For instance, for `container_scanning` type the location is defined by Docker im ## Troubleshooting +### Dismissed vulnerabilities are sometimes still visible + In some instances of GitLab 16.8 and earlier [dismissed vulnerabilities are sometimes still visible](https://gitlab.com/gitlab-org/gitlab/-/issues/367298). This can be resolved by upgrading to GitLab 16.9 and later. + +### Report parsing and scan ingestion errors + +NOTE: +These steps are to be used by GitLab Support to reproduce such errors. + +Some security scans may result in errors in the **Security** tab of the pipeline related to report parsing or scan ingestion. If it is not possible to get a copy of the project from the user, you can reproduce the error using the report generated from the scan. + +To recreate the error: + +1. Obtain a copy of the report from the user. In this example, `gl-sast-report.json`. +1. Create a project. +1. Commit the report to the repository. +1. Add your `.gitlab-ci.yml` file and have the report as an artifact in a job. + + For example, to reproduce an error caused by a SAST job: + + ```yaml + sample-job: + script: + - echo "Testing report" + artifacts: + reports: + sast: gl-sast-report.json + ``` + +1. After the pipeline completes, check the content of the pipeline's **Security** tab for errors. + +You can replace `sast: gl-sast-report.json` with the respective [`artifacts:reports`](../../../ci/yaml/index.md#artifactsreports) type and the correct JSON report filename depending on the scan that generated the report. diff --git a/doc/user/compliance/audit_event_types.md b/doc/user/compliance/audit_event_types.md index 71fd37d2194..50bd2e0b703 100644 --- a/doc/user/compliance/audit_event_types.md +++ b/doc/user/compliance/audit_event_types.md @@ -68,10 +68,12 @@ Audit event types belong to the following product categories. | [`created_group_audit_event_streaming_destination`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/147888) | Event triggered when an external audit event destination for a top-level group is created.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.11](https://gitlab.com/gitlab-org/gitlab/-/issues/436610) | Group | | [`created_group_namespace_filter`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/150712) | Event triggered when a namespace filter for an external audit event destination for a top-level group is created.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [17.0](https://gitlab.com/gitlab-org/gitlab/-/issues/436612) | Group | | [`created_instance_audit_event_streaming_destination`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/148383) | Event triggered when an external audit event destination for a GitLab instance is created.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.11](https://gitlab.com/gitlab-org/gitlab/-/issues/436615) | Instance | +| [`created_instance_namespace_filter`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/153156) | Event triggered when a namespace filter for an external audit event destination for an instance is created.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [17.2](https://gitlab.com/gitlab-org/gitlab/-/issues/436613) | Instance | | [`delete_http_namespace_filter`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136302) | Event triggered when a namespace filter for an external audit event destination for a top-level group is deleted.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.7](https://gitlab.com/gitlab-org/gitlab/-/issues/424177) | Group | | [`deleted_group_audit_event_streaming_destination`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/148738) | Event triggered when an external audit event destination for a top-level group is deleted.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.11](https://gitlab.com/gitlab-org/gitlab/-/issues/436610) | Group | | [`deleted_group_namespace_filter`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/150712) | Event triggered when a namespace filter for an external audit event destination for a top-level group is deleted.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [17.0](https://gitlab.com/gitlab-org/gitlab/-/issues/436612) | Group | | [`deleted_instance_audit_event_streaming_destination`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/14910) | Event triggered when an external audit event destination for a GitLab instance is deleted.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.11](https://gitlab.com/gitlab-org/gitlab/-/issues/436615) | Instance | +| [`deleted_instance_namespace_filter`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/153156) | Event triggered when a namespace filter for an external audit event destination for an instance is deleted.| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [17.2](https://gitlab.com/gitlab-org/gitlab/-/issues/436613) | Instance | | [`destroy_event_streaming_destination`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74632) | Event triggered when an external audit event destination is deleted| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [14.6](https://gitlab.com/gitlab-org/gitlab/-/issues/344664) | Group | | [`destroy_instance_event_streaming_destination`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125846) | Event triggered when an instance level external audit event destination is deleted| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [16.2](https://gitlab.com/gitlab-org/gitlab/-/issues/404730) | Instance | | [`event_type_filters_created`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/113081) | Event triggered when a new audit events streaming event type filter is created| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [15.10](https://gitlab.com/gitlab-org/gitlab/-/issues/344848) | Group | diff --git a/doc/user/project/service_desk/configure.md b/doc/user/project/service_desk/configure.md index 91f79ba4a96..f5ce2c55d6a 100644 --- a/doc/user/project/service_desk/configure.md +++ b/doc/user/project/service_desk/configure.md @@ -186,6 +186,33 @@ To edit the custom email display name: 1. Below **Email display name**, enter a new name. 1. Select **Save changes**. +## Default ticket visibility + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33091) in GitLab 17.2 [with a flag](../../../administration/feature_flags.md) named `service_desk_ticket_confidentiality`. Disabled by default. + +FLAG: +The availability of this feature is controlled by a feature flag. +For more information, see the history. + +New tickets are confidential by default, so only project members with at least the Reporter role +can view them. + +In private and internal projects, you can configure GitLab so that new tickets are not confidential by default, and any project member can view them. + +In public projects, this setting is not available because new tickets are always confidential by default. + +Prerequisites: + +- You must have at least the Maintainer role for the project. + +To disable this setting: + +1. On the left sidebar, select **Search or go to** and find your project. +1. Select **Settings > General**. +1. Expand **Service Desk**. +1. Clear the **New tickets are confidential by default** checkbox. +1. Select **Save changes**. + ## Reopen issues when an external participant comments > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8549) in GitLab 16.7 diff --git a/doc/user/shortcuts.md b/doc/user/shortcuts.md index 141dcfb9f0c..7e624d464a7 100644 --- a/doc/user/shortcuts.md +++ b/doc/user/shortcuts.md @@ -43,7 +43,6 @@ These shortcuts are available in most areas of GitLab: | Shift + t | Go to your To-Do List page. | | p, then b | Show or hide the Performance Bar. | | Escape | Hide tooltips or popovers. | -| Escape | Hide tooltips or popovers. | | g, then x | Toggle between [GitLab](https://gitlab.com/) and [GitLab Next](https://next.gitlab.com/) (GitLab SaaS only). | | . | Open the [Web IDE](project/web_ide/index.md). | @@ -105,7 +104,6 @@ These shortcuts are available when viewing issues: | l | Change label. | | c + r | Copy issue reference. | | r | Start writing a comment. Pre-selected text is quoted in the comment. Can't be used to reply in a thread. | -| . | Open the [Web IDE](project/web_ide/index.md). | | | Go to the next design. | | | Go to the previous design. | | Escape | Close the design. | diff --git a/lib/gitlab/background_migration/backfill_vulnerability_findings_remediations_project_id.rb b/lib/gitlab/background_migration/backfill_vulnerability_findings_remediations_project_id.rb new file mode 100644 index 00000000000..4a899cfc366 --- /dev/null +++ b/lib/gitlab/background_migration/backfill_vulnerability_findings_remediations_project_id.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + class BackfillVulnerabilityFindingsRemediationsProjectId < BackfillDesiredShardingKeyJob + operation_name :backfill_vulnerability_findings_remediations_project_id + feature_category :vulnerability_management + end + end +end diff --git a/lib/users/internal.rb b/lib/users/internal.rb index 1cc8d4970b9..3eb0e108b78 100644 --- a/lib/users/internal.rb +++ b/lib/users/internal.rb @@ -129,7 +129,7 @@ module Users uniquify = Gitlab::Utils::Uniquify.new - username = uniquify.string(username) { |s| User.find_by_username(s) } + username = uniquify.string(username) { |s| Namespace.by_path(s) } email = uniquify.string(->(n) { Kernel.sprintf(email_pattern, n) }) do |s| User.find_by_email(s) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 41a5063590b..fc530af9cb4 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -49130,6 +49130,9 @@ msgstr "" msgid "ServiceDesk|Add external participants from the %{codeStart}Cc%{codeEnd} header" msgstr "" +msgid "ServiceDesk|Any project member can view new tickets." +msgstr "" + msgid "ServiceDesk|CRAM-MD5" msgstr "" @@ -49205,6 +49208,9 @@ msgstr "" msgid "ServiceDesk|Enable custom email address" msgstr "" +msgid "ServiceDesk|External participants" +msgstr "" + msgid "ServiceDesk|Forward all emails to the custom email address to %{incomingEmail}." msgstr "" @@ -49238,6 +49244,15 @@ msgstr "" msgid "ServiceDesk|Minimum 8 characters long." msgstr "" +msgid "ServiceDesk|New tickets are confidential by default" +msgstr "" + +msgid "ServiceDesk|On public projects, tickets are always confidential by default." +msgstr "" + +msgid "ServiceDesk|Only project members with at least the Reporter role can view new tickets." +msgstr "" + msgid "ServiceDesk|Or reset and connect a new custom email address to this Service Desk." msgstr "" @@ -49334,6 +49349,9 @@ msgstr "" msgid "ServiceDesk|This issue has been reopened because it received a new comment from an external participant." msgstr "" +msgid "ServiceDesk|Ticket visibility" +msgstr "" + msgid "ServiceDesk|To use a custom email address for this Service Desk, you'll need to configure and verify an email address again." msgstr "" @@ -55876,7 +55894,7 @@ msgstr "" msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)" msgstr "" -msgid "Trial| By clicking Continue or registering through a third party, you accept the %{gitlabSubscriptionAgreement} and acknowledge the %{privacyStatement} and %{cookiePolicy}." +msgid "Trial| By selecting Continue or registering through a third party, you accept the %{gitlabSubscriptionAgreement} and acknowledge the %{privacyStatement} and %{cookiePolicy}." msgstr "" msgid "Trial|Allowed characters: +, 0-9, -, and spaces." diff --git a/package.json b/package.json index 4fb5cd88786..a185520ff0d 100644 --- a/package.json +++ b/package.json @@ -290,7 +290,7 @@ "swagger-cli": "^4.0.4", "tailwindcss": "^3.4.1", "timezone-mock": "^1.0.8", - "vite": "^5.2.13", + "vite": "^5.3.1", "vite-plugin-ruby": "^5.0.0", "vue-loader-vue3": "npm:vue-loader@17.4.2", "vue-test-utils-compat": "0.0.14", diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb index 0fc0b0bcc2e..35c965d3244 100644 --- a/spec/controllers/search_controller_spec.rb +++ b/spec/controllers/search_controller_spec.rb @@ -511,6 +511,36 @@ RSpec.describe SearchController, feature_category: :global_search do expect(json_response).to eq({ 'count' => '0' }) end + describe 'database transaction' do + before do + allow_next_instance_of(SearchService) do |search_service| + allow(search_service).to receive(:search_type).and_return(search_type) + end + end + + subject(:count) { get :count, params: { search: 'hello', scope: 'projects' } } + + context 'for basic search' do + let(:search_type) { 'basic' } + + it 'executes within transaction with short timeout' do + expect(ApplicationRecord).to receive(:with_fast_read_statement_timeout) + + count + end + end + + context 'for advacned search' do + let(:search_type) { 'advanced' } + + it 'does not execute within transaction' do + expect(ApplicationRecord).not_to receive(:with_fast_read_statement_timeout) + + count + end + end + end + it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit do let(:current_user) { user } diff --git a/spec/frontend/behaviors/gl_emoji_spec.js b/spec/frontend/behaviors/gl_emoji_spec.js index ef40179c23b..221ef3ec3f8 100644 --- a/spec/frontend/behaviors/gl_emoji_spec.js +++ b/spec/frontend/behaviors/gl_emoji_spec.js @@ -155,6 +155,10 @@ describe('gl_emoji', () => { group: { id: 1, customEmoji: { + pageInfo: { + hasNextPage: false, + endCursor: 'test', + }, nodes: [{ id: 1, name: 'parrot', url: 'parrot.gif' }], }, }, @@ -163,7 +167,6 @@ describe('gl_emoji', () => { ], ]); - window.gon = { features: { customEmoji: true } }; document.body.dataset.groupFullPath = 'test-group'; await initEmojiMock(emojiData); diff --git a/spec/frontend/emoji/index_spec.js b/spec/frontend/emoji/index_spec.js index fd3d503c01e..66c000d2088 100644 --- a/spec/frontend/emoji/index_spec.js +++ b/spec/frontend/emoji/index_spec.js @@ -59,24 +59,42 @@ const emptySupportMap = { 1.1: false, }; -function createMockEmojiClient() { - mockClient = createMockClient([ +function createMockEmojiClient(hasNextPage = false) { + mockClient = createMockClient( [ - customEmojiQuery, - jest.fn().mockResolvedValue({ - data: { - group: { - id: 1, - customEmoji: { - nodes: [{ id: 1, name: 'parrot', url: 'parrot.gif' }], + [ + customEmojiQuery, + ({ after }) => + Promise.resolve({ + data: { + group: { + id: 1, + customEmoji: { + pageInfo: { + hasNextPage: after ? false : hasNextPage, + endCursor: 'test', + }, + nodes: [{ id: 1, name: `parrot${after ? `-${after}` : ''}`, url: 'parrot.gif' }], + }, + }, + }, + }), + ], + ], + {}, + { + typePolicies: { + Query: { + fields: { + group: { + merge: true, }, }, }, - }), - ], - ]); + }, + }, + ); - window.gon = { features: { customEmoji: true } }; document.body.dataset.groupFullPath = 'test-group'; } @@ -916,12 +934,9 @@ describe('emoji', () => { }); describe('loadCustomEmojiWithNames', () => { - beforeEach(() => { - createMockEmojiClient(); - }); - describe('when not in a group', () => { beforeEach(() => { + createMockEmojiClient(); delete document.body.dataset.groupFullPath; }); @@ -953,8 +968,10 @@ describe('emoji', () => { }); }); - describe('when in a group with flag enabled', () => { + describe('when in a group', () => { it('returns emoji data', async () => { + createMockEmojiClient(); + const result = await loadCustomEmojiWithNames(); expect(result).toEqual({ @@ -971,6 +988,34 @@ describe('emoji', () => { names: ['parrot'], }); }); + + it('paginates custom emoji emoji', async () => { + createMockEmojiClient(true); + + const result = await loadCustomEmojiWithNames(); + + expect(result).toEqual({ + emojis: { + parrot: { + c: 'custom', + d: 'parrot', + e: undefined, + name: 'parrot', + src: 'parrot.gif', + u: 'custom', + }, + 'parrot-test': { + c: 'custom', + d: 'parrot-test', + e: undefined, + name: 'parrot-test', + src: 'parrot.gif', + u: 'custom', + }, + }, + names: ['parrot', 'parrot-test'], + }); + }); }); }); }); diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js index 185a85cdb80..8144bd31e96 100644 --- a/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js +++ b/spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js @@ -22,6 +22,7 @@ describe('ServiceDeskRoot', () => { isIssueTrackerEnabled: true, outgoingName: 'GitLab Support Bot', projectKey: 'key', + areTicketsConfidentialByDefault: false, reopenIssueOnExternalParticipantNote: true, addExternalParticipantsFromCc: true, selectedTemplate: 'Bug', @@ -61,6 +62,7 @@ describe('ServiceDeskRoot', () => { incomingEmail: provideData.initialIncomingEmail, initialOutgoingName: provideData.outgoingName, initialProjectKey: provideData.projectKey, + initialAreTicketsConfidentialByDefault: provideData.areTicketsConfidentialByDefault, initialReopenIssueOnExternalParticipantNote: provideData.reopenIssueOnExternalParticipantNote, initialAddExternalParticipantsFromCc: provideData.addExternalParticipantsFromCc, @@ -69,6 +71,7 @@ describe('ServiceDeskRoot', () => { isEnabled: provideData.initialIsEnabled, isIssueTrackerEnabled: provideData.isIssueTrackerEnabled, isTemplateSaving: false, + publicProject: provideData.publicProject, templates: provideData.templates, }); }); @@ -149,6 +152,7 @@ describe('ServiceDeskRoot', () => { selectedTemplate: 'Bug', outgoingName: 'GitLab Support Bot', projectKey: 'key', + areTicketsConfidentialByDefault: false, reopenIssueOnExternalParticipantNote: true, addExternalParticipantsFromCc: true, }; @@ -164,6 +168,7 @@ describe('ServiceDeskRoot', () => { outgoing_name: 'GitLab Support Bot', project_key: 'key', service_desk_enabled: true, + tickets_confidential_by_default: false, reopen_issue_on_external_participant_note: true, add_external_participants_from_cc: true, }); @@ -184,6 +189,7 @@ describe('ServiceDeskRoot', () => { selectedTemplate: 'Bug', outgoingName: 'GitLab Support Bot', projectKey: 'key', + tickets_confidential_by_default: false, reopen_issue_on_external_participant_note: true, addExternalParticipantsFromCc: true, }; diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js index f7bdb2455e9..ce031c04ba5 100644 --- a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js +++ b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js @@ -19,6 +19,10 @@ describe('ServiceDeskSetting', () => { const findSuffixFormGroup = () => wrapper.findByTestId('suffix-form-group'); const findIssueTrackerInfo = () => wrapper.findComponent(GlAlert); const findIssueHelpLink = () => wrapper.findByTestId('issue-help-page'); + const findAreTicketsConfidentialByDefaultWrapper = () => + wrapper.findByTestId('service-desk-are-tickets-confidential-by-default-wrapper'); + const findAreTicketsConfidentialByDefaultCheckbox = () => + wrapper.findByTestId('service-desk-are-tickets-confidential-by-default'); const findReopenIssueOnExternalParticipantNoteCheckbox = () => wrapper.findByTestId('reopen-issue-on-external-participant-note'); const findAddExternalParticipantsFromCcCheckbox = () => @@ -35,6 +39,7 @@ describe('ServiceDeskSetting', () => { provide: { glFeatures: { issueEmailParticipants: true, + serviceDeskTicketsConfidentiality: true, }, ...provide, }, @@ -215,6 +220,83 @@ describe('ServiceDeskSetting', () => { }); }); + describe('are tickets confidential by default checkbox', () => { + it('is rendered', () => { + wrapper = createComponent(); + + expect(findAreTicketsConfidentialByDefaultCheckbox().exists()).toBe(true); + }); + + describe('when project is public', () => { + beforeEach(() => { + wrapper = createComponent({ + props: { publicProject: true, initialAreTicketsConfidentialByDefault: false }, + }); + }); + + it('displays correct help text', () => { + expect(findAreTicketsConfidentialByDefaultWrapper().text()).toContain( + ServiceDeskSetting.i18n.areTicketsConfidentialByDefault.help.publicProject, + ); + }); + + it('checks and disables the checkbox', () => { + const { element } = findAreTicketsConfidentialByDefaultCheckbox().find('input'); + + expect(element.checked).toBe(true); + expect(element.disabled).toBe(true); + }); + }); + + describe('when project is not public', () => { + describe('when tickets are confidential by default', () => { + beforeEach(() => { + wrapper = createComponent({ props: { initialAreTicketsConfidentialByDefault: true } }); + }); + + it('forwards true as initial value to the checkbox', () => { + expect(findAreTicketsConfidentialByDefaultCheckbox().find('input').element.checked).toBe( + true, + ); + }); + + it('displays correct help text', () => { + expect(findAreTicketsConfidentialByDefaultWrapper().text()).toContain( + ServiceDeskSetting.i18n.areTicketsConfidentialByDefault.help.confidential, + ); + }); + }); + + describe('when tickets are not confidential by default', () => { + beforeEach(() => { + wrapper = createComponent({ props: { initialAreTicketsConfidentialByDefault: false } }); + }); + + it('forwards false as initial value to the checkbox', () => { + expect(findAreTicketsConfidentialByDefaultCheckbox().find('input').element.checked).toBe( + false, + ); + }); + + it('displays correct help text', () => { + expect(findAreTicketsConfidentialByDefaultWrapper().text()).toContain( + ServiceDeskSetting.i18n.areTicketsConfidentialByDefault.help.nonConfidential, + ); + }); + }); + }); + + describe('when feature flag service_desk_tickets_confidentiality is disabled', () => { + it('is not rendered', () => { + wrapper = createComponent({ + provide: { glFeatures: { serviceDeskTicketsConfidentiality: false } }, + }); + + expect(findAreTicketsConfidentialByDefaultCheckbox().exists()).toBe(false); + }); + }); + }); + describe('reopen issue on external participant note checkbox', () => { it('is rendered', () => { wrapper = createComponent(); @@ -273,6 +355,7 @@ describe('ServiceDeskSetting', () => { initialSelectedFileTemplateProjectId: 42, initialOutgoingName: 'GitLab Support Bot', initialProjectKey: 'key', + initialAreTicketsConfidentialByDefault: false, initialReopenIssueOnExternalParticipantNote: true, initialAddExternalParticipantsFromCc: true, }, @@ -287,6 +370,7 @@ describe('ServiceDeskSetting', () => { fileTemplateProjectId: 42, outgoingName: 'GitLab Support Bot', projectKey: 'key', + areTicketsConfidentialByDefault: false, reopenIssueOnExternalParticipantNote: true, addExternalParticipantsFromCc: true, }; diff --git a/spec/frontend/work_items/components/design_management/design_preview/design_toolbar_spec.js b/spec/frontend/work_items/components/design_management/design_preview/design_toolbar_spec.js index abbc3423a5f..bc057577cbe 100644 --- a/spec/frontend/work_items/components/design_management/design_preview/design_toolbar_spec.js +++ b/spec/frontend/work_items/components/design_management/design_preview/design_toolbar_spec.js @@ -1,5 +1,5 @@ import { nextTick } from 'vue'; -import { GlSkeletonLoader } from '@gitlab/ui'; +import { GlSkeletonLoader, GlButton } from '@gitlab/ui'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import DesignToolbar from '~/work_items/components/design_management/design_preview/design_toolbar.vue'; import CloseButton from '~/work_items/components/design_management/design_preview/close_button.vue'; @@ -41,6 +41,12 @@ describe('DesignToolbar', () => { expect(wrapper.find('h2').text()).toContain(mockDesign.filename); }); + it('renders download button with correct link', () => { + createComponent(); + + expect(wrapper.findComponent(GlButton).attributes('href')).toBe(mockDesign.image); + }); + it('renders close button', () => { createComponent(); diff --git a/spec/frontend/work_items/components/work_item_detail_spec.js b/spec/frontend/work_items/components/work_item_detail_spec.js index bea9d3f0f3d..2e9fed48b30 100644 --- a/spec/frontend/work_items/components/work_item_detail_spec.js +++ b/spec/frontend/work_items/components/work_item_detail_spec.js @@ -106,6 +106,7 @@ describe('WorkItemDetail component', () => { error = undefined, workItemsAlphaEnabled = false, workItemsBeta = false, + namespaceLevelWorkItems = true, } = {}) => { wrapper = shallowMountExtended(WorkItemDetail, { apolloProvider: createMockApollo([ @@ -130,6 +131,7 @@ describe('WorkItemDetail component', () => { glFeatures: { workItemsAlpha: workItemsAlphaEnabled, workItemsBeta, + namespaceLevelWorkItems, }, hasIssueWeightsFeature: true, hasIterationsFeature: true, @@ -315,7 +317,7 @@ describe('WorkItemDetail component', () => { expect(findAncestors().exists()).toBe(false); }); - it('does not show ancestors widget if there is not a parent', async () => { + it('does not show ancestors widget if there is no parent', async () => { createComponent({ handler: jest.fn().mockResolvedValue(workItemQueryResponseWithoutParent) }); await waitForPromises(); @@ -330,6 +332,17 @@ describe('WorkItemDetail component', () => { expect(findWorkItemType().classes()).toEqual(['sm:!gl-block', 'gl-w-full']); }); + describe('`namespace_level_work_items` is disabled', () => { + it('does not show ancestors widget and shows title in the header', async () => { + createComponent({ namespaceLevelWorkItems: false }); + + await waitForPromises(); + + expect(findAncestors().exists()).toBe(false); + expect(findWorkItemType().classes()).toEqual(['sm:!gl-block', 'gl-w-full']); + }); + }); + describe('with parent', () => { beforeEach(() => { const parentResponse = workItemByIidResponseFactory(mockParent); diff --git a/spec/lib/gitlab/background_migration/backfill_vulnerability_findings_remediations_project_id_spec.rb b/spec/lib/gitlab/background_migration/backfill_vulnerability_findings_remediations_project_id_spec.rb new file mode 100644 index 00000000000..437e9ed4817 --- /dev/null +++ b/spec/lib/gitlab/background_migration/backfill_vulnerability_findings_remediations_project_id_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::BackfillVulnerabilityFindingsRemediationsProjectId, + feature_category: :vulnerability_management, + schema: 20240618121517 do + include_examples 'desired sharding key backfill job' do + let(:batch_table) { :vulnerability_findings_remediations } + let(:backfill_column) { :project_id } + let(:backfill_via_table) { :vulnerability_occurrences } + let(:backfill_via_column) { :project_id } + let(:backfill_via_foreign_key) { :vulnerability_occurrence_id } + end +end diff --git a/spec/lib/users/internal_spec.rb b/spec/lib/users/internal_spec.rb index dd9257d29ba..60071ded09b 100644 --- a/spec/lib/users/internal_spec.rb +++ b/spec/lib/users/internal_spec.rb @@ -27,7 +27,7 @@ RSpec.describe Users::Internal, feature_category: :user_profile do end.not_to change { User.count } end - context 'when a regular user exists with the bot usernane' do + context 'when a regular user exists with the bot username' do it 'creates a user with a non-conflicting username' do create(:user, username: username) @@ -47,6 +47,16 @@ RSpec.describe Users::Internal, feature_category: :user_profile do end end + context 'when a group namespace exists with path that is equal to the bot username' do + it 'creates a user with a non-conflicting username' do + create(:group, path: username) + + expect do + described_class.public_send(bot_type) + end.to change { User.where(user_type: bot_type).count }.by(1) + end + end + context 'when a domain allowlist is in place' do before do stub_application_setting(domain_allowlist: ['gitlab.com']) diff --git a/spec/migrations/20240618121521_queue_backfill_vulnerability_findings_remediations_project_id_spec.rb b/spec/migrations/20240618121521_queue_backfill_vulnerability_findings_remediations_project_id_spec.rb new file mode 100644 index 00000000000..32d3f4c859d --- /dev/null +++ b/spec/migrations/20240618121521_queue_backfill_vulnerability_findings_remediations_project_id_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe QueueBackfillVulnerabilityFindingsRemediationsProjectId, feature_category: :vulnerability_management do + let!(:batched_migration) { described_class::MIGRATION } + + it 'schedules a new batched migration' do + reversible_migration do |migration| + migration.before -> { + expect(batched_migration).not_to have_scheduled_batched_migration + } + + migration.after -> { + expect(batched_migration).to have_scheduled_batched_migration( + table_name: :vulnerability_findings_remediations, + column_name: :id, + interval: described_class::DELAY_INTERVAL, + batch_size: described_class::BATCH_SIZE, + sub_batch_size: described_class::SUB_BATCH_SIZE, + gitlab_schema: :gitlab_main_cell, + job_arguments: [ + :project_id, + :vulnerability_occurrences, + :project_id, + :vulnerability_occurrence_id + ] + ) + } + end + end +end diff --git a/spec/support/shared_examples/mailers/notify_shared_examples.rb b/spec/support/shared_examples/mailers/notify_shared_examples.rb index f0d89f6ffaa..939e2a2377a 100644 --- a/spec/support/shared_examples/mailers/notify_shared_examples.rb +++ b/spec/support/shared_examples/mailers/notify_shared_examples.rb @@ -196,11 +196,12 @@ end RSpec.shared_examples 'an unsubscribeable thread' do it_behaves_like 'an unsubscribeable thread with incoming address without %{key}' - it 'has a List-Unsubscribe header in the correct format, and a body link' do + it 'has a List-Unsubscribe header in the correct format, List-Unsubscribe-Post header, and a body link' do aggregate_failures do is_expected.to have_header('List-Unsubscribe', /unsubscribe/) is_expected.to have_header('List-Unsubscribe', /mailto/) is_expected.to have_header('List-Unsubscribe', /^<.+,.+>$/) + is_expected.to have_header('List-Unsubscribe-Post', 'List-Unsubscribe=One-Click') is_expected.to have_body_text('unsubscribe') end end @@ -209,20 +210,22 @@ end RSpec.shared_examples 'an unsubscribeable thread with incoming address without %{key}' do include_context 'reply-by-email is enabled with incoming address without %{key}' - it 'has a List-Unsubscribe header in the correct format, and a body link' do + it 'has a List-Unsubscribe header in the correct format, List-Unsubscribe-Post header, and a body link' do aggregate_failures do is_expected.to have_header('List-Unsubscribe', /unsubscribe/) is_expected.not_to have_header('List-Unsubscribe', /mailto/) is_expected.to have_header('List-Unsubscribe', /^<[^,]+>$/) + is_expected.to have_header('List-Unsubscribe-Post', 'List-Unsubscribe=One-Click') is_expected.to have_body_text('unsubscribe') end end end RSpec.shared_examples 'a user cannot unsubscribe through footer link' do - it 'does not have a List-Unsubscribe header or a body link' do + it 'does not have a List-Unsubscribe header, List-Unsubscribe-Post header or a body link' do aggregate_failures do is_expected.not_to have_header('List-Unsubscribe', /unsubscribe/) + is_expected.not_to have_header('List-Unsubscribe-Post', 'List-Unsubscribe=One-Click') is_expected.not_to have_body_text('unsubscribe') end end diff --git a/yarn.lock b/yarn.lock index 233843d0f3b..deab07d12b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1092,125 +1092,125 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@esbuild/aix-ppc64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537" - integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g== +"@esbuild/aix-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" + integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== -"@esbuild/android-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9" - integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg== +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== -"@esbuild/android-arm@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995" - integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w== +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== -"@esbuild/android-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98" - integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg== +"@esbuild/android-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" + integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== -"@esbuild/darwin-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb" - integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA== +"@esbuild/darwin-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== -"@esbuild/darwin-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0" - integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA== +"@esbuild/darwin-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" + integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== -"@esbuild/freebsd-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911" - integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw== +"@esbuild/freebsd-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" + integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== -"@esbuild/freebsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c" - integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw== +"@esbuild/freebsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" + integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== -"@esbuild/linux-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5" - integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A== +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== -"@esbuild/linux-arm@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c" - integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg== +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== -"@esbuild/linux-ia32@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa" - integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig== +"@esbuild/linux-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" + integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== "@esbuild/linux-loong64@0.14.54": version "0.14.54" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz#de2a4be678bd4d0d1ffbb86e6de779cde5999028" integrity sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw== -"@esbuild/linux-loong64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5" - integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ== +"@esbuild/linux-loong64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" + integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== -"@esbuild/linux-mips64el@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa" - integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA== +"@esbuild/linux-mips64el@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" + integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== -"@esbuild/linux-ppc64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20" - integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg== +"@esbuild/linux-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" + integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== -"@esbuild/linux-riscv64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300" - integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg== +"@esbuild/linux-riscv64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" + integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== -"@esbuild/linux-s390x@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685" - integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ== +"@esbuild/linux-s390x@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" + integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== -"@esbuild/linux-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff" - integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw== +"@esbuild/linux-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" + integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== -"@esbuild/netbsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6" - integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ== +"@esbuild/netbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" + integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== -"@esbuild/openbsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf" - integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ== +"@esbuild/openbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" + integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== -"@esbuild/sunos-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f" - integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w== +"@esbuild/sunos-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" + integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== -"@esbuild/win32-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90" - integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ== +"@esbuild/win32-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" + integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== -"@esbuild/win32-ia32@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23" - integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ== +"@esbuild/win32-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" + integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== -"@esbuild/win32-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc" - integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ== +"@esbuild/win32-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" + integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" @@ -6494,34 +6494,34 @@ esbuild@^0.14.14: esbuild-windows-64 "0.14.54" esbuild-windows-arm64 "0.14.54" -esbuild@^0.20.1: - version "0.20.2" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1" - integrity sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g== +esbuild@^0.21.3: + version "0.21.5" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" + integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== optionalDependencies: - "@esbuild/aix-ppc64" "0.20.2" - "@esbuild/android-arm" "0.20.2" - "@esbuild/android-arm64" "0.20.2" - "@esbuild/android-x64" "0.20.2" - "@esbuild/darwin-arm64" "0.20.2" - "@esbuild/darwin-x64" "0.20.2" - "@esbuild/freebsd-arm64" "0.20.2" - "@esbuild/freebsd-x64" "0.20.2" - "@esbuild/linux-arm" "0.20.2" - "@esbuild/linux-arm64" "0.20.2" - "@esbuild/linux-ia32" "0.20.2" - "@esbuild/linux-loong64" "0.20.2" - "@esbuild/linux-mips64el" "0.20.2" - "@esbuild/linux-ppc64" "0.20.2" - "@esbuild/linux-riscv64" "0.20.2" - "@esbuild/linux-s390x" "0.20.2" - "@esbuild/linux-x64" "0.20.2" - "@esbuild/netbsd-x64" "0.20.2" - "@esbuild/openbsd-x64" "0.20.2" - "@esbuild/sunos-x64" "0.20.2" - "@esbuild/win32-arm64" "0.20.2" - "@esbuild/win32-ia32" "0.20.2" - "@esbuild/win32-x64" "0.20.2" + "@esbuild/aix-ppc64" "0.21.5" + "@esbuild/android-arm" "0.21.5" + "@esbuild/android-arm64" "0.21.5" + "@esbuild/android-x64" "0.21.5" + "@esbuild/darwin-arm64" "0.21.5" + "@esbuild/darwin-x64" "0.21.5" + "@esbuild/freebsd-arm64" "0.21.5" + "@esbuild/freebsd-x64" "0.21.5" + "@esbuild/linux-arm" "0.21.5" + "@esbuild/linux-arm64" "0.21.5" + "@esbuild/linux-ia32" "0.21.5" + "@esbuild/linux-loong64" "0.21.5" + "@esbuild/linux-mips64el" "0.21.5" + "@esbuild/linux-ppc64" "0.21.5" + "@esbuild/linux-riscv64" "0.21.5" + "@esbuild/linux-s390x" "0.21.5" + "@esbuild/linux-x64" "0.21.5" + "@esbuild/netbsd-x64" "0.21.5" + "@esbuild/openbsd-x64" "0.21.5" + "@esbuild/sunos-x64" "0.21.5" + "@esbuild/win32-arm64" "0.21.5" + "@esbuild/win32-ia32" "0.21.5" + "@esbuild/win32-x64" "0.21.5" escalade@^3.1.1: version "3.1.1" @@ -14131,12 +14131,12 @@ vite-plugin-ruby@^5.0.0: debug "^4.3.4" fast-glob "^3.3.2" -vite@^5.2.13: - version "5.2.13" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.13.tgz#945ababcbe3d837ae2479c29f661cd20bc5e1a80" - integrity sha512-SSq1noJfY9pR3I1TUENL3rQYDQCFqgD+lM6fTRAM8Nv6Lsg5hDLaXkjETVeBt+7vZBCMoibD+6IWnT2mJ+Zb/A== +vite@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.3.1.tgz#bb2ca6b5fd7483249d3e86b25026e27ba8a663e6" + integrity sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ== dependencies: - esbuild "^0.20.1" + esbuild "^0.21.3" postcss "^8.4.38" rollup "^4.13.0" optionalDependencies: