Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-06-19 12:23:23 +00:00
parent ab756700d5
commit d134089c5e
61 changed files with 1107 additions and 291 deletions

View File

@ -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"

View File

@ -1 +1 @@
5.0.0
5.1.0

View File

@ -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() {

View File

@ -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

View File

@ -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"

View File

@ -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 {
</template>
</gl-form-group>
<div
v-if="showAreTicketsConfidentialByDefault"
data-testid="service-desk-are-tickets-confidential-by-default-wrapper"
>
<h5>{{ $options.i18n.headlines.ticketVisibility }}</h5>
<gl-form-checkbox
v-model="areTicketsConfidentialByDefault"
:disabled="!isIssueTrackerEnabled || publicProject"
data-testid="service-desk-are-tickets-confidential-by-default"
>
{{ $options.i18n.areTicketsConfidentialByDefault.label }}
<template #help>
{{ areTicketsConfidentialByDefaultHelp }}
</template>
</gl-form-checkbox>
</div>
<h5>{{ $options.i18n.headlines.externalParticipants }}</h5>
<gl-form-checkbox
v-model="reopenIssueOnExternalParticipantNote"
:disabled="!isIssueTrackerEnabled"
data-testid="reopen-issue-on-external-participant-note"
class="gl-mb-3"
>
{{ $options.i18n.reopenIssueOnExternalParticipantNote.label }}

View File

@ -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,

View File

@ -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 {
<close-button class="md:gl-hidden gl-ml-auto" />
</div>
<div class="gl-flex md:gl-flex-row gl-flex-shrink-0 gl-md-ml-auto gl-mr-5">
<gl-button
v-gl-tooltip.bottom
category="tertiary"
class="gl-ml-2"
:href="design.image"
icon="download"
:title="$options.i18n.downloadButtonLabel"
:aria-label="$options.i18n.downloadButtonLabel"
/>
<gl-button
v-gl-tooltip.bottom
category="tertiary"

View File

@ -25,6 +25,7 @@ import {
WIDGET_TYPE_DESIGNS,
LINKED_ITEMS_ANCHOR,
WORK_ITEM_REFERENCE_CHAR,
WORK_ITEM_TYPE_VALUE_TASK,
} from '../constants';
import workItemUpdatedSubscription from '../graphql/work_item_updated.subscription.graphql';
@ -206,6 +207,13 @@ export default {
parentWorkItem() {
return this.isWidgetPresent(WIDGET_TYPE_HIERARCHY)?.parent;
},
showAncestors() {
// TODO: This is a temporary check till the issue work item migration is completed
// Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/468114
return this.workItemType === WORK_ITEM_TYPE_VALUE_TASK
? this.glFeatures.namespaceLevelWorkItems && this.parentWorkItem
: this.parentWorkItem;
},
parentWorkItemConfidentiality() {
return this.parentWorkItem?.confidential;
},
@ -269,16 +277,16 @@ export default {
},
titleClassHeader() {
return {
'sm:!gl-hidden gl-mt-3': this.parentWorkItem,
'sm:!gl-block': !this.parentWorkItem,
'gl-w-full': !this.parentWorkItem && !this.editMode,
'editable-wi-title': this.editMode && !this.parentWorkItem,
'sm:!gl-hidden gl-mt-3': this.showAncestors,
'sm:!gl-block': !this.showAncestors,
'gl-w-full': !this.showAncestors && !this.editMode,
'editable-wi-title': this.editMode && !this.showAncestors,
};
},
titleClassComponent() {
return {
'sm:!gl-block': !this.parentWorkItem,
'gl-hidden sm:!gl-block gl-mt-3': this.parentWorkItem,
'sm:!gl-block': !this.showAncestors,
'gl-hidden sm:!gl-block gl-mt-3': this.showAncestors,
'editable-wi-title': this.workItemsAlphaEnabled,
};
},
@ -494,7 +502,7 @@ export default {
/>
<div v-else data-testid="detail-wrapper">
<div class="gl-block sm:!gl-flex gl-items-start gl-flex-row gl-gap-3">
<work-item-ancestors v-if="parentWorkItem" :work-item="workItem" class="gl-mb-1" />
<work-item-ancestors v-if="showAncestors" :work-item="workItem" class="gl-mb-1" />
<div v-if="!error" :class="titleClassHeader" data-testid="work-item-type">
<work-item-title
v-if="workItem.title"
@ -568,7 +576,7 @@ export default {
</div>
<div :class="{ 'gl-mt-3': !editMode }">
<work-item-title
v-if="workItem.title && parentWorkItem"
v-if="workItem.title && showAncestors"
ref="title"
:is-editing="editMode"
:class="titleClassComponent"

View File

@ -9,6 +9,7 @@ module Groups
push_force_frontend_feature_flag(:work_items, group&.work_items_feature_flag_enabled?)
push_force_frontend_feature_flag(:work_items_beta, group&.work_items_beta_feature_flag_enabled?)
push_force_frontend_feature_flag(:work_items_alpha, group&.work_items_alpha_feature_flag_enabled?)
push_frontend_feature_flag(:namespace_level_work_items, group)
end
def index

View File

@ -42,6 +42,7 @@ class GroupsController < Groups::ApplicationController
push_force_frontend_feature_flag(:work_items_alpha, group.work_items_alpha_feature_flag_enabled?)
push_frontend_feature_flag(:issues_grid_view)
push_frontend_feature_flag(:group_multi_select_tokens, group)
push_frontend_feature_flag(:namespace_level_work_items, group)
end
before_action only: :merge_requests do

View File

@ -67,6 +67,7 @@ class Projects::IssuesController < Projects::ApplicationController
push_force_frontend_feature_flag(:work_items_alpha, project&.work_items_alpha_feature_flag_enabled?)
push_frontend_feature_flag(:epic_widget_edit_confirmation, project)
push_frontend_feature_flag(:display_work_item_epic_issue_sidebar, project)
push_frontend_feature_flag(:namespace_level_work_items, project&.group)
end
around_action :allow_gitaly_ref_name_caching, only: [:discussions]

View File

@ -12,6 +12,7 @@ class Projects::WorkItemsController < Projects::ApplicationController
push_force_frontend_feature_flag(:work_items, project&.work_items_feature_flag_enabled?)
push_force_frontend_feature_flag(:work_items_beta, project&.work_items_beta_feature_flag_enabled?)
push_force_frontend_feature_flag(:work_items_alpha, project&.work_items_alpha_feature_flag_enabled?)
push_frontend_feature_flag(:namespace_level_work_items, project&.group)
end
feature_category :team_planning

View File

@ -53,6 +53,7 @@ class ProjectsController < Projects::ApplicationController
push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?)
push_force_frontend_feature_flag(:work_items_beta, @project&.work_items_beta_feature_flag_enabled?)
push_force_frontend_feature_flag(:work_items_alpha, @project&.work_items_alpha_feature_flag_enabled?)
push_frontend_feature_flag(:namespace_level_work_items, @project&.group)
end
layout :determine_layout

View File

@ -106,9 +106,13 @@ class SearchController < ApplicationController
count = 0
@global_search_duration_s = Benchmark.realtime do
ApplicationRecord.with_fast_read_statement_timeout do
count = search_service.search_results.formatted_count(scope)
end
count = if @search_type == 'basic'
ApplicationRecord.with_fast_read_statement_timeout do
search_service.search_results.formatted_count(scope)
end
else
search_service.search_results.formatted_count(scope)
end
# Users switching tabs will keep fetching the same tab counts so it's a
# good idea to cache in their browser just for a short time. They can still

View File

@ -237,6 +237,10 @@ class Notify < ApplicationMailer
end
headers['List-Unsubscribe'] = list_unsubscribe_methods.map { |e| "<#{e}>" }.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

View File

@ -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

View File

@ -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: '</a>'.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),

View File

@ -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

View File

@ -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

View File

@ -17,3 +17,4 @@ desired_sharding_key:
table: vulnerability_occurrences
sharding_key: project_id
belongs_to: finding
desired_sharding_key_migration_job_name: BackfillVulnerabilityFindingsRemediationsProjectId

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
27c7b399872c197d8238e688fe42c09f8df86964812ea7a4ae59f38bfa018400

View File

@ -0,0 +1 @@
98d2934a8067678b201fb45a9361f78f45263c3800600e580f7e34ead39ea052

View File

@ -0,0 +1 @@
808154ef3dde0e14e82d86702e7e4e807e9b1f9858feef6efdef66f0f47fb3a9

View File

@ -0,0 +1 @@
8e6fc4e2d1477908ca7995f5f98127d202ed21ae3cbfcb8d7de86c4500fc4797

View File

@ -0,0 +1 @@
0a9dce38fe804d84fa7ac6c1d65bdff5ac6c88e3df57a0812ccd291dfd2c147a

View File

@ -0,0 +1 @@
47c824811fde371acee3547b45cceb29157c1a5a9339df22348935d89c457933

View File

@ -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;

View File

@ -2018,6 +2018,52 @@ Input type: `AuditEventsInstanceDestinationEventsDeleteInput`
| <a id="mutationauditeventsinstancedestinationeventsdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationauditeventsinstancedestinationeventsdeleteerrors"></a>`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 |
| ---- | ---- | ----------- |
| <a id="mutationauditeventsinstancedestinationnamespacefiltercreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationauditeventsinstancedestinationnamespacefiltercreatedestinationid"></a>`destinationId` | [`AuditEventsInstanceExternalStreamingDestinationID!`](#auditeventsinstanceexternalstreamingdestinationid) | Destination ID. |
| <a id="mutationauditeventsinstancedestinationnamespacefiltercreatenamespacepath"></a>`namespacePath` | [`String`](#string) | Full path of the namespace. Project or group namespaces only. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationauditeventsinstancedestinationnamespacefiltercreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationauditeventsinstancedestinationnamespacefiltercreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationauditeventsinstancedestinationnamespacefiltercreatenamespacefilter"></a>`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 |
| ---- | ---- | ----------- |
| <a id="mutationauditeventsinstancedestinationnamespacefilterdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationauditeventsinstancedestinationnamespacefilterdeletenamespacefilterid"></a>`namespaceFilterId` | [`AuditEventsInstanceNamespaceFilterID!`](#auditeventsinstancenamespacefilterid) | Namespace filter ID. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationauditeventsinstancedestinationnamespacefilterdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationauditeventsinstancedestinationnamespacefilterdeleteerrors"></a>`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.
| <a id="instanceamazons3configurationtypeid"></a>`id` | [`ID!`](#id) | ID of the configuration. |
| <a id="instanceamazons3configurationtypename"></a>`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 |
| ---- | ---- | ----------- |
| <a id="instanceauditeventnamespacefilterexternalstreamingdestination"></a>`externalStreamingDestination` | [`InstanceAuditEventStreamingDestination!`](#instanceauditeventstreamingdestination) | Destination to which the filter belongs. |
| <a id="instanceauditeventnamespacefilterid"></a>`id` | [`ID!`](#id) | ID of the filter. |
| <a id="instanceauditeventnamespacefilternamespace"></a>`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.
| <a id="instanceauditeventstreamingdestinationeventtypefilters"></a>`eventTypeFilters` | [`[String!]!`](#string) | List of event type filters added for streaming. |
| <a id="instanceauditeventstreamingdestinationid"></a>`id` | [`ID!`](#id) | ID of the destination. |
| <a id="instanceauditeventstreamingdestinationname"></a>`name` | [`String!`](#string) | Name of the external destination to send audit events to. |
| <a id="instanceauditeventstreamingdestinationnamespacefilters"></a>`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.

View File

@ -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: <your_access_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: <your_access_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.

View File

@ -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

View File

@ -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.<br/>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. |

View File

@ -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

View File

@ -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 `<host>[:<port>]/<project_full_path>`. 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. |

View File

@ -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).

View File

@ -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.

View File

@ -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 |

View File

@ -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

View File

@ -43,7 +43,6 @@ These shortcuts are available in most areas of GitLab:
| <kbd>Shift</kbd> + <kbd>t</kbd> | Go to your To-Do List page. |
| <kbd>p</kbd>, then <kbd>b</kbd> | Show or hide the Performance Bar. |
| <kbd>Escape</kbd> | Hide tooltips or popovers. |
| <kbd>Escape</kbd> | Hide tooltips or popovers. |
| <kbd>g</kbd>, then <kbd>x</kbd> | Toggle between [GitLab](https://gitlab.com/) and [GitLab Next](https://next.gitlab.com/) (GitLab SaaS only). |
| <kbd>.</kbd> | Open the [Web IDE](project/web_ide/index.md). |
@ -105,7 +104,6 @@ These shortcuts are available when viewing issues:
| <kbd>l</kbd> | Change label. |
| <kbd>c</kbd> + <kbd>r</kbd> | Copy issue reference. |
| <kbd>r</kbd> | Start writing a comment. Pre-selected text is quoted in the comment. Can't be used to reply in a thread. |
| <kbd>.</kbd> | Open the [Web IDE](project/web_ide/index.md). |
| <kbd></kbd> | Go to the next design. |
| <kbd></kbd> | Go to the previous design. |
| <kbd>Escape</kbd> | Close the design. |

View File

@ -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

View File

@ -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)

View File

@ -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 youre enjoying the features of GitLab %{planName}. To keep those features after your trial ends, youll 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."

View File

@ -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",

View File

@ -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 }

View File

@ -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);

View File

@ -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'],
});
});
});
});
});

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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();

View File

@ -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);

View File

@ -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

View File

@ -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'])

View File

@ -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

View File

@ -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

248
yarn.lock
View File

@ -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: