Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/diffs/components/app.vue15
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_item.vue239
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_list_root.vue124
-rw-r--r--app/assets/javascripts/issues_list/components/issue_card_time_info.vue17
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue5
-rw-r--r--app/assets/stylesheets/pages/issuable.scss54
-rw-r--r--app/controllers/projects/merge_requests_controller.rb1
-rw-r--r--config/feature_flags/development/mr_changes_fluid_layout.yml8
-rw-r--r--config/initializers/backtrace_silencers.rb2
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md26
-rw-r--r--doc/ci/chatops/index.md2
-rw-r--r--doc/ci/variables/predefined_variables.md1
-rw-r--r--doc/update/restore_after_failure.md46
-rw-r--r--doc/user/application_security/dependency_scanning/analyzers.md6
-rw-r--r--doc/user/application_security/dependency_scanning/index.md12
-rw-r--r--lib/gitlab/chat/command.rb3
-rw-r--r--locale/gitlab.pot3
-rw-r--r--package.json2
-rw-r--r--spec/frontend/diffs/components/app_spec.js19
-rw-r--r--spec/frontend/issuable_list/components/issuable_item_spec.js15
-rw-r--r--spec/frontend/vue_shared/components/issue/issue_assignees_spec.js4
-rw-r--r--spec/lib/gitlab/chat/command_spec.rb1
-rw-r--r--yarn.lock8
23 files changed, 311 insertions, 302 deletions
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index a2ea42e963c..465f9836140 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -19,6 +19,7 @@ import { updateHistory } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import MrWidgetHowToMergeModal from '~/vue_merge_request_widget/components/mr_widget_how_to_merge_modal.vue';
import PanelResizer from '~/vue_shared/components/panel_resizer.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import notesEventHub from '../../notes/event_hub';
import {
@@ -79,6 +80,7 @@ export default {
MrWidgetHowToMergeModal,
GlAlert,
},
+ mixins: [glFeatureFlagsMixin()],
alerts: {
ALERT_OVERFLOW_HIDDEN,
ALERT_MERGE_CONFLICT,
@@ -252,6 +254,10 @@ export default {
return this.treeWidth <= TREE_HIDE_STATS_WIDTH;
},
isLimitedContainer() {
+ if (this.glFeatures.mrChangesFluidLayout) {
+ return false;
+ }
+
return !this.renderFileTree && !this.isParallelView && !this.isFluidLayout;
},
isFullChangeset() {
@@ -386,6 +392,8 @@ export default {
diffsApp.instrument();
},
created() {
+ this.mergeRequestContainers = document.querySelectorAll('.merge-request-container');
+
this.adjustView();
this.subscribeToEvents();
@@ -513,6 +521,13 @@ export default {
} else {
this.removeEventListeners();
}
+
+ if (!this.isFluidLayout && this.glFeatures.mrChangesFluidLayout) {
+ this.mergeRequestContainers.forEach((el) => {
+ el.classList.toggle('limit-container-width', !this.shouldShow);
+ el.classList.toggle('container-limited', !this.shouldShow);
+ });
+ }
},
setEventListeners() {
Mousetrap.bind(keysFor(MR_PREVIOUS_FILE_IN_DIFF), () => this.jumpToFile(-1));
diff --git a/app/assets/javascripts/issuable_list/components/issuable_item.vue b/app/assets/javascripts/issuable_list/components/issuable_item.vue
index df9d5c86a4b..ab04c6a38a5 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_item.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_item.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink, GlIcon, GlLabel, GlFormCheckbox, GlTooltipDirective } from '@gitlab/ui';
+import { GlLink, GlIcon, GlLabel, GlFormCheckbox, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { isScopedLabel } from '~/lib/utils/common_utils';
@@ -15,6 +15,7 @@ export default {
GlIcon,
GlLabel,
GlFormCheckbox,
+ GlSprintf,
IssuableAssignees,
},
directives: {
@@ -82,9 +83,7 @@ export default {
return this.issuable.assignees?.nodes || this.issuable.assignees || [];
},
createdAt() {
- return sprintf(__('created %{timeAgo}'), {
- timeAgo: getTimeago().format(this.issuable.createdAt),
- });
+ return getTimeago().format(this.issuable.createdAt);
},
updatedAt() {
return sprintf(__('updated %{timeAgo}'), {
@@ -164,132 +163,132 @@ export default {
<template>
<li
:id="`issuable_${issuableId}`"
- class="issue gl-px-5!"
+ class="issue gl-display-flex! gl-px-5!"
:class="{ closed: issuable.closedAt, today: createdInPastDay }"
:data-labels="labelIdsString"
>
- <div class="issuable-info-container">
- <div v-if="showCheckbox" class="issue-check">
- <gl-form-checkbox
- class="gl-mr-0"
- :checked="checked"
- :data-id="issuableId"
- @input="$emit('checked-input', $event)"
+ <gl-form-checkbox
+ v-if="showCheckbox"
+ class="issue-check gl-mr-0"
+ :checked="checked"
+ :data-id="issuableId"
+ @input="$emit('checked-input', $event)"
+ >
+ <span class="gl-sr-only">{{ issuable.title }}</span>
+ </gl-form-checkbox>
+ <div class="issuable-main-info">
+ <div data-testid="issuable-title" class="issue-title title">
+ <gl-icon
+ v-if="issuable.confidential"
+ v-gl-tooltip
+ name="eye-slash"
+ :title="__('Confidential')"
+ :aria-label="__('Confidential')"
+ />
+ <gl-link class="issue-title-text" dir="auto" :href="webUrl" v-bind="issuableTitleProps">
+ {{ issuable.title }}
+ <gl-icon v-if="isIssuableUrlExternal" name="external-link" class="gl-ml-2" />
+ </gl-link>
+ <span
+ v-if="taskStatus"
+ class="task-status gl-display-none gl-sm-display-inline-block! gl-ml-3"
+ data-testid="task-status"
>
- <span class="gl-sr-only">{{ issuable.title }}</span>
- </gl-form-checkbox>
+ {{ taskStatus }}
+ </span>
</div>
- <div class="issuable-main-info">
- <div data-testid="issuable-title" class="issue-title title">
- <span class="issue-title-text" dir="auto">
- <gl-icon
- v-if="issuable.confidential"
- v-gl-tooltip
- name="eye-slash"
- :title="__('Confidential')"
- :aria-label="__('Confidential')"
- />
- <gl-link :href="webUrl" v-bind="issuableTitleProps">
- {{ issuable.title
- }}<gl-icon v-if="isIssuableUrlExternal" name="external-link" class="gl-ml-2"
- /></gl-link>
- </span>
- <span
- v-if="taskStatus"
- class="task-status gl-display-none gl-sm-display-inline-block! gl-ml-3"
- data-testid="task-status"
- >
- {{ taskStatus }}
- </span>
- </div>
- <div class="issuable-info">
- <slot v-if="hasSlotContents('reference')" name="reference"></slot>
- <span v-else data-testid="issuable-reference" class="issuable-reference">
- {{ reference }}
- </span>
- <span class="issuable-authored gl-display-none gl-sm-display-inline-block! gl-mr-3">
- <span aria-hidden="true">&middot;</span>
- <span
- v-gl-tooltip:tooltipcontainer.bottom
- data-testid="issuable-created-at"
- :title="tooltipTitle(issuable.createdAt)"
- >{{ createdAt }}</span
- >
- {{ __('by') }}
- <slot v-if="hasSlotContents('author')" name="author"></slot>
- <gl-link
- v-else
- :data-user-id="authorId"
- :data-username="author.username"
- :data-name="author.name"
- :data-avatar-url="author.avatarUrl"
- :href="author.webUrl"
- data-testid="issuable-author"
- class="author-link js-user-link"
- >
- <span class="author">{{ author.name }}</span>
- </gl-link>
+ <div class="issuable-info">
+ <slot v-if="hasSlotContents('reference')" name="reference"></slot>
+ <span v-else data-testid="issuable-reference" class="issuable-reference">
+ {{ reference }}
+ </span>
+ <span class="gl-display-none gl-sm-display-inline-block">
+ <span aria-hidden="true">&middot;</span>
+ <span class="issuable-authored gl-mr-3">
+ <gl-sprintf :message="__('created %{timeAgo} by %{author}')">
+ <template #timeAgo>
+ <span
+ v-gl-tooltip.bottom
+ :title="tooltipTitle(issuable.createdAt)"
+ data-testid="issuable-created-at"
+ >
+ {{ createdAt }}
+ </span>
+ </template>
+ <template #author>
+ <slot v-if="hasSlotContents('author')" name="author"></slot>
+ <gl-link
+ v-else
+ :data-user-id="authorId"
+ :data-username="author.username"
+ :data-name="author.name"
+ :data-avatar-url="author.avatarUrl"
+ :href="author.webUrl"
+ data-testid="issuable-author"
+ class="author-link js-user-link"
+ >
+ <span class="author">{{ author.name }}</span>
+ </gl-link>
+ </template>
+ </gl-sprintf>
</span>
<slot name="timeframe"></slot>
- &nbsp;
- <span v-if="labels.length" role="group" :aria-label="__('Labels')">
- <gl-label
- v-for="(label, index) in labels"
- :key="index"
- :background-color="label.color"
- :title="labelTitle(label)"
- :description="label.description"
- :scoped="scopedLabel(label)"
- :target="labelTarget(label)"
- :class="{ 'gl-ml-2': index }"
- size="sm"
- />
- </span>
- </div>
+ </span>
+ &nbsp;
+ <span v-if="labels.length" role="group" :aria-label="__('Labels')">
+ <gl-label
+ v-for="(label, index) in labels"
+ :key="index"
+ :background-color="label.color"
+ :title="labelTitle(label)"
+ :description="label.description"
+ :scoped="scopedLabel(label)"
+ :target="labelTarget(label)"
+ :class="{ 'gl-ml-2': index }"
+ size="sm"
+ />
+ </span>
</div>
- <div class="issuable-meta">
- <ul v-if="showIssuableMeta" class="controls">
- <li v-if="hasSlotContents('status')" class="issuable-status">
- <slot name="status"></slot>
- </li>
- <li v-if="assignees.length" class="gl-display-flex">
- <issuable-assignees
- :assignees="assignees"
- :icon-size="16"
- :max-visible="4"
- img-css-classes="gl-mr-2!"
- class="gl-align-items-center gl-display-flex gl-ml-3"
- />
- </li>
- <slot name="statistics"></slot>
- <li
- v-if="showDiscussions"
- data-testid="issuable-discussions"
- class="issuable-comments gl-display-none gl-sm-display-block"
- >
- <gl-link
- v-gl-tooltip:tooltipcontainer.top
- :title="__('Comments')"
- :href="issuableNotesLink"
- :class="{ 'no-comments': !notesCount }"
- class="gl-reset-color!"
- >
- <gl-icon name="comments" />
- {{ notesCount }}
- </gl-link>
- </li>
- </ul>
- <div
- data-testid="issuable-updated-at"
- class="float-right issuable-updated-at gl-display-none gl-sm-display-inline-block"
+ </div>
+ <div class="issuable-meta">
+ <ul v-if="showIssuableMeta" class="controls">
+ <li v-if="hasSlotContents('status')" class="issuable-status">
+ <slot name="status"></slot>
+ </li>
+ <li v-if="assignees.length">
+ <issuable-assignees
+ :assignees="assignees"
+ :icon-size="16"
+ :max-visible="4"
+ img-css-classes="gl-mr-2!"
+ class="gl-align-items-center gl-display-flex gl-ml-3"
+ />
+ </li>
+ <slot name="statistics"></slot>
+ <li
+ v-if="showDiscussions"
+ data-testid="issuable-discussions"
+ class="issuable-comments gl-display-none gl-sm-display-block"
>
- <span
- v-gl-tooltip:tooltipcontainer.bottom
- :title="tooltipTitle(issuable.updatedAt)"
- class="issuable-updated-at"
- >{{ updatedAt }}</span
+ <gl-link
+ v-gl-tooltip.top
+ :title="__('Comments')"
+ :href="issuableNotesLink"
+ :class="{ 'no-comments': !notesCount }"
+ class="gl-reset-color!"
>
- </div>
+ <gl-icon name="comments" />
+ {{ notesCount }}
+ </gl-link>
+ </li>
+ </ul>
+ <div
+ v-gl-tooltip.bottom
+ class="gl-text-gray-500 gl-display-none gl-sm-display-inline-block"
+ :title="tooltipTitle(issuable.updatedAt)"
+ data-testid="issuable-updated-at"
+ >
+ {{ updatedAt }}
</div>
</div>
</li>
diff --git a/app/assets/javascripts/issuable_list/components/issuable_list_root.vue b/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
index 87066a0a0b6..c1082987146 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
@@ -284,72 +284,70 @@ export default {
<slot name="sidebar-items" :checked-issuables="bulkEditIssuables"></slot>
</template>
</issuable-bulk-edit-sidebar>
- <div class="issuables-holder">
- <ul v-if="issuablesLoading" class="content-list">
- <li v-for="n in skeletonItemCount" :key="n" class="issue gl-px-5! gl-py-5!">
- <gl-skeleton-loading />
- </li>
- </ul>
- <template v-else>
- <component
- :is="issuablesWrapper"
- v-if="issuables.length > 0"
- class="content-list issuable-list issues-list"
- :class="{ 'manual-ordering': isManualOrdering }"
- v-bind="$options.vueDraggableAttributes"
- @update="handleVueDraggableUpdate"
+ <ul v-if="issuablesLoading" class="content-list">
+ <li v-for="n in skeletonItemCount" :key="n" class="issue gl-px-5! gl-py-5!">
+ <gl-skeleton-loading />
+ </li>
+ </ul>
+ <template v-else>
+ <component
+ :is="issuablesWrapper"
+ v-if="issuables.length > 0"
+ class="content-list issuable-list issues-list"
+ :class="{ 'manual-ordering': isManualOrdering }"
+ v-bind="$options.vueDraggableAttributes"
+ @update="handleVueDraggableUpdate"
+ >
+ <issuable-item
+ v-for="issuable in issuables"
+ :key="issuableId(issuable)"
+ :class="{ 'gl-cursor-grab': isManualOrdering }"
+ :issuable-symbol="issuableSymbol"
+ :issuable="issuable"
+ :enable-label-permalinks="enableLabelPermalinks"
+ :label-filter-param="labelFilterParam"
+ :show-checkbox="showBulkEditSidebar"
+ :checked="issuableChecked(issuable)"
+ @checked-input="handleIssuableCheckedInput(issuable, $event)"
>
- <issuable-item
- v-for="issuable in issuables"
- :key="issuableId(issuable)"
- :class="{ 'gl-cursor-grab': isManualOrdering }"
- :issuable-symbol="issuableSymbol"
- :issuable="issuable"
- :enable-label-permalinks="enableLabelPermalinks"
- :label-filter-param="labelFilterParam"
- :show-checkbox="showBulkEditSidebar"
- :checked="issuableChecked(issuable)"
- @checked-input="handleIssuableCheckedInput(issuable, $event)"
- >
- <template #reference>
- <slot name="reference" :issuable="issuable"></slot>
- </template>
- <template #author>
- <slot name="author" :author="issuable.author"></slot>
- </template>
- <template #timeframe>
- <slot name="timeframe" :issuable="issuable"></slot>
- </template>
- <template #status>
- <slot name="status" :issuable="issuable"></slot>
- </template>
- <template #statistics>
- <slot name="statistics" :issuable="issuable"></slot>
- </template>
- </issuable-item>
- </component>
- <slot v-else name="empty-state"></slot>
- </template>
+ <template #reference>
+ <slot name="reference" :issuable="issuable"></slot>
+ </template>
+ <template #author>
+ <slot name="author" :author="issuable.author"></slot>
+ </template>
+ <template #timeframe>
+ <slot name="timeframe" :issuable="issuable"></slot>
+ </template>
+ <template #status>
+ <slot name="status" :issuable="issuable"></slot>
+ </template>
+ <template #statistics>
+ <slot name="statistics" :issuable="issuable"></slot>
+ </template>
+ </issuable-item>
+ </component>
+ <slot v-else name="empty-state"></slot>
+ </template>
- <div v-if="showPaginationControls && useKeysetPagination" class="gl-text-center gl-mt-3">
- <gl-keyset-pagination
- :has-next-page="hasNextPage"
- :has-previous-page="hasPreviousPage"
- @next="$emit('next-page')"
- @prev="$emit('previous-page')"
- />
- </div>
- <gl-pagination
- v-else-if="showPaginationControls"
- :per-page="defaultPageSize"
- :total-items="totalItems"
- :value="currentPage"
- :prev-page="previousPage"
- :next-page="nextPage"
- align="center"
- class="gl-pagination gl-mt-3"
- @input="$emit('page-change', $event)"
+ <div v-if="showPaginationControls && useKeysetPagination" class="gl-text-center gl-mt-3">
+ <gl-keyset-pagination
+ :has-next-page="hasNextPage"
+ :has-previous-page="hasPreviousPage"
+ @next="$emit('next-page')"
+ @prev="$emit('previous-page')"
/>
</div>
+ <gl-pagination
+ v-else-if="showPaginationControls"
+ :per-page="defaultPageSize"
+ :total-items="totalItems"
+ :value="currentPage"
+ :prev-page="previousPage"
+ :next-page="nextPage"
+ align="center"
+ class="gl-pagination gl-mt-3"
+ @input="$emit('page-change', $event)"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/issues_list/components/issue_card_time_info.vue b/app/assets/javascripts/issues_list/components/issue_card_time_info.vue
index a687a58a6ad..4a2f7861492 100644
--- a/app/assets/javascripts/issues_list/components/issue_card_time_info.vue
+++ b/app/assets/javascripts/issues_list/components/issue_card_time_info.vue
@@ -85,7 +85,7 @@ export default {
<span>
<span
v-if="issue.milestone"
- class="issuable-milestone gl-display-none gl-sm-display-inline-block! gl-mr-3"
+ class="issuable-milestone gl-mr-3"
data-testid="issuable-milestone"
>
<gl-link v-gl-tooltip :href="milestoneLink" :title="milestoneDate">
@@ -96,7 +96,7 @@ export default {
<span
v-if="issue.dueDate"
v-gl-tooltip
- class="issuable-due-date gl-display-none gl-sm-display-inline-block! gl-mr-3"
+ class="issuable-due-date gl-mr-3"
:class="{ 'gl-text-red-500': showDueDateInRed }"
:title="__('Due date')"
data-testid="issuable-due-date"
@@ -107,21 +107,14 @@ export default {
<span
v-if="timeEstimate"
v-gl-tooltip
- class="gl-display-none gl-sm-display-inline-block! gl-mr-3"
+ class="gl-mr-3"
:title="__('Estimate')"
data-testid="time-estimate"
>
<gl-icon name="timer" />
{{ timeEstimate }}
</span>
- <weight-count
- class="issuable-weight gl-display-none gl-sm-display-inline-block gl-mr-3"
- :weight="issue.weight"
- />
- <issue-health-status
- v-if="showHealthStatus"
- class="gl-display-none gl-sm-display-inline-block"
- :health-status="healthStatus"
- />
+ <weight-count class="issuable-weight gl-mr-3" :weight="issue.weight" />
+ <issue-health-status v-if="showHealthStatus" :health-status="healthStatus" />
</span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue b/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue
index b2f077f5329..5955f31fc70 100644
--- a/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue
@@ -77,7 +77,7 @@ export default {
};
</script>
<template>
- <div class="issue-assignees">
+ <div>
<user-avatar-link
v-for="assignee in assigneesToShow"
:key="assignee.id"
@@ -97,10 +97,9 @@ export default {
</user-avatar-link>
<span
v-if="numHiddenAssignees > 0"
- v-gl-tooltip
+ v-gl-tooltip.bottom
:title="assigneesCounterTooltip"
class="avatar-counter"
- data-placement="bottom"
data-qa-selector="avatar_counter_content"
>{{ assigneeCounterLabel }}</span
>
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 94912b1c641..d8fc94cce0c 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -673,40 +673,40 @@
.issuable-info-container {
flex: 1;
display: flex;
+ }
- .issuable-main-info {
- flex: 1 auto;
- margin-right: 10px;
- min-width: 0;
+ .issuable-main-info {
+ flex: 1 auto;
+ margin-right: 10px;
+ min-width: 0;
- .issue-weight-icon,
- .issue-estimate-icon {
- vertical-align: sub;
- }
+ .issue-weight-icon,
+ .issue-estimate-icon {
+ vertical-align: sub;
}
+ }
- .issuable-meta {
- display: flex;
- flex-direction: column;
- align-items: flex-end;
- flex: 1 0 auto;
-
- .controls {
- margin-bottom: 2px;
- line-height: 20px;
- padding: 0;
- }
+ .issuable-meta {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ flex: 1 0 auto;
- .issue-updated-at {
- line-height: 20px;
- }
+ .controls {
+ margin-bottom: 2px;
+ line-height: 20px;
+ padding: 0;
}
- @include media-breakpoint-down(xs) {
- .issuable-meta {
- .controls li {
- margin-right: 0;
- }
+ .issue-updated-at {
+ line-height: 20px;
+ }
+ }
+
+ @include media-breakpoint-down(xs) {
+ .issuable-meta {
+ .controls li {
+ margin-right: 0;
}
}
}
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 50eeda7283a..9a8eff56927 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -41,6 +41,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:improved_emoji_picker, project, default_enabled: :yaml)
push_frontend_feature_flag(:diffs_virtual_scrolling, project, default_enabled: :yaml)
push_frontend_feature_flag(:restructured_mr_widget, project, default_enabled: :yaml)
+ push_frontend_feature_flag(:mr_changes_fluid_layout, project, default_enabled: :yaml)
# Usage data feature flags
push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml)
diff --git a/config/feature_flags/development/mr_changes_fluid_layout.yml b/config/feature_flags/development/mr_changes_fluid_layout.yml
new file mode 100644
index 00000000000..87f0c0c6569
--- /dev/null
+++ b/config/feature_flags/development/mr_changes_fluid_layout.yml
@@ -0,0 +1,8 @@
+---
+name: mr_changes_fluid_layout
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70815
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341809
+milestone: '14.4'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb
index f3e01d23448..4fd41bd4c75 100644
--- a/config/initializers/backtrace_silencers.rb
+++ b/config/initializers/backtrace_silencers.rb
@@ -4,7 +4,7 @@ Rails.backtrace_cleaner.remove_silencers!
# This allows us to see the proper caller of SQL calls in {development,test}.log
if (Rails.env.development? || Rails.env.test?) && Gitlab.ee?
- Rails.backtrace_cleaner.add_silencer { |line| %r(^ee/lib/gitlab/database/load_balancing).match?(line) }
+ Rails.backtrace_cleaner.add_silencer { |line| %r(^lib/gitlab/database/load_balancing).match?(line) }
end
Rails.backtrace_cleaner.add_silencer { |line| !Gitlab::APP_DIRS_PATTERN.match?(line) }
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index bf5233f2dcf..109f451be5a 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -488,27 +488,29 @@ The exported project is located within a `.tar.gz` file in `/var/opt/gitlab/gitl
If it seems that a commit has gone "missing", search the sequence of pushes to a repository.
[This StackOverflow article](https://stackoverflow.com/questions/13468027/the-mystery-of-the-missing-commit-across-merges)
-describes how you can end up in this state without a force push.
+describes how you can end up in this state without a force push. Another cause can be a misconfigured [server hook](../server_hooks.md) that changes a HEAD ref via a `git reset` operation.
If you look at the output from the sample code below for the target branch, you
-see a discontinuity in the from/to commits as you step through the output. Each new
-push should be "from" the "to" SHA of the previous push. When this discontinuity happens,
-you see two pushes with the same "from" SHA:
+see a discontinuity in the from/to commits as you step through the output. The `commit_from` of each new push should equal the `commit_to` of the previous push. A break in that sequence indicates one or more commits have been "lost" from the repository history.
+
+The following example checks the last 100 pushes and prints the `commit_from` and `commit_to` entries:
```ruby
-p = Project.find_with_namespace('u/p')
+p = Project.find_by_full_path('u/p')
p.events.pushed_action.last(100).each do |e|
- printf "%-20.20s %8s...%8s (%s)\n", e.data[:ref], e.data[:before], e.data[:after], e.author.try(:username)
+ printf "%-20.20s %8s...%8s (%s)
+", e.push_event_payload[:ref], e.push_event_payload[:commit_from], e.push_event_payload[:commit_to], e.author.try(:username)
end
```
-GitLab 9.5 and above:
+Example output showing break in sequence at line 4:
-```ruby
-p = Project.find_by_full_path('u/p')
-p.events.pushed_action.last(100).each do |e|
- printf "%-20.20s %8s...%8s (%s)\n", e.push_event_payload[:ref], e.push_event_payload[:commit_from], e.push_event_payload[:commit_to], e.author.try(:username)
-end
+```plaintext
+master f21b07713251e04575908149bdc8ac1f105aabc3...6bc56c1f46244792222f6c85b11606933af171de (root)
+master 6bc56c1f46244792222f6c85b11606933af171de...132da6064f5d3453d445fd7cb452b148705bdc1b (root)
+master 132da6064f5d3453d445fd7cb452b148705bdc1b...a62e1e693150a2e46ace0ce696cd4a52856dfa65 (root)
+master 58b07b719a4b0039fec810efa52f479ba1b84756...f05321a5b5728bd8a89b7bf530aa44043c951dce (root)
+master f05321a5b5728bd8a89b7bf530aa44043c951dce...7d02e575fd790e76a3284ee435368279a5eb3773 (root)
```
## Mirrors
diff --git a/doc/ci/chatops/index.md b/doc/ci/chatops/index.md
index a2d9cf9054d..19133e355cb 100644
--- a/doc/ci/chatops/index.md
+++ b/doc/ci/chatops/index.md
@@ -9,6 +9,7 @@ type: index, concepts, howto
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4466) in GitLab Ultimate 10.6.
> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/24780) to GitLab Free in 11.9.
+> - `CHAT_USER_ID` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/341798) in GitLab 14.4.
GitLab ChatOps provides a method to interact with CI/CD jobs through chat services
like Slack. Many organizations' discussion, collaboration, and troubleshooting takes
@@ -30,6 +31,7 @@ to the job:
- `CHAT_INPUT` contains any additional arguments.
- `CHAT_CHANNEL` is set to the name of channel the action was triggered in.
+- `CHAT_USER_ID` is set to the chat service's user ID of the user who triggered the slash command.
When executed, ChatOps looks up the specified job name and attempts to match it
to a corresponding job in [`.gitlab-ci.yml`](../yaml/index.md). If a matching job
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index c8688d2433e..45fa1994342 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -20,6 +20,7 @@ There are also [Kubernetes-specific deployment variables](../../user/project/clu
|------------------------------------------|--------|--------|-------------|
| `CHAT_CHANNEL` | 10.6 | all | The Source chat channel that triggered the [ChatOps](../chatops/index.md) command. |
| `CHAT_INPUT` | 10.6 | all | The additional arguments passed with the [ChatOps](../chatops/index.md) command. |
+| `CHAT_USER_ID` | 14.4 | all | The chat service's user ID of the user who triggered the [ChatOps](../chatops/index.md) command. |
| `CI` | all | 0.4 | Available for all jobs executed in CI/CD. `true` when available. |
| `CI_API_V4_URL` | 11.7 | all | The GitLab API v4 root URL. |
| `CI_BUILDS_DIR` | all | 11.10 | The top-level directory where builds are executed. |
diff --git a/doc/update/restore_after_failure.md b/doc/update/restore_after_failure.md
index b8cceb8c367..cedb46a7c71 100644
--- a/doc/update/restore_after_failure.md
+++ b/doc/update/restore_after_failure.md
@@ -31,9 +31,7 @@ attempts. This is because some tables may have been added during the failed
upgrade. If these tables are still present after you restore from the
older backup it can lead to migration failures on future upgrades.
-Starting in GitLab 8.6 we drop all tables prior to importing the backup to
-prevent this problem. If you've restored a backup to a version prior to 8.6 you
-may have to manually correct the problem next time you upgrade.
+We drop all tables prior to importing the backup to prevent this problem.
Example error:
@@ -52,38 +50,16 @@ Copy the version from the error. In this case the version number is
WARNING:
Use the following steps only if you are certain you must do them.
-### GitLab 8.6+
+1. Pass the version to a database Rake task to manually mark the migration as
+ complete.
-Pass the version to a database Rake task to manually mark the migration as
-complete.
+ ```shell
+ # Source install
+ sudo -u git -H bundle exec rake gitlab:db:mark_migration_complete[20151103134857] RAILS_ENV=production
-```shell
-# Source install
-sudo -u git -H bundle exec rake gitlab:db:mark_migration_complete[20151103134857] RAILS_ENV=production
+ # Omnibus install
+ sudo gitlab-rake gitlab:db:mark_migration_complete[20151103134857]
+ ```
-# Omnibus install
-sudo gitlab-rake gitlab:db:mark_migration_complete[20151103134857]
-```
-
-After the migration is successfully marked, run the Rake `db:migrate` task again.
-Repeat this process until all failed migrations are complete.
-
-### GitLab < 8.6
-
-```shell
-# Source install
-sudo -u git -H bundle exec rails console -e production
-
-# Omnibus install
-sudo gitlab-rails console
-```
-
-At the Rails console, type the following commands:
-
-```ruby
-ActiveRecord::Base.connection.execute("INSERT INTO schema_migrations (version) VALUES('20151103134857')")
-exit
-```
-
-After the migration is successfully marked, run the Rake `db:migrate` task again.
-Repeat this process until all failed migrations are complete.
+1. After the migration is successfully marked, run the Rake `db:migrate` task again.
+1. Repeat this process until all failed migrations are complete.
diff --git a/doc/user/application_security/dependency_scanning/analyzers.md b/doc/user/application_security/dependency_scanning/analyzers.md
index fae0f457a20..8559d5af02e 100644
--- a/doc/user/application_security/dependency_scanning/analyzers.md
+++ b/doc/user/application_security/dependency_scanning/analyzers.md
@@ -47,7 +47,7 @@ In `.gitlab-ci.yml` define:
```yaml
include:
- template: Dependency-Scanning.gitlab-ci.yml
+ template: Security/Dependency-Scanning.gitlab-ci.yml
variables:
SECURE_ANALYZERS_PREFIX: my-docker-registry/gl-images
@@ -64,7 +64,7 @@ In `.gitlab-ci.yml` define:
```yaml
include:
- template: Dependency-Scanning.gitlab-ci.yml
+ template: Security/Dependency-Scanning.gitlab-ci.yml
variables:
DS_EXCLUDED_ANALYZERS: "bundler-audit, gemnasium"
@@ -77,7 +77,7 @@ In `.gitlab-ci.yml` define:
```yaml
include:
- template: Dependency-Scanning.gitlab-ci.yml
+ template: Security/Dependency-Scanning.gitlab-ci.yml
variables:
DS_EXCLUDED_ANALYZERS: "gemnasium, gemnasium-maven, gemnasium-python, bundler-audit, retire.js"
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 6754e02f3d3..8e97bb697e7 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -347,7 +347,7 @@ Add the following to your `.gitlab-ci.yml` file:
```yaml
include:
- - template: Dependency-Scanning.gitlab-ci.yml
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
```
The included template creates dependency scanning jobs in your CI/CD
@@ -381,7 +381,7 @@ For example:
```yaml
include:
- - template: Dependency-Scanning.gitlab-ci.yml
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
variables:
SECURE_LOG_LEVEL: error
@@ -403,7 +403,7 @@ the `gemnasium` analyzer:
```yaml
include:
- - template: Dependency-Scanning.gitlab-ci.yml
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
gemnasium-dependency_scanning:
variables:
@@ -414,7 +414,7 @@ To override the `dependencies: []` attribute, add an override job as above, targ
```yaml
include:
- - template: Dependency-Scanning.gitlab-ci.yml
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
gemnasium-dependency_scanning:
dependencies: ["build"]
@@ -713,7 +713,7 @@ value of `GEMNASIUM_DB_REMOTE_URL` to the location of your offline Git copy of t
```yaml
include:
- - template: Dependency-Scanning.gitlab-ci.yml
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
variables:
SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers"
@@ -868,7 +868,7 @@ to the supported `requirements.txt` as follows.
```yaml
include:
- - template: Dependency-Scanning.gitlab-ci.yml
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
stages:
- test
diff --git a/lib/gitlab/chat/command.rb b/lib/gitlab/chat/command.rb
index 0add53f8174..9370c594ce1 100644
--- a/lib/gitlab/chat/command.rb
+++ b/lib/gitlab/chat/command.rb
@@ -66,7 +66,8 @@ module Gitlab
def build_environment_variables(pipeline)
pipeline.variables.build(
[{ key: 'CHAT_INPUT', value: arguments },
- { key: 'CHAT_CHANNEL', value: channel }]
+ { key: 'CHAT_CHANNEL', value: channel },
+ { key: 'CHAT_USER_ID', value: chat_name.chat_id }]
)
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index a3bbf3a4d0e..c4149d60508 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -39900,6 +39900,9 @@ msgstr ""
msgid "created %{timeAgo}"
msgstr ""
+msgid "created %{timeAgo} by %{author}"
+msgstr ""
+
msgid "created by"
msgstr ""
diff --git a/package.json b/package.json
index 1f12a8c64e2..ae33b5ef76a 100644
--- a/package.json
+++ b/package.json
@@ -57,7 +57,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "1.212.0",
"@gitlab/tributejs": "1.0.0",
- "@gitlab/ui": "32.11.2",
+ "@gitlab/ui": "32.11.4",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "6.1.3-2",
"@rails/ujs": "6.1.3-2",
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js
index 9b63f84e617..0527c2153f4 100644
--- a/spec/frontend/diffs/components/app_spec.js
+++ b/spec/frontend/diffs/components/app_spec.js
@@ -702,4 +702,23 @@ describe('diffs/components/app', () => {
);
});
});
+
+ describe('fluid layout', () => {
+ beforeEach(() => {
+ setFixtures(
+ '<div><div class="merge-request-container limit-container-width container-limited"></div></div>',
+ );
+ });
+
+ it('removes limited container classes when on diffs tab', () => {
+ createComponent({ isFluidLayout: false, shouldShow: true }, () => {}, {
+ glFeatures: { mrChangesFluidLayout: true },
+ });
+
+ const containerClassList = document.querySelector('.merge-request-container').classList;
+
+ expect(containerClassList).not.toContain('container-limited');
+ expect(containerClassList).not.toContain('limit-container-width');
+ });
+ });
});
diff --git a/spec/frontend/issuable_list/components/issuable_item_spec.js b/spec/frontend/issuable_list/components/issuable_item_spec.js
index ea36d59ff83..ac3bf7f3269 100644
--- a/spec/frontend/issuable_list/components/issuable_item_spec.js
+++ b/spec/frontend/issuable_list/components/issuable_item_spec.js
@@ -1,4 +1,4 @@
-import { GlLink, GlLabel, GlIcon, GlFormCheckbox } from '@gitlab/ui';
+import { GlLink, GlLabel, GlIcon, GlFormCheckbox, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { useFakeDate } from 'helpers/fake_date';
import IssuableItem from '~/issuable_list/components/issuable_item.vue';
@@ -16,6 +16,9 @@ const createComponent = ({ issuableSymbol = '#', issuable = mockIssuable, slots
showCheckbox: false,
},
slots,
+ stubs: {
+ GlSprintf,
+ },
});
const MOCK_GITLAB_URL = 'http://0.0.0.0:3000';
@@ -135,13 +138,6 @@ describe('IssuableItem', () => {
});
});
- describe('createdAt', () => {
- it('returns string containing timeago string based on `issuable.createdAt`', () => {
- expect(wrapper.vm.createdAt).toContain('created');
- expect(wrapper.vm.createdAt).toContain('ago');
- });
- });
-
describe('updatedAt', () => {
it('returns string containing timeago string based on `issuable.updatedAt`', () => {
expect(wrapper.vm.updatedAt).toContain('updated');
@@ -449,8 +445,7 @@ describe('IssuableItem', () => {
it('renders issuable updatedAt info', () => {
const updatedAtEl = wrapper.find('[data-testid="issuable-updated-at"]');
- expect(updatedAtEl.exists()).toBe(true);
- expect(updatedAtEl.find('span').attributes('title')).toBe('Sep 10, 2020 11:41am UTC');
+ expect(updatedAtEl.attributes('title')).toBe('Sep 10, 2020 11:41am UTC');
expect(updatedAtEl.text()).toBe(wrapper.vm.updatedAt);
});
diff --git a/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js b/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
index 2658fa4a706..f74b9b37197 100644
--- a/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
+++ b/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
@@ -94,10 +94,6 @@ describe('IssueAssigneesComponent', () => {
expect(vm.avatarUrlTitle(mockAssigneesList[0])).toBe('Assigned to Terrell Graham');
});
- it('renders component root element with class `issue-assignees`', () => {
- expect(wrapper.element.classList.contains('issue-assignees')).toBe(true);
- });
-
it('renders assignee', () => {
const data = findAvatars().wrappers.map((x) => ({
...x.props(),
diff --git a/spec/lib/gitlab/chat/command_spec.rb b/spec/lib/gitlab/chat/command_spec.rb
index d99c07d1fa3..c8b4b3f73b2 100644
--- a/spec/lib/gitlab/chat/command_spec.rb
+++ b/spec/lib/gitlab/chat/command_spec.rb
@@ -72,6 +72,7 @@ RSpec.describe Gitlab::Chat::Command do
expect(vars['CHAT_INPUT']).to eq('foo')
expect(vars['CHAT_CHANNEL']).to eq('123')
+ expect(vars['CHAT_USER_ID']).to eq(chat_name.chat_id)
end
end
end
diff --git a/yarn.lock b/yarn.lock
index f137af92592..3e303259e36 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -974,10 +974,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
-"@gitlab/ui@32.11.2":
- version "32.11.2"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.11.2.tgz#c18456543700b84ec473eccf9871a75d416984cb"
- integrity sha512-taJ7aLAt8xG2NB9Rwgve9u+BGn788wgsEe6wjx4crEEWJ3EemXr/zmTe6kzSgo+n/zjZfFBRLl0vjUWCj5ylSQ==
+"@gitlab/ui@32.11.4":
+ version "32.11.4"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.11.4.tgz#ead781c4fd57b4f7bc6818de99e56d023f94c397"
+ integrity sha512-plxOvtAIo+PIng1jBssj/QCx2ATIbZqQvLvCeezgAABgY107XhqZDw50VZL0texTX+0jGwB5PaXthmU/wnCk2w==
dependencies:
"@babel/standalone" "^7.0.0"
bootstrap-vue "2.18.1"