Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-04-26 21:10:59 +00:00
parent 78f9663bdd
commit a2880360e7
63 changed files with 394 additions and 246 deletions

View File

@ -45,6 +45,7 @@ code_quality cache:
artifacts:
paths:
- gl-sast-report.json # GitLab-specific
access: 'developer'
expire_in: 1 week # GitLab-specific
variables:
SAST_BRAKEMAN_LEVEL: 2 # GitLab-specific
@ -64,6 +65,7 @@ semgrep-sast:
artifacts:
paths:
- gl-secret-detection-report.json # GitLab-specific
access: 'developer'
expire_in: 1 week # GitLab-specific
secret_detection:
@ -82,6 +84,7 @@ secret_detection:
artifacts:
paths:
- gl-dependency-scanning-report.json # GitLab-specific
access: 'developer'
expire_in: 1 week # GitLab-specific
gemnasium-dependency_scanning:
@ -119,6 +122,7 @@ gemnasium-python-dependency_scanning:
artifacts:
paths:
- gl-dependency-scanning-report.json
access: 'developer'
reports:
dependency_scanning: gl-dependency-scanning-report.json
expire_in: 1 week

View File

@ -187,6 +187,7 @@ semgrep-appsec-custom-rules:
expire_in: 30 days
paths:
- gl-sast-report.json
access: 'developer'
audit-event-types-verify:
variables:

View File

@ -358,9 +358,9 @@ gem 'gitlab-license', '~> 2.4', feature_category: :shared
gem 'rack-attack', '~> 6.7.0' # rubocop:todo Gemfile/MissingFeatureCategory
# Sentry integration
gem 'sentry-ruby', '~> 5.10.0', feature_category: :error_tracking
gem 'sentry-rails', '~> 5.10.0', feature_category: :error_tracking
gem 'sentry-sidekiq', '~> 5.10.0', feature_category: :error_tracking
gem 'sentry-ruby', '~> 5.17.3', feature_category: :error_tracking
gem 'sentry-rails', '~> 5.17.3', feature_category: :error_tracking
gem 'sentry-sidekiq', '~> 5.17.3', feature_category: :error_tracking
# PostgreSQL query parsing
#

View File

@ -59,6 +59,8 @@
{"name":"benchmark-perf","version":"0.6.0","platform":"ruby","checksum":"fe2b01959f3de0f9dd34820d54ef881eb4f3589fccb7d17b63068ac92d7f9621"},
{"name":"benchmark-trend","version":"0.4.0","platform":"ruby","checksum":"de5a02a9f443babefbbd97784759820decee8554a0c273d859c02a0990845d81"},
{"name":"better_errors","version":"2.10.1","platform":"ruby","checksum":"f798f1bac93f3e775925b7fcb24cffbcf0bb62ee2210f5350f161a6b75fc0a73"},
{"name":"bigdecimal","version":"3.1.7","platform":"java","checksum":"955f5c7aa90136874b494655e42ed70d81382abb0f49f1b42f374a1660e33c63"},
{"name":"bigdecimal","version":"3.1.7","platform":"ruby","checksum":"e799b369a0005fc6d62eed7ef19139ac9bc319cc51470c637b9dcdf593600133"},
{"name":"bindata","version":"2.4.11","platform":"ruby","checksum":"c38e0c99ffcd80c10a0a7ae6c8586d2fe26bf245cbefac90bec8764523220f6a"},
{"name":"binding_of_caller","version":"1.0.0","platform":"ruby","checksum":"3aad25d1d538fc6e7972978f9bf512ccd992784009947c81633bea776713161d"},
{"name":"bootsnap","version":"1.18.3","platform":"ruby","checksum":"d7b70de761e2fb1d63d21dd941b393c881c5cab5575211369cede788dfc034eb"},
@ -621,9 +623,9 @@
{"name":"seed-fu","version":"2.3.7","platform":"ruby","checksum":"f19673443e9af799b730e3d4eca6a89b39e5a36825015dffd00d02ea3365cf74"},
{"name":"selenium-webdriver","version":"4.19.0","platform":"ruby","checksum":"4c8bd1d6016a456154b4ba71a3bb4d532a0ae185a38acf9cec0acbd38b4e5066"},
{"name":"semver_dialects","version":"2.0.2","platform":"ruby","checksum":"60059c9f416f931b5212d862fad2879d6b9affb8e0b9afb0d91b793639c116fe"},
{"name":"sentry-rails","version":"5.10.0","platform":"ruby","checksum":"99aa2fac136c26942eb1897c65de65dac88ad43ac5eb183ff20711287a137ebd"},
{"name":"sentry-ruby","version":"5.10.0","platform":"ruby","checksum":"115c24c0aee1309210f3a2988fb118e2bec1f11609feeda90e694388b1183619"},
{"name":"sentry-sidekiq","version":"5.10.0","platform":"ruby","checksum":"cc81018d0733fb1be3fb5641c9e0b61030bbeaa1d0b23ca64797d70def7aea1a"},
{"name":"sentry-rails","version":"5.17.3","platform":"ruby","checksum":"017771c42d739c0ad2213a581ca9d005cf543227bc13662cd1ca9909f2429459"},
{"name":"sentry-ruby","version":"5.17.3","platform":"ruby","checksum":"61791a4b0bb0f95cd87aceeaa1efa6d4ab34d64236c9d5df820478adfe2fbbfc"},
{"name":"sentry-sidekiq","version":"5.17.3","platform":"ruby","checksum":"d0714a218999e41e38127d0c174e0ee62a32b069f92e85b544e0c2125eca2c58"},
{"name":"sexp_processor","version":"4.17.1","platform":"ruby","checksum":"91110946720307f30bf1d549e90d9a529fef40d1fc471c069c8cca7667015da0"},
{"name":"shellany","version":"0.0.1","platform":"ruby","checksum":"0e127a9132698766d7e752e82cdac8250b6adbd09e6c0a7fbbb6f61964fedee7"},
{"name":"shoulda-matchers","version":"5.1.0","platform":"ruby","checksum":"a01d20589989e9653ab4a28c67d9db2b82bcf0a2496cf01d5e1a95a4aaaf5b07"},

View File

@ -353,6 +353,7 @@ GEM
erubi (>= 1.0.0)
rack (>= 0.9.0)
rouge (>= 1.0.0)
bigdecimal (3.1.7)
bindata (2.4.11)
binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1)
@ -1660,13 +1661,14 @@ GEM
pastel (~> 0.8.0)
thor (~> 1.3)
tty-command (~> 0.10.1)
sentry-rails (5.10.0)
sentry-rails (5.17.3)
railties (>= 5.0)
sentry-ruby (~> 5.10.0)
sentry-ruby (5.10.0)
sentry-ruby (~> 5.17.3)
sentry-ruby (5.17.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
sentry-sidekiq (5.10.0)
sentry-ruby (~> 5.10.0)
sentry-sidekiq (5.17.3)
sentry-ruby (~> 5.17.3)
sidekiq (>= 3.0)
sexp_processor (4.17.1)
shellany (0.0.1)
@ -2214,9 +2216,9 @@ DEPENDENCIES
seed-fu (~> 2.3.7)
selenium-webdriver (~> 4.19)
semver_dialects (~> 2.0, >= 2.0.2)
sentry-rails (~> 5.10.0)
sentry-ruby (~> 5.10.0)
sentry-sidekiq (~> 5.10.0)
sentry-rails (~> 5.17.3)
sentry-ruby (~> 5.17.3)
sentry-sidekiq (~> 5.17.3)
shoulda-matchers (~> 5.1.0)
sidekiq!
sidekiq-cron (~> 1.12.0)

View File

@ -62,7 +62,7 @@ export default {
</script>
<template>
<div class="board-new-issue-form gl-z-index-3 gl-m-3">
<div class="board-new-issue-form gl-z-3 gl-m-3">
<div class="board-card position-relative gl-p-5 rounded">
<gl-form @submit.prevent="handleFormSubmit" @reset="handleFormCancel">
<label :for="inputFieldId" class="gl-font-weight-bold">{{ __('Title') }}</label>

View File

@ -280,7 +280,7 @@ export default {
<div
v-if="job.archived"
class="gl-mt-3 gl-py-2 gl-px-3 gl-align-items-center gl-z-index-1 gl-m-auto archived-job"
class="gl-mt-3 gl-py-2 gl-px-3 gl-align-items-center gl-z-1 gl-m-auto archived-job"
:class="{ 'sticky-top gl-border-bottom-0': hasJobLog }"
data-testid="archived-job"
>

View File

@ -142,7 +142,7 @@ export default {
<gl-loading-icon
v-if="isSwitcherLoading"
data-testid="switcher-loading-state"
class="gl-absolute gl-w-full gl-bg-white gl-opacity-5 gl-z-index-2"
class="gl-absolute gl-w-full gl-bg-white gl-opacity-5 gl-z-2"
size="lg"
/>
<span class="gl-font-weight-bold">{{ $options.i18n.viewLabelText }}</span>

View File

@ -61,7 +61,7 @@ export default {
<tooltip-on-truncate :title="jobName" truncate-target="child" placement="top">
<div
:id="id"
class="gl-bg-white gl-shadow-inner-1-gray-100 gl-text-center gl-text-truncate gl-rounded-6 gl-mb-3 gl-px-5 gl-py-3 gl-relative gl-z-index-1 gl-transition-duration-slow gl-transition-timing-function-ease"
class="gl-bg-white gl-shadow-inner-1-gray-100 gl-text-center gl-text-truncate gl-rounded-6 gl-mb-3 gl-px-5 gl-py-3 gl-relative gl-z-1 gl-transition-duration-slow gl-transition-timing-function-ease"
:class="jobPillClasses"
@mouseover="onMouseEnter"
@mouseleave="onMouseLeave"

View File

@ -187,11 +187,11 @@ export default {
<div
v-if="isCodeSuggestion"
:contenteditable="false"
class="gl-relative gl-z-index-0"
class="gl-relative gl-z-0"
data-testid="code-suggestion-box"
>
<div
class="md-suggestion-header gl-flex-wrap gl-z-index-1 gl-w-full gl-border-none! gl-font-regular gl-px-4 gl-py-3 gl-border-b-1! gl-border-b-solid! gl-mr-n10!"
class="md-suggestion-header gl-flex-wrap gl-z-1 gl-w-full gl-border-none! gl-font-regular gl-px-4 gl-py-3 gl-border-b-1! gl-border-b-solid! gl-mr-n10!"
>
<div class="gl-font-weight-bold gl-pr-3">
{{ __('Suggested change') }}
@ -280,7 +280,7 @@ export default {
>
</div>
</div>
<node-view-content ref="nodeViewContent" as="code" class="gl-relative gl-z-index-1" />
<node-view-content ref="nodeViewContent" as="code" class="gl-relative gl-z-1" />
</node-view-wrapper>
</editor-state-observer>
</template>

View File

@ -13,7 +13,7 @@ export default {
<transition name="design-disclosure">
<aside
v-if="open"
class="design-disclosure gl-w-full gl-display-flex gl-flex-direction-column gl-relative gl-border-l gl-z-index-0 gl-bg-white gl-top-0 gl-right-0 gl-h-full gl-overflow-y-auto"
class="design-disclosure gl-w-full gl-display-flex gl-flex-direction-column gl-relative gl-border-l gl-z-0 gl-bg-white gl-top-0 gl-right-0 gl-h-full gl-overflow-y-auto"
>
<slot></slot>
</aside>

View File

@ -55,7 +55,7 @@ export default {
</script>
<template>
<gl-button-group class="gl-z-index-1">
<gl-button-group class="gl-z-1">
<gl-button
icon="dash"
:disabled="disableDecrease"

View File

@ -43,7 +43,7 @@ export default {
<template>
<gl-intersection-observer class="gl-px-4 gl-h-full" @appear="categoryAppeared">
<div class="gl-top-0 gl-py-3 gl-w-full gl-z-index-1 gl-font-sm emoji-picker-category-header">
<div class="gl-top-0 gl-py-3 gl-w-full gl-z-1 gl-font-sm emoji-picker-category-header">
<b>{{ categoryTitle }}</b>
</div>
<template v-if="emojis.length">

View File

@ -814,7 +814,7 @@ export default {
<stop-component
v-if="canStopEnvironment"
:environment="model"
class="gl-z-index-2"
class="gl-z-2"
data-track-action="click_button"
data-track-label="environment_stop"
/>

View File

@ -177,7 +177,7 @@ export default {
<div class="gl-relative gl-min-h-6">
<div
v-if="isLoading"
class="gl-absolute gl-top-0 gl-left-0 gl-w-full gl-h-full gl-z-index-200 gl-bg-gray-10 gl-opacity-3"
class="gl-absolute gl-top-0 gl-left-0 gl-w-full gl-h-full gl-z-200 gl-bg-gray-10 gl-opacity-3"
></div>
<gl-loading-icon v-if="isLoading" size="lg" class="gl-absolute gl-top-1/2 gl-left-1/2" />
<div v-if="isDeploymentTableShown">

View File

@ -82,7 +82,7 @@ export default {
<template>
<div
class="gl-display-flex gl-align-items-center ide-file-templates gl-relative gl-z-index-1"
class="gl-display-flex gl-align-items-center ide-file-templates gl-relative gl-z-1"
data-testid="file-templates-bar"
>
<strong class="gl-mr-3"> {{ $options.i18n.barLabel }} </strong>

View File

@ -26,7 +26,7 @@ export default {
<div class="d-flex gl-align-items-center">
<ci-icon
:status="job.status"
class="gl-align-items-center gl-border gl-display-inline-flex gl-z-index-1"
class="gl-align-items-center gl-border gl-display-inline-flex gl-z-1"
/>
<span class="gl-ml-3">
{{ job.name }}

View File

@ -92,7 +92,7 @@ export default {
</div>
</div>
<div class="gl-relative gl-w-full gl-h-13 gl-overflow-hidden">
<div class="gl-absolute gl-z-index-1 gl-font-monospace gl-text-transparent">
<div class="gl-absolute gl-z-1 gl-font-monospace gl-text-transparent">
<div
data-testid="highlights"
:style="{
@ -120,7 +120,7 @@ export default {
ref="textarea"
:placeholder="placeholder"
:value="text"
class="gl-absolute gl-w-full gl-h-full gl-z-index-2 gl-font-monospace p-0 gl-outline-0 gl-bg-transparent gl-border-0"
class="gl-absolute gl-w-full gl-h-full gl-z-2 gl-font-monospace p-0 gl-outline-0 gl-bg-transparent gl-border-0"
dir="auto"
name="commit-message"
@scroll="handleScroll"

View File

@ -767,7 +767,7 @@ export default {
</gl-empty-state>
<template v-else>
<div
class="gl-bg-gray-10 gl-border-solid gl-border-gray-200 gl-border-0 gl-border-b-1 gl-px-4 gl-display-flex gl-align-items-center gl-sticky gl-z-index-3 import-table-bar"
class="gl-bg-gray-10 gl-border-solid gl-border-gray-200 gl-border-0 gl-border-b-1 gl-px-4 gl-display-flex gl-align-items-center gl-sticky gl-z-3 import-table-bar"
>
<span data-test-id="selection-count">
<gl-sprintf :message="__('%{count} selected')">
@ -822,7 +822,7 @@ export default {
class="gl-w-full import-table"
:tbody-tr-class="rowClasses"
:tbody-tr-attr="qaRowAttributes"
thead-class="gl-sticky gl-z-index-2 gl-bg-gray-10"
thead-class="gl-sticky gl-z-2 gl-bg-gray-10"
:items="groupsTableData"
:fields="$options.fields"
selectable

View File

@ -110,7 +110,7 @@ export default {
<div class="create-timeline-event gl-relative gl-display-flex gl-align-items-start">
<div
v-if="hasTimelineEvents"
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-align-self-start gl-bg-white gl-text-gray-200 gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-full gl-mt-2 gl-w-8 gl-h-8 gl-flex-shrink-0 gl-p-3 gl-z-index-1"
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-align-self-start gl-bg-white gl-text-gray-200 gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-full gl-mt-2 gl-w-8 gl-h-8 gl-flex-shrink-0 gl-p-3 gl-z-1"
>
<gl-icon name="comment" class="note-icon" />
</div>

View File

@ -30,7 +30,7 @@ export default {
<template>
<div class="edit-timeline-event gl-relative gl-display-flex gl-align-items-center">
<div
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-align-self-start gl-bg-white gl-text-gray-200 gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-full gl-mt-2 gl-w-8 gl-h-8 gl-z-index-1"
class="gl-display-flex gl-align-items-center gl-justify-content-center gl-align-self-start gl-bg-white gl-text-gray-200 gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-full gl-mt-2 gl-w-8 gl-h-8 gl-z-1"
>
<gl-icon name="comment" class="note-icon" />
</div>

View File

@ -72,7 +72,7 @@ export default {
<template>
<div class="timeline-event gl-display-grid">
<div
class="timeline-event-icon gl--flex-center gl-bg-white gl-text-gray-200 gl-border gl-rounded-full gl-mt-2 gl-w-8 gl-h-8 gl-p-3 gl-z-index-1"
class="timeline-event-icon gl--flex-center gl-bg-white gl-text-gray-200 gl-border gl-rounded-full gl-mt-2 gl-w-8 gl-h-8 gl-p-3 gl-z-1"
>
<gl-icon :name="getEventIcon(action)" class="note-icon" />
</div>

View File

@ -79,7 +79,7 @@ export default {
<transition name="issuable-header-slide">
<div
v-if="show"
class="issue-sticky-header gl-fixed gl-z-index-3 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-100 gl-py-3"
class="issue-sticky-header gl-fixed gl-z-3 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-100 gl-py-3"
data-testid="issue-sticky-header"
>
<div

View File

@ -227,10 +227,10 @@ export default {
data-testid="placeholder-overlay"
>
<div
class="gl-absolute gl-top-0 gl-right-0 gl-bottom-0 gl-left-0 bg-white gl-opacity-5 gl-z-index-2"
class="gl-absolute gl-top-0 gl-right-0 gl-bottom-0 gl-left-0 bg-white gl-opacity-5 gl-z-2"
></div>
<div
class="gl-relative gl-h-full gl-display-flex gl-align-items-center gl-justify-content-center gl-z-index-3"
class="gl-relative gl-h-full gl-display-flex gl-align-items-center gl-justify-content-center gl-z-3"
>
<div class="gl-max-w-34">
<h4 data-testid="filename">{{ filename }}</h4>

View File

@ -120,7 +120,7 @@ export default {
:show="show"
:target="id"
:title="title"
:css-classes="['gl-z-index-200', 'release-tag-selector']"
:css-classes="['gl-z-200', 'release-tag-selector']"
placement="bottom"
triggers="manual"
container="content-body"

View File

@ -28,5 +28,5 @@ export default {
</script>
<template>
<div v-if="!hasError" ref="map" class="gl-h-100vh gl-z-index-0" data-testid="map"></div>
<div v-if="!hasError" ref="map" class="gl-h-100vh gl-z-0" data-testid="map"></div>
</template>

View File

@ -211,7 +211,7 @@ export default {
v-if="isFocused"
v-outside="closeDropdown"
data-testid="header-search-dropdown-menu"
class="header-search-dropdown-menu gl-overflow-y-auto gl-absolute gl-bg-white gl-border-1 gl-rounded-base gl-border-solid gl-border-gray-200 gl-shadow-x0-y2-b4-s0 gl-mt-3 gl-z-index-2 gl-w-full! gl-min-w-full! gl-max-w-none!"
class="header-search-dropdown-menu gl-overflow-y-auto gl-absolute gl-bg-white gl-border-1 gl-rounded-base gl-border-solid gl-border-gray-200 gl-shadow-x0-y2-b4-s0 gl-mt-3 gl-z-2 gl-w-full! gl-min-w-full! gl-max-w-none!"
>
<div class="header-search-dropdown-content gl-py-2">
<dropdown-keyboard-navigation

View File

@ -99,7 +99,7 @@ export default {
<gl-collapsible-listbox
v-model="selectedSortOptionTitle"
placement="right"
class="gl-z-index-1"
class="gl-z-1"
toggle-class="gl-rounded-top-right-none! gl-rounded-bottom-right-none!"
:toggle-text="selectedSortOptionTitle"
:items="listboxOptions"

View File

@ -121,7 +121,7 @@ export default {
<gl-alert
v-if="errorMessage"
sticky
class="gl-top-8 gl-z-index-1"
class="gl-top-8 gl-z-1"
data-testid="manage-via-mr-error-alert"
variant="danger"
@dismiss="dismissAlert"

View File

@ -126,7 +126,7 @@ export default {
<template>
<div
:id="`${targetId}-flyout`"
class="gl-fixed gl-p-4 gl-mx-n1 gl-z-index-9999 gl-max-h-full gl-overflow-y-auto"
class="gl-fixed gl-p-4 gl-mx-n1 gl-z-9999 gl-max-h-full gl-overflow-y-auto"
@mouseover="$emit('mouseover')"
@mouseleave="$emit('mouseleave')"
>

View File

@ -59,7 +59,7 @@ export default {
:size="12"
:aria-label="iconAriaLabel"
:data-testid="`status-${iconName}-icon`"
class="gl-relative gl-z-index-1"
class="gl-relative gl-z-1"
/>
</div>
</template>

View File

@ -133,7 +133,7 @@ export default {
<div
v-if="datePickerShown"
v-outside="handleClickOutside"
class="gl-absolute gl-z-index-1 gl-bg-white gl-border-1 gl-border-gray-200 gl-my-2 gl-p-4 gl-rounded-base gl-shadow-x0-y2-b4-s0 gl-top-full"
class="gl-absolute gl-z-1 gl-bg-white gl-border-1 gl-border-gray-200 gl-my-2 gl-p-4 gl-rounded-base gl-shadow-x0-y2-b4-s0 gl-top-full"
>
<gl-daterange-picker
:max-date-range="computedConfig.maxDateRange"

View File

@ -100,7 +100,7 @@ export default {
v-if="hoverMap[`code-${index}`]"
:title="$options.i18n.copyCodeTitle"
:text="block.text"
class="gl-absolute gl-top-3 gl-right-3 gl-z-index-1 gl-transition-duration-medium"
class="gl-absolute gl-top-3 gl-right-3 gl-z-1 gl-transition-duration-medium"
/>
<code-block-highlighted
class="gl-border gl-rounded-0! gl-p-4 gl-mb-0 gl-overflow-y-auto"

View File

@ -46,6 +46,12 @@ export default {
isSortAscending() {
return this.sorting.sort === ASCENDING_ORDER;
},
baselineQueryStringFilters() {
return this.tokens.reduce((acc, curr) => {
acc[curr.type] = null;
return acc;
}, {});
},
sortDirectionData() {
return this.isSortAscending ? SORT_DIRECTION_UI.asc : SORT_DIRECTION_UI.desc;
},
@ -57,25 +63,28 @@ export default {
generateQueryData({ sorting = {}, filter = [] } = {}) {
// Ensure that we clean up the query when we remove a token from the search
const result = {
...this.baselineQueryStringFilters,
...sorting,
search: null,
after: null,
before: null,
};
filter
.filter((f) => f.value.data)
.forEach((f) => {
if (f.type === FILTERED_SEARCH_TERM) {
if (result.search === null) {
result.search = [f.value.data];
} else {
result.search.push(f.value.data);
}
filter.forEach((f) => {
if (f.type === FILTERED_SEARCH_TERM) {
const value = f.value.data?.trim();
if (!value) return;
if (Array.isArray(result.search)) {
result.search.push(value);
} else {
result[f.type] = f.value.data;
result.search = [value];
}
});
} else {
result[f.type] = f.value.data;
}
});
return result;
},
onDirectionChange() {

View File

@ -35,7 +35,7 @@ export default {
<template>
<div class="gl-display-flex">
<div
class="gl-p-0! gl-absolute gl-z-index-3 diff-line-num gl-border-r gl-display-flex line-links line-numbers"
class="gl-p-0! gl-absolute gl-z-3 diff-line-num gl-border-r gl-display-flex line-links line-numbers"
>
<a
class="gl-select-none gl-shadow-none! file-line-blame gl-mx-n2 gl-flex-grow-1"

View File

@ -89,7 +89,7 @@ export default {
v-for="(n, index) in totalLines"
:key="index"
data-testid="line-numbers"
class="gl-p-0! gl-z-index-3 diff-line-num gl-border-r gl-display-flex line-links line-numbers"
class="gl-p-0! gl-z-3 diff-line-num gl-border-r gl-display-flex line-links line-numbers"
>
<a
class="gl-select-none gl-shadow-none! file-line-blame"

View File

@ -87,7 +87,7 @@ export default {
<transition name="issuable-header-slide">
<div
v-if="stickyTitleVisible"
class="issue-sticky-header gl-fixed gl-z-index-3 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-100 gl-py-3"
class="issue-sticky-header gl-fixed gl-z-3 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-100 gl-py-3"
data-testid="header"
>
<div class="issue-sticky-header-text gl-display-flex gl-align-items-baseline gl-mx-auto">

View File

@ -103,7 +103,7 @@ export default {
class="disclosure-hierarchy-button"
:aria-label="ellipsisTooltipLabel"
>
<gl-icon name="ellipsis_h" class="gl-ml-3 gl-text-gray-600 gl-z-index-200" />
<gl-icon name="ellipsis_h" class="gl-ml-3 gl-text-gray-600 gl-z-200" />
</button>
</template>
<template #list-item="{ item }">

View File

@ -51,7 +51,7 @@ export default {
:name="item.icon"
class="gl-mx-2 gl-text-gray-600 gl-flex-shrink-0"
/>
<span class="gl-z-index-200 gl-text-truncate">{{ item.title }}</span>
<span class="gl-z-200 gl-text-truncate">{{ item.title }}</span>
</gl-link>
<!--
@slot Additional content to be displayed in an item.

View File

@ -91,7 +91,7 @@ export default {
<transition name="issuable-header-slide">
<div
v-if="isStickyHeaderShowing"
class="issue-sticky-header gl-fixed gl-bg-white gl-border-b gl-z-index-3 gl-py-2"
class="issue-sticky-header gl-fixed gl-bg-white gl-border-b gl-z-3 gl-py-2"
data-testid="work-item-sticky-header"
>
<div

View File

@ -13,7 +13,7 @@
.home-panel-description-markdown.read-more-container{ itemprop: 'description', data: { 'read-more-height': 320 } }
.read-more-content.read-more-content--has-scrim
= markdown_field(@project, :description)
.js-read-more-trigger.gl-display-none.gl-w-full.gl-h-8.gl-absolute.gl-bottom-0.gl-z-index-2.gl-bg-white
.js-read-more-trigger.gl-display-none.gl-w-full.gl-h-8.gl-absolute.gl-bottom-0.gl-z-2.gl-bg-white
= render Pajamas::ButtonComponent.new(variant: :link, button_options: { 'aria-label': _("Expand project information") }) do
= sprite_icon('chevron-down', size: 14)
= _("Read more")

View File

@ -24,7 +24,7 @@
- text = tag.span(sprite_icon('history')) + tag.span(_('Recent searches'), class: "gl-sr-only")
= dropdown_tag(text,
options: { wrapper_class: "filtered-search-history-dropdown-wrapper",
toggle_class: "gl-button btn btn-default filtered-search-history-dropdown-toggle-button gl-pl-4! gl-pr-5!",
toggle_class: "gl-button btn btn-default filtered-search-history-dropdown-toggle-button",
dropdown_class: "filtered-search-history-dropdown",
content_class: "filtered-search-history-dropdown-content" }) do
.js-filtered-search-history-dropdown{ data: { full_path: search_history_storage_prefix } }

View File

@ -11,7 +11,7 @@
.gl-ml-auto
= link_to _('Edit file'), edit_blob_path(@user.user_project, @user.user_project.default_branch, @user.user_readme.path)
= render 'projects/blob/viewer', viewer: @user.user_readme.rich_viewer, load_async: false
.js-read-more-trigger.read-more-trigger.gl-h-8.gl-absolute.gl-z-index-2.gl-bg-white.gl-px-6.gl-rounded-bottom-base
.js-read-more-trigger.read-more-trigger.gl-h-8.gl-absolute.gl-z-2.gl-bg-white.gl-px-6.gl-rounded-bottom-base
= render Pajamas::ButtonComponent.new(variant: :link, button_options: { class: 'gl-mt-4 gl-ml-n1', 'aria-label': _("Expand Readme") }) do
= sprite_icon('chevron-down', size: 14, css_class: 'gl-mr-1 gl-mb-n1')
= _("Read more")

View File

@ -0,0 +1,43 @@
import chokidar from 'chokidar';
/**
* This vite plugin automatically stops vite if
*
* 1. a new dependency install happened, because it could affect vite itself
* 2. a new entry point is created, because right now our entry points are
* statically looked at during start up
*/
export function AutoStopPlugin() {
return {
name: 'vite-plugin-auto-stop',
configureServer(server) {
const nodeModulesWatcher = chokidar.watch(['node_modules/.yarn-integrity'], {
ignoreInitial: true,
});
const pageEntrypointsWatcher = chokidar.watch(
[
'app/assets/javascripts/pages/**/*.js',
'ee/app/assets/javascripts/pages/**/*.js',
'jh/app/assets/javascripts/pages/**/*.js',
],
{
ignoreInitial: true,
},
);
// GDK will restart Vite server for us
const stop = () => process.kill(process.pid);
pageEntrypointsWatcher.on('add', stop);
pageEntrypointsWatcher.on('unlink', stop);
nodeModulesWatcher.on('add', stop);
nodeModulesWatcher.on('change', stop);
nodeModulesWatcher.on('unlink', stop);
server.httpServer?.addListener?.('close', () => {
pageEntrypointsWatcher.close();
nodeModulesWatcher.close();
});
},
};
}

View File

@ -0,0 +1,73 @@
import path from 'node:path';
import { copyFile, mkdir, stat } from 'node:fs/promises';
import globby from 'globby';
/**
* This is a simple-reimplementation of the copy-webpack-plugin
*
* it also uses the `globby` package under the hood, and _only_ allows for copying
* 1. absolute paths
* 2. files and directories.
*/
export function CopyPlugin({ patterns }) {
return {
name: 'vite-plugin-copy',
async configureServer() {
console.warn('Start copying files...');
let count = 0;
const allTheFiles = patterns.map(async (patternEntry) => {
const { from, to, globOptions = {} } = patternEntry;
// By only supporting absolute paths we simplify
// the implementation a lot
if (!path.isAbsolute(from)) {
throw new Error(`'from' path is not absolute: ${path}`);
}
if (!path.isAbsolute(to)) {
throw new Error(`'to' path is not absolute: ${path}`);
}
let pattern = '';
let sourceRoot = '';
const fromStat = await stat(from);
if (fromStat.isDirectory()) {
sourceRoot = from;
pattern = path.join(from, '**/*');
} else if (fromStat.isFile()) {
sourceRoot = path.dirname(from);
pattern = from;
} else {
// No need to support globs, because we do not
// use them yet...
throw new Error('Our implementation does not support globs.');
}
globOptions.dot = globOptions.dot ?? true;
const paths = await globby(pattern, globOptions);
return paths.map((srcPath) => {
const targetPath = path.join(to, path.relative(sourceRoot, srcPath));
return { srcPath, targetPath };
});
});
const srcTargetMap = (await Promise.all(allTheFiles)).flat();
await Promise.all(
srcTargetMap.map(async ({ srcPath, targetPath }) => {
try {
await mkdir(path.dirname(targetPath), { recursive: true });
await copyFile(srcPath, targetPath);
count += 1;
} catch (e) {
console.warn(`Could not copy ${srcPath} => ${targetPath}`);
}
}),
);
console.warn(`Done copying ${count} files...`);
},
};
}

View File

@ -0,0 +1,46 @@
import { generateEntries } from '../webpack.helpers';
const comment = '/* this is a virtual module used by Vite, it exists only in dev mode */\n';
export const virtualEntrypoints = Object.entries(generateEntries()).reduce(
(acc, [entryName, imports]) => {
const modulePath = imports[imports.length - 1];
const importPath = modulePath.startsWith('./') ? `~/${modulePath.substring(2)}` : modulePath;
acc[`${entryName}.js`] = `${comment}/* ${modulePath} */ import '${importPath}';\n`;
return acc;
},
{},
);
const entrypointsDir = '/javascripts/entrypoints/';
/**
* This Plugin provides virtual entrypoints for our automatic
* rails-route to entrypoint mapping during development
*
* For example on a rails route:
* foo:bar:show
* it tries to load:
* ~/pages/foo/bar/show/index.js
* ~/pages/foo/bar/index.js
* ~/pages/foo/index.js
*
* if the JH/EE files exist, they take precendence over the CE file.
*
* If the file doesn't exist, it loads an empty JS file.
*/
export function PageEntrypointsPlugin() {
return {
name: 'vite-plugin-page-entrypoints',
load(id) {
if (!id.startsWith('pages.')) {
return undefined;
}
return virtualEntrypoints[id] ?? `/* doesn't exist */`;
},
resolveId(source) {
const fixedSource = source.replace(entrypointsDir, '');
if (fixedSource.startsWith('pages.')) return { id: fixedSource };
return undefined;
},
};
}

View File

@ -0,0 +1,30 @@
import RubyPlugin from 'vite-plugin-ruby';
const [rubyPlugin, ...rest] = RubyPlugin.default();
/**
* A fixed version of vite-plugin-ruby
*
* We can't use regular 'resolve' which points to sourceCodeDir in vite.json
* Because we need for '~' alias to resolve to app/assets/javascripts
* We can't use javascripts folder in sourceCodeDir because we also need to resolve other assets
* With undefined 'resolve' an '~' alias from Webpack config is used instead
* See the issue for details: https://github.com/ElMassimo/vite_ruby/issues/237
*/
export function FixedRubyPlugin() {
return [
{
...rubyPlugin,
name: 'vite-plugin-ruby-fixed',
config: (...args) => {
const originalConfig = rubyPlugin.config(...args);
return {
...originalConfig,
resolve: undefined,
};
},
},
...rest,
];
}

View File

@ -7,4 +7,9 @@ Time.zone = Gitlab.config.gitlab.time_zone || Time.zone
# runs. We set the default to ensure multi-threaded servers have the
# right value.
Time.zone_default = Time.zone
Rails.application.config.time_zone = Time.zone
# Time.zone format is '(GMT+00:00) UTC', which causes
# (TZInfo::InvalidTimezoneIdentifier) when accessed as
# ::ActiveSupport::TimeZone.find_tzinfo(::Rails.application.config.time_zone)
# by sentry-rails https://gitlab.com/gitlab-org/gitlab/-/merge_requests/150621#note_1878079953
Rails.application.config.time_zone = Time.zone.name

View File

@ -125,6 +125,13 @@ module.exports = {
'x0-y2-b4-s0': '0 2px 4px 0 #0000001a',
'x0-y0-b3-s1-blue-500': 'inset 0 0 3px 1px var(--blue-500, #1f75cb)',
},
zIndex: {
1: '1',
2: '2',
3: '3',
200: '200',
9999: '9999',
},
},
},
plugins: [

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
class RemoveUniqueIndexForMlModelPackagesOnProjectIdNameVersion < Gitlab::Database::Migration[2.2]
disable_ddl_transaction!
milestone '17.0'
def up
remove_concurrent_index_by_name :packages_packages, 'uniq_idx_packages_packages_on_project_id_name_version_ml_model'
end
def down
# NOOP, this reading this index could cause errors when there are packages pending destruction
end
end

View File

@ -0,0 +1,28 @@
# frozen_string_literal: true
class AddUniqueIndexForMlModelPackagesOnProjectIdNameVersion < Gitlab::Database::Migration[2.2]
milestone '17.0'
disable_ddl_transaction!
INDEX_NAME = 'uniq_idx_packages_packages_on_project_id_name_version_ml_model'
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/packages/package.rb#L30
PACKAGE_TYPE_ML_MODEL = 14
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/packages/package.rb#L33
PACKAGE_STATUS_PENDING_DESTRUCTION = 4
def up
add_concurrent_index(
:packages_packages,
%i[project_id name version],
name: INDEX_NAME,
unique: true,
where: "package_type = #{PACKAGE_TYPE_ML_MODEL} AND status <> #{PACKAGE_STATUS_PENDING_DESTRUCTION}"
)
end
def down
remove_concurrent_index_by_name :packages_packages, INDEX_NAME
end
end

View File

@ -0,0 +1 @@
6912713c356a4f9cfa679e7565a48fcc6ee7af43468a33220f3dd52123d8b3c7

View File

@ -0,0 +1 @@
84d5048f664540e6fad886e03a992e47ea849b4d1e0978711d40338ebbae4084

View File

@ -28181,7 +28181,7 @@ CREATE UNIQUE INDEX uniq_audit_instance_event_filters_destination_id_and_event_t
CREATE UNIQUE INDEX uniq_google_cloud_logging_configuration_namespace_id_and_name ON audit_events_google_cloud_logging_configurations USING btree (namespace_id, name);
CREATE UNIQUE INDEX uniq_idx_packages_packages_on_project_id_name_version_ml_model ON packages_packages USING btree (project_id, name, version) WHERE (package_type = 14);
CREATE UNIQUE INDEX uniq_idx_packages_packages_on_project_id_name_version_ml_model ON packages_packages USING btree (project_id, name, version) WHERE ((package_type = 14) AND (status <> 4));
CREATE UNIQUE INDEX uniq_idx_streaming_group_destination_id_and_namespace_id ON audit_events_streaming_group_namespace_filters USING btree (external_streaming_destination_id, namespace_id);

View File

@ -8,10 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
DETAILS:
**Tier:** Free, Premium, Ultimate
**Offering:** Self-managed
> - It's enabled on GitLab.com.
> - It's recommended for production use.
**Offering:** GitLab.com, Self-managed
Usage Trends gives you an overview of how much data your instance contains, and how quickly this volume is changing over time.
Usage Trends data refreshes daily.

View File

@ -36,12 +36,14 @@ dast:
GIT_STRATEGY: none
allow_failure: true
script:
- export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)}
- if [ -z "$DAST_WEBSITE$DAST_API_SPECIFICATION" ]; then echo "Either DAST_WEBSITE or DAST_API_SPECIFICATION must be set. See https://docs.gitlab.com/ee/user/application_security/dast/#configuration for more details." && exit 1; fi
- if [[ -f "environment_url.txt" ]]; then DAST_WEBSITE="${DAST_WEBSITE:-$(cat environment_url.txt)}"; export DAST_WEBSITE; fi
- /analyze
artifacts:
when: always
reports:
dast: gl-dast-report.json
paths:
- gl-dast-*.*
rules:
- if: $DAST_DISABLED == 'true' || $DAST_DISABLED == '1'
when: never
@ -65,6 +67,6 @@ dast:
- if: $CI_COMMIT_BRANCH &&
$GITLAB_FEATURES =~ /\bdast\b/
after_script:
# Remove any debug.log files because they might contain secrets.
# For DAST 4 compatibility, remove any debug.log files because they might contain secrets.
- rm -f /zap/wrk/**/debug.log
- cp -r /zap/wrk dast_artifacts

View File

@ -15,9 +15,9 @@
# - test
# - deploy
# - dast
#
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/dast/
#
# Configure DAST with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/index.html).
# List of available variables: https://docs.gitlab.com/ee/user/application_security/dast/#available-variables
@ -36,14 +36,14 @@ dast:
GIT_STRATEGY: none
allow_failure: true
script:
- export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)}
- if [ -z "$DAST_WEBSITE$DAST_API_SPECIFICATION" ]; then echo "Either DAST_WEBSITE or DAST_API_SPECIFICATION must be set. See https://docs.gitlab.com/ee/user/application_security/dast/#configuration for more details." && exit 1; fi
- if [[ -f "environment_url.txt" ]]; then DAST_WEBSITE="${DAST_WEBSITE:-$(cat environment_url.txt)}"; export DAST_WEBSITE; fi
- /analyze
artifacts:
paths:
- dast_artifacts/*
when: always
reports:
dast: gl-dast-report.json
paths:
- gl-dast-*.*
rules:
- if: $DAST_DISABLED == 'true' || $DAST_DISABLED == '1'
when: never
@ -84,6 +84,6 @@ dast:
- if: $CI_COMMIT_BRANCH &&
$GITLAB_FEATURES =~ /\bdast\b/
after_script:
# Remove any debug.log files because they might contain secrets.
# For DAST 4 compatibility, remove any debug.log files because they might contain secrets.
- rm -f /zap/wrk/**/debug.log
- cp -r /zap/wrk dast_artifacts

View File

@ -37,6 +37,13 @@ module Gitlab
config.send_default_pii = true
config.send_modules = false
config.traces_sample_rate = 0.2 if Gitlab::Utils.to_boolean(ENV['ENABLE_SENTRY_PERFORMANCE_MONITORING'])
# Reason for disabling the below configs https://gitlab.com/gitlab-org/gitlab/-/merge_requests/150771#note_1881953691
config.metrics.enabled = false
config.metrics.enable_code_locations = false
config.propagate_traces = false
config.trace_propagation_targets = []
config.enabled_patches = []
config.enable_tracing = false
yield config if block_given?
end

View File

@ -5,13 +5,17 @@ module QA
module Project
module Settings
class Integrations < QA::Page::Base
# rubocop:disable QA/ElementWithPattern -- required for qa:selectors job to pass
view 'app/assets/javascripts/integrations/index/components/integrations_table.vue' do
element 'jenkins-link', %q(:data-testid="`${item.name}-link`") # rubocop:disable QA/ElementWithPattern -- required for qa:selectors job to pass
element 'prometheus-link', %q(:data-testid="`${item.name}-link`") # rubocop:disable QA/ElementWithPattern -- required for qa:selectors job to pass
element 'jira-link', %q(:data-testid="`${item.name}-link`") # rubocop:disable QA/ElementWithPattern -- required for qa:selectors job to pass
element 'pipelines_email-link', %q(:data-testid="`${item.name}-link`") # rubocop:disable QA/ElementWithPattern -- required for qa:selectors job to pass
element 'gitlab_slack_application-link', %q(:data-testid="`${item.name}-link`") # rubocop:disable QA/ElementWithPattern -- required for qa:selectors job to pass
element 'jenkins-link', %q(:data-testid="`${item.name}-link`")
element 'prometheus-link', %q(:data-testid="`${item.name}-link`")
element 'jira-link', %q(:data-testid="`${item.name}-link`")
element 'pipelines_email-link', %q(:data-testid="`${item.name}-link`")
element 'gitlab_slack_application-link', %q(:data-testid="`${item.name}-link`")
element 'google_cloud_platform_workload_identity_federation-link', %q(:data-testid="`${item.name}-link`")
element 'google_cloud_platform_artifact_registry-link', %q(:data-testid="`${item.name}-link`")
end
# rubocop:enable QA/ElementWithPattern
def click_on_prometheus_integration
click_element('prometheus-link')
@ -37,3 +41,5 @@ module QA
end
end
end
QA::Page::Project::Settings::Integrations.prepend_mod_with("Page::Project::Settings::Integrations", namespace: QA)

View File

@ -20,6 +20,7 @@ describe('Registry Search', () => {
};
const defaultQueryChangedPayload = {
foo: null,
orderBy: 'name',
search: null,
sort: 'asc',

View File

@ -2,7 +2,7 @@
exports[`Chunk component rendering isHighlighted is true renders line numbers 1`] = `
<div
class="diff-line-num gl-border-r gl-display-flex gl-p-0! gl-z-index-3 line-links line-numbers"
class="diff-line-num gl-border-r gl-display-flex gl-p-0! gl-z-3 line-links line-numbers"
data-testid="line-numbers"
>
<a

View File

@ -184,6 +184,21 @@ RSpec.shared_examples 'shared package filtering' do
'sort' => 'desc'
)
end
context 'when cleared' do
before do
wait_for_requests
click_button 'Clear'
end
it 'resets query params' do
queryparams = Rack::Utils.parse_query(URI.parse(current_url).query)
expect(queryparams).to eq(
'orderBy' => 'created_at',
'sort' => 'desc'
)
end
end
end
end

View File

@ -1,16 +1,11 @@
import { readFileSync } from 'node:fs';
import { stat, mkdir, copyFile } from 'node:fs/promises';
import path from 'node:path';
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue2';
import graphql from '@rollup/plugin-graphql';
import RubyPlugin from 'vite-plugin-ruby';
import chokidar from 'chokidar';
import globby from 'globby';
import { viteCommonjs } from '@originjs/vite-plugin-commonjs';
import webpackConfig from './config/webpack.config';
import { generateEntries } from './config/webpack.helpers';
import {
IS_EE,
IS_JH,
@ -21,6 +16,13 @@ import {
/* eslint-disable import/extensions */
import { viteCSSCompilerPlugin } from './scripts/frontend/lib/compile_css.mjs';
import { viteTailwindCompilerPlugin } from './scripts/frontend/tailwindcss.mjs';
import { CopyPlugin } from './config/helpers/vite_plugin_copy.mjs';
import { AutoStopPlugin } from './config/helpers/vite_plugin_auto_stop.mjs';
import {
PageEntrypointsPlugin,
virtualEntrypoints,
} from './config/helpers/vite_plugin_page_entrypoints.mjs';
import { FixedRubyPlugin } from './config/helpers/vite_plugin_ruby_fixed.mjs';
/* eslint-enable import/extensions */
let viteGDKConfig;
@ -42,36 +44,6 @@ const javascriptsPath = path.resolve(assetsPath, 'javascripts');
const emptyComponent = path.resolve(javascriptsPath, 'vue_shared/components/empty_component.js');
const [rubyPlugin, ...rest] = RubyPlugin();
const comment = '/* this is a virtual module used by Vite, it exists only in dev mode */\n';
const virtualEntrypoints = Object.entries(generateEntries()).reduce((acc, [entryName, imports]) => {
const modulePath = imports[imports.length - 1];
const importPath = modulePath.startsWith('./') ? `~/${modulePath.substring(2)}` : modulePath;
acc[`${entryName}.js`] = `${comment}/* ${modulePath} */ import '${importPath}';\n`;
return acc;
}, {});
// We can't use regular 'resolve' which points to sourceCodeDir in vite.json
// Because we need for '~' alias to resolve to app/assets/javascripts
// We can't use javascripts folder in sourceCodeDir because we also need to resolve other assets
// With undefined 'resolve' an '~' alias from Webpack config is used instead
// See the issue for details: https://github.com/ElMassimo/vite_ruby/issues/237
const fixedRubyPlugin = [
{
...rubyPlugin,
config: (...args) => {
const originalConfig = rubyPlugin.config(...args);
return {
...originalConfig,
resolve: undefined,
};
},
},
...rest,
];
const EE_ALIAS_FALLBACK = [
{
find: /^ee_component\/(.*)\.vue/,
@ -86,124 +58,6 @@ const JH_ALIAS_FALLBACK = [
},
];
const autoRestartPlugin = {
configureServer(server) {
const nodeModulesWatcher = chokidar.watch(['node_modules/.yarn-integrity'], {
ignoreInitial: true,
});
const pageEntrypointsWatcher = chokidar.watch(
[
'app/assets/javascripts/pages/**/*.js',
'ee/app/assets/javascripts/pages/**/*.js',
'jh/app/assets/javascripts/pages/**/*.js',
],
{
ignoreInitial: true,
},
);
// GDK will restart Vite server for us
const stop = () => process.kill(process.pid);
pageEntrypointsWatcher.on('add', stop);
pageEntrypointsWatcher.on('unlink', stop);
nodeModulesWatcher.on('add', stop);
nodeModulesWatcher.on('change', stop);
nodeModulesWatcher.on('unlink', stop);
server.httpServer?.addListener?.('close', () => {
pageEntrypointsWatcher.close();
nodeModulesWatcher.close();
});
},
};
/**
* This is a simple-reimplementation of the copy-webpack-plugin
*
* it also uses the `globby` package under the hood, and _only_ allows for copying
* 1. absolute paths
* 2. files and directories.
*/
function viteCopyPlugin({ patterns }) {
return {
name: 'viteCopyPlugin',
async configureServer() {
console.warn('Start copying files...');
let count = 0;
const allTheFiles = patterns.map(async (patternEntry) => {
const { from, to, globOptions = {} } = patternEntry;
// By only supporting absolute paths we simplify
// the implementation a lot
if (!path.isAbsolute(from)) {
throw new Error(`'from' path is not absolute: ${path}`);
}
if (!path.isAbsolute(to)) {
throw new Error(`'to' path is not absolute: ${path}`);
}
let pattern = '';
let sourceRoot = '';
const fromStat = await stat(from);
if (fromStat.isDirectory()) {
sourceRoot = from;
pattern = path.join(from, '**/*');
} else if (fromStat.isFile()) {
sourceRoot = path.dirname(from);
pattern = from;
} else {
// No need to support globs, because we do not
// use them yet...
throw new Error('Our implementation does not support globs.');
}
globOptions.dot = globOptions.dot ?? true;
const paths = await globby(pattern, globOptions);
return paths.map((srcPath) => {
const targetPath = path.join(to, path.relative(sourceRoot, srcPath));
return { srcPath, targetPath };
});
});
const srcTargetMap = (await Promise.all(allTheFiles)).flat();
await Promise.all(
srcTargetMap.map(async ({ srcPath, targetPath }) => {
try {
await mkdir(path.dirname(targetPath), { recursive: true });
await copyFile(srcPath, targetPath);
count += 1;
} catch (e) {
console.warn(`Could not copy ${srcPath} => ${targetPath}`);
}
}),
);
console.warn(`Done copying ${count} files...`);
},
};
}
const entrypointsDir = '/javascripts/entrypoints/';
const pageEntrypointsPlugin = {
name: 'page-entrypoints',
load(id) {
if (!id.startsWith('pages.')) {
return undefined;
}
return virtualEntrypoints[id] ?? `/* doesn't exist */`;
},
resolveId(source) {
const fixedSource = source.replace(entrypointsDir, '');
if (fixedSource.startsWith('pages.')) return { id: fixedSource };
return undefined;
},
};
export default defineConfig({
cacheDir: path.resolve(__dirname, 'tmp/cache/vite'),
resolve: {
@ -222,14 +76,14 @@ export default defineConfig({
],
},
plugins: [
pageEntrypointsPlugin,
PageEntrypointsPlugin(),
viteCSSCompilerPlugin({ shouldWatch: viteGDKConfig.hmr !== null }),
viteTailwindCompilerPlugin({ shouldWatch: viteGDKConfig.hmr !== null }),
viteCopyPlugin({
CopyPlugin({
patterns: copyFilesPatterns,
}),
viteGDKConfig.enabled ? autoRestartPlugin : null,
fixedRubyPlugin,
viteGDKConfig.enabled ? AutoStopPlugin() : null,
FixedRubyPlugin(),
vue({
template: {
compilerOptions: {