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:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-06-01 18:08:16 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-06-01 18:08:16 +0300
commit711f8595324430e216ba62f874e7db9fdf482f73 (patch)
treeda5b8063c16a20e2ab414ca20526ef64817b4393
parent65f197cdb6f7732e6c56433483a17f50d98b48f0 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/alert_management/components/alert_management_list.vue85
-rw-r--r--app/assets/javascripts/alert_management/constants.js2
-rw-r--r--app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql35
-rw-r--r--app/assets/javascripts/badges/components/badge.vue4
-rw-r--r--app/assets/javascripts/badges/components/badge_list_row.vue2
-rw-r--r--app/assets/javascripts/batch_comments/components/draft_note.vue2
-rw-r--r--app/assets/javascripts/batch_comments/components/preview_dropdown.vue2
-rw-r--r--app/assets/javascripts/batch_comments/components/preview_item.vue4
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.vue2
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue2
-rw-r--r--app/assets/javascripts/clusters/components/application_row.vue2
-rw-r--r--app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue2
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue10
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue6
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue2
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list.vue2
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_item.vue2
-rw-r--r--app/assets/javascripts/ide/components/jobs/stage.vue2
-rw-r--r--app/assets/javascripts/ide/components/mr_file_icon.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel.vue2
-rw-r--r--app/assets/javascripts/releases/components/evidence_block.vue4
-rw-r--r--app/assets/javascripts/releases/components/release_block_metadata.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/file_finder/item.vue8
-rw-r--r--app/assets/stylesheets/framework/common.scss1
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss2
-rw-r--r--app/models/releases/link.rb7
-rw-r--r--app/views/admin/hooks/edit.html.haml2
-rw-r--r--app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml2
-rw-r--r--app/views/import/bitbucket_server/new.html.haml6
-rw-r--r--app/views/import/phabricator/new.html.haml4
-rw-r--r--app/views/projects/_home_panel.html.haml2
-rw-r--r--app/views/projects/buttons/_fork.html.haml2
-rw-r--r--app/views/projects/buttons/_star.html.haml4
-rw-r--r--app/views/projects/diffs/_stats.html.haml4
-rw-r--r--app/views/projects/hooks/edit.html.haml2
-rw-r--r--app/views/projects/issues/_new_branch.html.haml2
-rw-r--r--app/views/shared/notifications/_new_button.html.haml2
-rw-r--r--app/views/shared/projects/_project.html.haml2
-rw-r--r--app/views/shared/web_hooks/_hook.html.haml4
-rw-r--r--changelogs/unreleased/207257-specify-asset-types-in-releases.yml5
-rw-r--r--changelogs/unreleased/213881-alerts-list-pagination.yml5
-rw-r--r--db/migrate/20200527092027_add_link_type_to_release_links.rb19
-rw-r--r--db/structure.sql4
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md2
-rw-r--r--doc/user/project/bulk_editing.md12
-rw-r--r--lib/gitlab/diff/formatters/base_formatter.rb11
-rw-r--r--lib/gitlab/diff/position.rb1
-rw-r--r--lib/gitlab/sidekiq_middleware/server_metrics.rb12
-rw-r--r--spec/frontend/alert_management/components/alert_management_list_spec.js131
-rw-r--r--spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap2
-rw-r--r--spec/frontend/jobs/components/job_log_spec.js2
-rw-r--r--spec/lib/gitlab/diff/formatters/image_formatter_spec.rb1
-rw-r--r--spec/lib/gitlab/diff/formatters/text_formatter_spec.rb1
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml1
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb14
-rw-r--r--spec/spec_helper.rb4
-rw-r--r--spec/support/shared_examples/lib/gitlab/position_formatters_shared_examples.rb16
59 files changed, 371 insertions, 114 deletions
diff --git a/app/assets/javascripts/alert_management/components/alert_management_list.vue b/app/assets/javascripts/alert_management/components/alert_management_list.vue
index 0b4e2d8ca02..ecb92ccef6f 100644
--- a/app/assets/javascripts/alert_management/components/alert_management_list.vue
+++ b/app/assets/javascripts/alert_management/components/alert_management_list.vue
@@ -11,6 +11,7 @@ import {
GlTabs,
GlTab,
GlBadge,
+ GlPagination,
} from '@gitlab/ui';
import createFlash from '~/flash';
import { s__ } from '~/locale';
@@ -22,6 +23,7 @@ import getAlertsCountByStatus from '../graphql/queries/get_count_by_status.query
import {
ALERTS_STATUS_TABS,
ALERTS_SEVERITY_LABELS,
+ DEFAULT_PAGE_SIZE,
trackAlertListViewsOptions,
trackAlertStatusUpdateOptions,
} from '../constants';
@@ -34,6 +36,14 @@ const bodyTrClass =
'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-bg-blue-50 gl-hover-cursor-pointer gl-hover-border-b-solid gl-hover-border-blue-200';
const findDefaultSortColumn = () => document.querySelector('.js-started-at');
+const initialPaginationState = {
+ currentPage: 1,
+ prevPageCursor: '',
+ nextPageCursor: '',
+ firstPageSize: DEFAULT_PAGE_SIZE,
+ lastPageSize: null,
+};
+
export default {
i18n: {
noAlertsMsg: s__(
@@ -110,6 +120,7 @@ export default {
GlTabs,
GlTab,
GlBadge,
+ GlPagination,
},
props: {
projectPath: {
@@ -142,10 +153,20 @@ export default {
projectPath: this.projectPath,
statuses: this.statusFilter,
sort: this.sort,
+ firstPageSize: this.pagination.firstPageSize,
+ lastPageSize: this.pagination.lastPageSize,
+ prevPageCursor: this.pagination.prevPageCursor,
+ nextPageCursor: this.pagination.nextPageCursor,
};
},
update(data) {
- return data.project?.alertManagementAlerts?.nodes;
+ const { alertManagementAlerts: { nodes: list = [], pageInfo = {} } = {} } =
+ data.project || {};
+
+ return {
+ list,
+ pageInfo,
+ };
},
error() {
this.errored = true;
@@ -169,7 +190,9 @@ export default {
isAlertDismissed: false,
isErrorAlertDismissed: false,
sort: 'STARTED_AT_ASC',
- statusFilter: this.$options.statusTabs[4].filters,
+ statusFilter: [],
+ filteredByStatus: '',
+ pagination: initialPaginationState,
};
},
computed: {
@@ -185,19 +208,34 @@ export default {
return this.$apollo.queries.alerts.loading;
},
hasAlerts() {
- return this.alerts?.length;
+ return this.alerts?.list?.length;
},
tbodyTrClass() {
return !this.loading && this.hasAlerts ? bodyTrClass : '';
},
+ showPaginationControls() {
+ return Boolean(this.prevPage || this.nextPage);
+ },
+ alertsForCurrentTab() {
+ return this.alertsCount ? this.alertsCount[this.filteredByStatus.toLowerCase()] : 0;
+ },
+ prevPage() {
+ return Math.max(this.pagination.currentPage - 1, 0);
+ },
+ nextPage() {
+ const nextPage = this.pagination.currentPage + 1;
+ return nextPage > Math.ceil(this.alertsForCurrentTab / DEFAULT_PAGE_SIZE) ? null : nextPage;
+ },
},
mounted() {
- findDefaultSortColumn().ariaSort = 'ascending';
this.trackPageViews();
},
methods: {
filterAlertsByStatus(tabIndex) {
- this.statusFilter = this.$options.statusTabs[tabIndex].filters;
+ this.resetPagination();
+ const { filters, status } = this.$options.statusTabs[tabIndex];
+ this.statusFilter = filters;
+ this.filteredByStatus = status;
},
fetchSortedData({ sortBy, sortDesc }) {
const sortDirection = sortDesc ? 'DESC' : 'ASC';
@@ -206,6 +244,7 @@ export default {
if (sortBy !== 'startedAt') {
findDefaultSortColumn().ariaSort = 'none';
}
+ this.resetPagination();
this.sort = `${sortColumn}_${sortDirection}`;
},
updateAlertStatus(status, iid) {
@@ -222,6 +261,7 @@ export default {
this.trackStatusUpdate(status);
this.$apollo.queries.alerts.refetch();
this.$apollo.queries.alertsCount.refetch();
+ this.resetPagination();
})
.catch(() => {
createFlash(
@@ -246,6 +286,28 @@ export default {
// TODO: Update to show list of assignee(s) after https://gitlab.com/gitlab-org/gitlab/-/issues/218405
return assignees?.length > 0 ? assignees[0]?.username : s__('AlertManagement|Unassigned');
},
+ handlePageChange(page) {
+ const { startCursor, endCursor } = this.alerts.pageInfo;
+
+ if (page > this.pagination.currentPage) {
+ this.pagination = {
+ ...initialPaginationState,
+ nextPageCursor: endCursor,
+ currentPage: page,
+ };
+ } else {
+ this.pagination = {
+ lastPageSize: DEFAULT_PAGE_SIZE,
+ firstPageSize: null,
+ prevPageCursor: startCursor,
+ nextPageCursor: '',
+ currentPage: page,
+ };
+ }
+ },
+ resetPagination() {
+ this.pagination = initialPaginationState;
+ },
},
};
</script>
@@ -275,7 +337,7 @@ export default {
</h4>
<gl-table
class="alert-management-table mt-3"
- :items="alerts"
+ :items="alerts ? alerts.list : []"
:fields="$options.fields"
:show-empty="true"
:busy="loading"
@@ -283,6 +345,7 @@ export default {
:tbody-tr-class="tbodyTrClass"
:no-local-sorting="true"
sort-icon-left
+ sort-by="startedAt"
@row-clicked="navigateToAlertDetails"
@sort-changed="fetchSortedData"
>
@@ -350,6 +413,16 @@ export default {
<gl-loading-icon size="lg" color="dark" class="mt-3" />
</template>
</gl-table>
+
+ <gl-pagination
+ v-if="showPaginationControls"
+ :value="pagination.currentPage"
+ :prev-page="prevPage"
+ :next-page="nextPage"
+ align="center"
+ class="gl-pagination prepend-top-default"
+ @input="handlePageChange"
+ />
</div>
<gl-empty-state
v-else
diff --git a/app/assets/javascripts/alert_management/constants.js b/app/assets/javascripts/alert_management/constants.js
index b79a64646eb..b9670466c0f 100644
--- a/app/assets/javascripts/alert_management/constants.js
+++ b/app/assets/javascripts/alert_management/constants.js
@@ -63,3 +63,5 @@ export const trackAlertStatusUpdateOptions = {
action: 'update_alert_status',
label: 'Status',
};
+
+export const DEFAULT_PAGE_SIZE = 10;
diff --git a/app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql b/app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql
index 42e5282e174..1d3c3c83cc1 100644
--- a/app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql
+++ b/app/assets/javascripts/alert_management/graphql/queries/get_alerts.query.graphql
@@ -1,11 +1,32 @@
#import "../fragments/list_item.fragment.graphql"
-query getAlerts($projectPath: ID!, $statuses: [AlertManagementStatus!], $sort: AlertManagementAlertSort ) {
- project(fullPath: $projectPath) {
- alertManagementAlerts(statuses: $statuses, sort: $sort) {
- nodes {
- ...AlertListItem
- }
+query getAlerts(
+ $projectPath: ID!,
+ $statuses: [AlertManagementStatus!],
+ $sort: AlertManagementAlertSort,
+ $firstPageSize: Int,
+ $lastPageSize: Int,
+ $prevPageCursor: String = ""
+ $nextPageCursor: String = ""
+) {
+ project(fullPath: $projectPath, ) {
+ alertManagementAlerts(
+ statuses: $statuses,
+ sort: $sort,
+ first: $firstPageSize
+ last: $lastPageSize,
+ after: $nextPageCursor,
+ before: $prevPageCursor
+ ) {
+ nodes {
+ ...AlertListItem
+ },
+ pageInfo {
+ hasNextPage
+ endCursor
+ hasPreviousPage
+ startCursor
+ }
+ }
}
- }
}
diff --git a/app/assets/javascripts/badges/components/badge.vue b/app/assets/javascripts/badges/components/badge.vue
index 6edbdc7090c..3242993b06a 100644
--- a/app/assets/javascripts/badges/components/badge.vue
+++ b/app/assets/javascripts/badges/components/badge.vue
@@ -84,10 +84,10 @@ export default {
<div v-show="hasError" class="btn-group">
<div class="btn btn-default btn-sm disabled">
- <icon :size="16" class="gl-ml-3 append-right-8" name="doc-image" aria-hidden="true" />
+ <icon :size="16" class="gl-ml-3 gl-mr-3" name="doc-image" aria-hidden="true" />
</div>
<div class="btn btn-default btn-sm disabled">
- <span class="gl-ml-3 append-right-8">{{ s__('Badges|No badge image') }}</span>
+ <span class="gl-ml-3 gl-mr-3">{{ s__('Badges|No badge image') }}</span>
</div>
</div>
diff --git a/app/assets/javascripts/badges/components/badge_list_row.vue b/app/assets/javascripts/badges/components/badge_list_row.vue
index bb363b8d85e..bad14666bb2 100644
--- a/app/assets/javascripts/badges/components/badge_list_row.vue
+++ b/app/assets/javascripts/badges/components/badge_list_row.vue
@@ -54,7 +54,7 @@ export default {
<div v-if="canEditBadge" class="table-action-buttons">
<button
:disabled="badge.isDeleting"
- class="btn btn-default append-right-8"
+ class="btn btn-default gl-mr-3"
type="button"
@click="editBadge(badge)"
>
diff --git a/app/assets/javascripts/batch_comments/components/draft_note.vue b/app/assets/javascripts/batch_comments/components/draft_note.vue
index 6e0859571db..3e0ae6f65c6 100644
--- a/app/assets/javascripts/batch_comments/components/draft_note.vue
+++ b/app/assets/javascripts/batch_comments/components/draft_note.vue
@@ -86,7 +86,7 @@ export default {
<publish-button
:show-count="true"
:should-publish="false"
- class="btn btn-success btn-inverted append-right-8"
+ class="btn btn-success btn-inverted gl-mr-3"
/>
<loading-button
ref="publishNowButton"
diff --git a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
index 13b2291d44b..195e1b7ec5c 100644
--- a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
+++ b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
@@ -103,7 +103,7 @@ export default {
:show-count="false"
:should-publish="true"
:label="__('Submit review')"
- class="float-right append-right-8"
+ class="float-right gl-mr-3"
/>
</div>
</div>
diff --git a/app/assets/javascripts/batch_comments/components/preview_item.vue b/app/assets/javascripts/batch_comments/components/preview_item.vue
index 9cd74b19c48..df9c419ff96 100644
--- a/app/assets/javascripts/batch_comments/components/preview_item.vue
+++ b/app/assets/javascripts/batch_comments/components/preview_item.vue
@@ -83,7 +83,7 @@ export default {
@click="scrollToDraft(draft)"
>
<span class="review-preview-item-header">
- <icon class="append-right-8 flex-shrink-0" :name="iconName" />
+ <icon class="gl-mr-3 flex-shrink-0" :name="iconName" />
<span class="bold text-nowrap">
<span class="review-preview-item-header-text block-truncated"> {{ titleText }} </span>
<template v-if="showLinePosition">
@@ -98,7 +98,7 @@ export default {
v-if="draft.discussion_id && resolvedStatusMessage"
class="review-preview-item-footer draft-note-resolution p-0"
>
- <icon class="append-right-8" name="status_success" /> {{ resolvedStatusMessage }}
+ <icon class="gl-mr-3" name="status_success" /> {{ resolvedStatusMessage }}
</span>
</button>
</template>
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue
index 76e7cb03799..e852032e9e0 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner.vue
@@ -188,7 +188,7 @@ export default {
>
<span
v-if="issue.referencePath"
- class="board-card-number overflow-hidden d-flex append-right-8 gl-mt-3"
+ class="board-card-number overflow-hidden d-flex gl-mr-3 gl-mt-3"
>
<tooltip-on-truncate
v-if="issueReferencePath"
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
index 7eb791f97e4..7b703c5ede1 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
@@ -170,7 +170,7 @@ export default {
v-if="tableIsNotEmpty"
ref="secret-value-reveal-button"
data-qa-selector="reveal_ci_variable_value_button"
- class="append-right-8"
+ class="gl-mr-3"
@click="toggleValues(!valuesHidden)"
>{{ valuesButtonText }}</gl-deprecated-button
>
diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue
index a4ca2a6c857..c4db122ba6f 100644
--- a/app/assets/javascripts/clusters/components/application_row.vue
+++ b/app/assets/javascripts/clusters/components/application_row.vue
@@ -313,7 +313,7 @@ export default {
:data-qa-selector="id"
>
<div class="gl-responsive-table-row-layout" role="row">
- <div class="table-section append-right-8 section-align-top" role="gridcell">
+ <div class="table-section gl-mr-3 section-align-top" role="gridcell">
<img
v-if="hasLogo"
:src="logoUrl"
diff --git a/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue b/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue
index c2f963f0b34..24c70b99efe 100644
--- a/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue
+++ b/app/assets/javascripts/clusters/components/ingress_modsecurity_settings.vue
@@ -168,7 +168,7 @@ export default {
}}
</gl-alert>
<div class="gl-responsive-table-row-layout" role="row">
- <div class="table-section append-right-8 section-align-top" role="gridcell">
+ <div class="table-section gl-mr-3 section-align-top" role="gridcell">
<img
:src="modSecurityLogo"
:alt="`${$options.title} logo`"
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index e9f581a95eb..6f6fa312865 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -86,7 +86,7 @@ export default {
<button
v-gl-tooltip.hover
type="button"
- class="btn btn-default append-right-8 js-toggle-tree-list"
+ class="btn btn-default gl-mr-3 js-toggle-tree-list"
:class="{
active: showTreeList,
}"
@@ -126,15 +126,11 @@ export default {
<gl-deprecated-button
v-if="commit || startVersion"
:href="latestVersionPath"
- class="append-right-8 js-latest-version"
+ class="gl-mr-3 js-latest-version"
>
{{ __('Show latest version') }}
</gl-deprecated-button>
- <gl-deprecated-button
- v-show="hasCollapsedFile"
- class="append-right-8"
- @click="expandAllFiles"
- >
+ <gl-deprecated-button v-show="hasCollapsedFile" class="gl-mr-3" @click="expandAllFiles">
{{ __('Expand all') }}
</gl-deprecated-button>
<settings-dropdown />
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index 410909190b3..5fe58c5e512 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -104,7 +104,7 @@ export default {
<gl-loading-icon
v-if="group.isChildrenLoading"
size="lg"
- class="d-none d-sm-inline-flex flex-shrink-0 append-right-8"
+ class="d-none d-sm-inline-flex flex-shrink-0 gl-mr-3"
/>
<div
:class="{ 'd-sm-flex': !group.isChildrenLoading }"
@@ -117,12 +117,12 @@ export default {
</div>
<div class="group-text-container d-flex flex-fill align-items-center">
<div class="group-text flex-grow-1 flex-shrink-1">
- <div class="d-flex align-items-center flex-wrap title namespace-title append-right-8">
+ <div class="d-flex align-items-center flex-wrap title namespace-title gl-mr-3">
<a
v-tooltip
:href="group.relativePath"
:title="group.fullName"
- class="no-expand gl-mt-3 append-right-8"
+ class="no-expand gl-mt-3 gl-mr-3"
data-placement="bottom"
>{{
// ending bracket must be by closing tag to prevent
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
index 24499fb9f6d..d171852b6a1 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
@@ -56,7 +56,7 @@ export default {
v-if="canDiscard"
ref="discardButton"
type="button"
- class="btn btn-remove btn-inverted append-right-8"
+ class="btn btn-remove btn-inverted gl-mr-3"
@click="showDiscardModal"
>
{{ __('Discard changes') }}
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list.vue b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
index 49885917c53..ed4097f5459 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
@@ -74,7 +74,7 @@ export default {
<div class="ide-commit-list-container">
<header class="multi-file-commit-panel-header d-flex mb-0">
<div class="d-flex align-items-center flex-fill">
- <icon v-once :name="iconName" :size="18" class="append-right-8" />
+ <icon v-once :name="iconName" :size="18" class="gl-mr-3" />
<strong> {{ titleText }} </strong>
<div class="d-flex ml-auto">
<button
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
index 5ae44c0d9a8..c65169f5d31 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
@@ -87,7 +87,7 @@ export default {
@click="openFileInEditor"
>
<span class="multi-file-commit-list-file-path d-flex align-items-center">
- <file-icon :file-name="file.name" class="append-right-8" />
+ <file-icon :file-name="file.name" class="gl-mr-3" />
<template v-if="file.prevName && file.prevName !== file.name">
{{ file.prevName }} &#x2192;
</template>
diff --git a/app/assets/javascripts/ide/components/jobs/stage.vue b/app/assets/javascripts/ide/components/jobs/stage.vue
index 40dc0a6e80d..169a948c2da 100644
--- a/app/assets/javascripts/ide/components/jobs/stage.vue
+++ b/app/assets/javascripts/ide/components/jobs/stage.vue
@@ -75,7 +75,7 @@ export default {
>
{{ stage.name }}
</strong>
- <div v-if="!stage.isLoading || stage.jobs.length" class="append-right-8 gl-ml-2">
+ <div v-if="!stage.isLoading || stage.jobs.length" class="gl-mr-3 gl-ml-2">
<span class="badge badge-pill"> {{ jobsCount }} </span>
</div>
<icon :name="collapseIcon" class="ide-stage-collapse-icon" />
diff --git a/app/assets/javascripts/ide/components/mr_file_icon.vue b/app/assets/javascripts/ide/components/mr_file_icon.vue
index cf8a1abbde4..4fab57b6f3e 100644
--- a/app/assets/javascripts/ide/components/mr_file_icon.vue
+++ b/app/assets/javascripts/ide/components/mr_file_icon.vue
@@ -18,6 +18,6 @@ export default {
:title="__('Part of merge request changes')"
:size="12"
name="git-merge"
- class="append-right-8"
+ class="gl-mr-3"
/>
</template>
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel.vue b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
index 629a71451e9..7bd9a90e8b8 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
@@ -285,7 +285,7 @@ export default {
<slot name="topLeft"></slot>
<h5
ref="graphTitle"
- class="prometheus-graph-title gl-font-lg font-weight-bold text-truncate append-right-8"
+ class="prometheus-graph-title gl-font-lg font-weight-bold text-truncate gl-mr-3"
tabindex="0"
>
{{ title }}
diff --git a/app/assets/javascripts/releases/components/evidence_block.vue b/app/assets/javascripts/releases/components/evidence_block.vue
index acae6fda533..2cc15777343 100644
--- a/app/assets/javascripts/releases/components/evidence_block.vue
+++ b/app/assets/javascripts/releases/components/evidence_block.vue
@@ -71,7 +71,7 @@ export default {
:download="evidenceTitle(index)"
:href="evidenceUrl(index)"
>
- <gl-icon name="review-list" class="align-middle append-right-8" />
+ <gl-icon name="review-list" class="align-middle gl-mr-3" />
<span>{{ evidenceTitle(index) }}</span>
</gl-link>
@@ -96,7 +96,7 @@ export default {
<gl-icon
v-gl-tooltip
name="clock"
- class="align-middle append-right-8"
+ class="align-middle gl-mr-3"
:title="collectedAt(index)"
/>
<span>{{ timeSummary(index) }}</span>
diff --git a/app/assets/javascripts/releases/components/release_block_metadata.vue b/app/assets/javascripts/releases/components/release_block_metadata.vue
index 40133941011..a3377ce044a 100644
--- a/app/assets/javascripts/releases/components/release_block_metadata.vue
+++ b/app/assets/javascripts/releases/components/release_block_metadata.vue
@@ -57,7 +57,7 @@ export default {
<template>
<div class="card-subtitle d-flex flex-wrap text-secondary">
- <div class="append-right-8">
+ <div class="gl-mr-3">
<icon name="commit" class="align-middle" />
<gl-link v-if="commitUrl" v-gl-tooltip.bottom :title="commit.title" :href="commitUrl">
{{ commit.shortId }}
@@ -65,7 +65,7 @@ export default {
<span v-else v-gl-tooltip.bottom :title="commit.title">{{ commit.shortId }}</span>
</div>
- <div class="append-right-8">
+ <div class="gl-mr-3">
<icon name="tag" class="align-middle" />
<gl-link v-if="tagUrl" v-gl-tooltip.bottom :title="__('Tag')" :href="tagUrl">
{{ release.tagName }}
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
index 2433ba879aa..0464c4b9c15 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
@@ -117,7 +117,7 @@ export default {
:href="webIdePath"
:title="ideButtonTitle"
:class="{ disabled: !mr.canPushToSourceBranch }"
- class="btn btn-default js-web-ide d-none d-md-inline-block append-right-8"
+ class="btn btn-default js-web-ide d-none d-md-inline-block gl-mr-3"
data-placement="bottom"
tabindex="0"
role="button"
@@ -129,7 +129,7 @@ export default {
:disabled="mr.sourceBranchRemoved"
data-target="#modal_merge_info"
data-toggle="modal"
- class="btn btn-default js-check-out-branch append-right-8"
+ class="btn btn-default js-check-out-branch gl-mr-3"
type="button"
>
{{ s__('mrWidget|Check out branch') }}
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
index e80cb06edfb..47231c4ad39 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
@@ -52,7 +52,7 @@ export default {
:download="fileName"
target="_blank"
>
- <icon :size="16" name="download" class="float-left append-right-8" />
+ <icon :size="16" name="download" class="float-left gl-mr-3" />
{{ __('Download') }}
</gl-link>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/file_finder/item.vue b/app/assets/javascripts/vue_shared/components/file_finder/item.vue
index 018e3a84c39..590501a975a 100644
--- a/app/assets/javascripts/vue_shared/components/file_finder/item.vue
+++ b/app/assets/javascripts/vue_shared/components/file_finder/item.vue
@@ -75,12 +75,8 @@ export default {
@mouseover="mouseOverRow"
@mousemove="mouseMove"
>
- <file-icon
- :file-name="file.name"
- :size="16"
- css-classes="diff-file-changed-icon append-right-8"
- />
- <span class="diff-changed-file-content append-right-8">
+ <file-icon :file-name="file.name" :size="16" css-classes="diff-file-changed-icon gl-mr-3" />
+ <span class="diff-changed-file-content gl-mr-3">
<strong class="diff-changed-file-name">
<span
v-for="(char, charIndex) in file.name.split('')"
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index bf474251572..b0144cde360 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -414,7 +414,6 @@ img.emoji {
.append-right-2 { margin-right: 2px; }
.append-right-4 { margin-right: 4px; }
.append-right-5 { margin-right: 5px; }
-.append-right-8 { margin-right: 8px; }
.append-right-10 { margin-right: 10px; }
.append-right-15 { margin-right: 15px; }
.append-right-default { margin-right: $gl-padding; }
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index 154717f9776..47c6a9a44ca 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -920,7 +920,7 @@ button.mini-pipeline-graph-dropdown-toggle {
.ci-status-icon {
- @extend .append-right-8;
+ @include gl-mr-3;
position: relative;
diff --git a/app/models/releases/link.rb b/app/models/releases/link.rb
index 65be2a22958..dc7e78a85a9 100644
--- a/app/models/releases/link.rb
+++ b/app/models/releases/link.rb
@@ -14,6 +14,13 @@ module Releases
scope :sorted, -> { order(created_at: :desc) }
+ enum link_type: {
+ other: 0,
+ runbook: 1,
+ package: 2,
+ image: 3
+ }
+
def internal?
url.start_with?(release.project.web_url)
end
diff --git a/app/views/admin/hooks/edit.html.haml b/app/views/admin/hooks/edit.html.haml
index 9ce0fa8d401..636dd6bdfc1 100644
--- a/app/views/admin/hooks/edit.html.haml
+++ b/app/views/admin/hooks/edit.html.haml
@@ -9,7 +9,7 @@
= form_for @hook, as: :hook, url: admin_hook_path do |f|
= render partial: 'form', locals: { form: f, hook: @hook }
.form-actions
- %span>= f.submit _('Save changes'), class: 'btn btn-success append-right-8'
+ %span>= f.submit _('Save changes'), class: 'btn btn-success gl-mr-3'
= render 'shared/web_hooks/test_button', hook: @hook
= link_to _('Delete'), admin_hook_path(@hook), method: :delete, class: 'btn btn-remove float-right', data: { confirm: _('Are you sure?') }
diff --git a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
index 617e5d1d5d3..486625c790b 100644
--- a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
+++ b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
@@ -2,7 +2,7 @@
.bs-callout.gcp-signup-offer.alert.alert-block.alert-dismissable.prepend-top-default.append-bottom-default{ role: 'alert', data: { feature_id: UserCalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: user_callouts_path } }
%button.close.js-close{ type: "button" } &times;
.gcp-signup-offer--content
- .gcp-signup-offer--icon.append-right-8
+ .gcp-signup-offer--icon.gl-mr-3
= sprite_icon("information", size: 16)
.gcp-signup-offer--copy
%h4= s_('ClusterIntegration|Did you know?')
diff --git a/app/views/import/bitbucket_server/new.html.haml b/app/views/import/bitbucket_server/new.html.haml
index ac86be8fa7a..2eac8d0c5a1 100644
--- a/app/views/import/bitbucket_server/new.html.haml
+++ b/app/views/import/bitbucket_server/new.html.haml
@@ -13,14 +13,14 @@
.form-group.row
= label_tag :bitbucket_server_url, 'Bitbucket Server URL', class: 'col-form-label col-md-2'
.col-md-4
- = text_field_tag :bitbucket_server_url, '', class: 'form-control append-right-8', placeholder: _('https://your-bitbucket-server'), size: 40
+ = text_field_tag :bitbucket_server_url, '', class: 'form-control gl-mr-3', placeholder: _('https://your-bitbucket-server'), size: 40
.form-group.row
= label_tag :bitbucket_server_url, 'Username', class: 'col-form-label col-md-2'
.col-md-4
- = text_field_tag :bitbucket_username, '', class: 'form-control append-right-8', placeholder: _('username'), size: 40
+ = text_field_tag :bitbucket_username, '', class: 'form-control gl-mr-3', placeholder: _('username'), size: 40
.form-group.row
= label_tag :personal_access_token, 'Password/Personal Access Token', class: 'col-form-label col-md-2'
.col-md-4
- = password_field_tag :personal_access_token, '', class: 'form-control append-right-8', placeholder: _('Personal Access Token'), size: 40
+ = password_field_tag :personal_access_token, '', class: 'form-control gl-mr-3', placeholder: _('Personal Access Token'), size: 40
.form-actions
= submit_tag _('List your Bitbucket Server repositories'), class: 'btn btn-success'
diff --git a/app/views/import/phabricator/new.html.haml b/app/views/import/phabricator/new.html.haml
index eaa36b9012e..3dfc7c37d98 100644
--- a/app/views/import/phabricator/new.html.haml
+++ b/app/views/import/phabricator/new.html.haml
@@ -16,10 +16,10 @@
.form-group.row
= label_tag :phabricator_server_url, _('Phabricator Server URL'), class: 'col-form-label col-md-2'
.col-md-4
- = text_field_tag :phabricator_server_url, params[:phabricator_server_url], class: 'form-control append-right-8', placeholder: 'https://your-phabricator-server', size: 40
+ = text_field_tag :phabricator_server_url, params[:phabricator_server_url], class: 'form-control gl-mr-3', placeholder: 'https://your-phabricator-server', size: 40
.form-group.row
= label_tag :api_token, _('API Token'), class: 'col-form-label col-md-2'
.col-md-4
- = password_field_tag :api_token, params[:api_token], class: 'form-control append-right-8', placeholder: _('Personal Access Token'), size: 40
+ = password_field_tag :api_token, params[:api_token], class: 'form-control gl-mr-3', placeholder: _('Personal Access Token'), size: 40
.form-actions
= submit_tag _('Import tasks'), class: 'btn btn-success'
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index b4e218451a0..38470fea6da 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -80,7 +80,7 @@
- if @project.badges.present?
.project-badges.mb-2
- @project.badges.each do |badge|
- %a.append-right-8{ href: badge.rendered_link_url(@project),
+ %a.gl-mr-3{ href: badge.rendered_link_url(@project),
target: '_blank',
rel: 'noopener noreferrer' }>
%img.project-badge{ src: badge.rendered_image_url(@project),
diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml
index 4b82eb2c5ef..2d9c7f9848f 100644
--- a/app/views/projects/buttons/_fork.html.haml
+++ b/app/views/projects/buttons/_fork.html.haml
@@ -1,6 +1,6 @@
- unless @project.empty_repo?
- if current_user && can?(current_user, :fork_project, @project)
- .count-badge.d-inline-flex.align-item-stretch.append-right-8
+ .count-badge.d-inline-flex.align-item-stretch.gl-mr-3
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: s_('ProjectOverview|Go to your fork'), class: 'btn btn-default has-tooltip count-badge-button d-flex align-items-center fork-btn' do
= sprite_icon('fork', { css_class: 'icon' })
diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml
index 02e5297528b..3dac38d1356 100644
--- a/app/views/projects/buttons/_star.html.haml
+++ b/app/views/projects/buttons/_star.html.haml
@@ -1,5 +1,5 @@
- if current_user
- .count-badge.d-inline-flex.align-item-stretch.append-right-8
+ .count-badge.d-inline-flex.align-item-stretch.gl-mr-3
%button.count-badge-button.btn.btn-default.btn-xs.d-flex.align-items-center.star-btn.toggle-star{ type: "button", data: { endpoint: toggle_star_project_path(@project, :json) } }
- if current_user.starred?(@project)
= sprite_icon('star', { css_class: 'icon' })
@@ -12,7 +12,7 @@
= @project.star_count
- else
- .count-badge.d-inline-flex.align-item-stretch.append-right-8
+ .count-badge.d-inline-flex.align-item-stretch.gl-mr-3
= link_to new_user_session_path, class: 'btn btn-default btn-xs has-tooltip count-badge-button d-flex align-items-center star-btn', title: s_('ProjectOverview|You must sign in to star a project') do
= sprite_icon('star-o', { css_class: 'icon' })
%span= s_('ProjectOverview|Star')
diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml
index 86e6e732610..17c1764e8a4 100644
--- a/app/views/projects/diffs/_stats.html.haml
+++ b/app/views/projects/diffs/_stats.html.haml
@@ -22,8 +22,8 @@
- diff_files.each do |diff_file|
%li
%a.diff-changed-file{ href: "##{hexdigest(diff_file.file_path)}", title: diff_file.new_path }
- = sprite_icon(diff_file_changed_icon(diff_file), size: 16, css_class: "#{diff_file_changed_icon_color(diff_file)} diff-file-changed-icon append-right-8")
- %span.diff-changed-file-content.append-right-8
+ = sprite_icon(diff_file_changed_icon(diff_file), size: 16, css_class: "#{diff_file_changed_icon_color(diff_file)} diff-file-changed-icon gl-mr-3")
+ %span.diff-changed-file-content.gl-mr-3
- if diff_file.file_path
%strong.diff-changed-file-name
= diff_file.file_path
diff --git a/app/views/projects/hooks/edit.html.haml b/app/views/projects/hooks/edit.html.haml
index f7eae802dac..15100840c0a 100644
--- a/app/views/projects/hooks/edit.html.haml
+++ b/app/views/projects/hooks/edit.html.haml
@@ -10,7 +10,7 @@
= form_for [@project.namespace.becomes(Namespace), @project, @hook], as: :hook, url: project_hook_path(@project, @hook) do |f|
= render partial: 'shared/web_hooks/form', locals: { form: f, hook: @hook }
- %span>= f.submit 'Save changes', class: 'btn btn-success append-right-8'
+ %span>= f.submit 'Save changes', class: 'btn btn-success gl-mr-3'
= render 'shared/web_hooks/test_button', hook: @hook
= link_to _('Delete'), project_hook_path(@project, @hook), method: :delete, class: 'btn btn-remove float-right', data: { confirm: _('Are you sure?') }
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
index a77eea8beaa..73904354a12 100644
--- a/app/views/projects/issues/_new_branch.html.haml
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -41,7 +41,7 @@
= _('Create branch')
%li.divider.droplab-item-ignore
- %li.droplab-item-ignore.gl-ml-3.append-right-8.prepend-top-16
+ %li.droplab-item-ignore.gl-ml-3.gl-mr-3.prepend-top-16
- if can_create_confidential_merge_request?
#js-forked-project{ data: { namespace_path: @project.namespace.full_path, project_path: @project.full_path, new_fork_path: new_project_fork_path(@project), help_page_path: help_page_path('user/project/merge_requests') } }
.form-group
diff --git a/app/views/shared/notifications/_new_button.html.haml b/app/views/shared/notifications/_new_button.html.haml
index 566f08b94ce..796ff095eea 100644
--- a/app/views/shared/notifications/_new_button.html.haml
+++ b/app/views/shared/notifications/_new_button.html.haml
@@ -8,7 +8,7 @@
- else
- button_title = _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }
- .js-notification-dropdown.notification-dropdown.home-panel-action-button.prepend-top-default.append-right-8.dropdown.inline
+ .js-notification-dropdown.notification-dropdown.home-panel-action-button.prepend-top-default.gl-mr-3.dropdown.inline
= form_for notification_setting, remote: true, html: { class: "inline notification-form no-label" } do |f|
= hidden_setting_source_input(notification_setting)
= hidden_field_tag "hide_label", true
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index 5a0003e546f..fc3f1a8d1c1 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -32,7 +32,7 @@
.d-flex.align-items-center.flex-wrap.project-title
%h2.d-flex.gl-mt-3
= link_to project_path(project), class: 'text-plain' do
- %span.project-full-name.append-right-8><
+ %span.project-full-name.gl-mr-3><
%span.namespace-name
- if project.namespace && !skip_namespace
= project.namespace.human_name
diff --git a/app/views/shared/web_hooks/_hook.html.haml b/app/views/shared/web_hooks/_hook.html.haml
index 34a62340966..470e2f6b904 100644
--- a/app/views/shared/web_hooks/_hook.html.haml
+++ b/app/views/shared/web_hooks/_hook.html.haml
@@ -11,6 +11,6 @@
= hook.enable_ssl_verification ? _('enabled') : _('disabled')
.col-md-4.col-lg-5.text-right-md.prepend-top-5
- %span>= render 'shared/web_hooks/test_button', hook: hook, button_class: 'btn-sm append-right-8'
- %span>= link_to _('Edit'), edit_hook_path(hook), class: 'btn btn-sm append-right-8'
+ %span>= render 'shared/web_hooks/test_button', hook: hook, button_class: 'btn-sm gl-mr-3'
+ %span>= link_to _('Edit'), edit_hook_path(hook), class: 'btn btn-sm gl-mr-3'
= link_to _('Delete'), destroy_hook_path(hook), data: { confirm: _('Are you sure?') }, method: :delete, class: 'btn btn-sm'
diff --git a/changelogs/unreleased/207257-specify-asset-types-in-releases.yml b/changelogs/unreleased/207257-specify-asset-types-in-releases.yml
new file mode 100644
index 00000000000..ee11eb72389
--- /dev/null
+++ b/changelogs/unreleased/207257-specify-asset-types-in-releases.yml
@@ -0,0 +1,5 @@
+---
+title: Add link_type column to release_links table
+merge_request: 33156
+author:
+type: changed
diff --git a/changelogs/unreleased/213881-alerts-list-pagination.yml b/changelogs/unreleased/213881-alerts-list-pagination.yml
new file mode 100644
index 00000000000..310152722ed
--- /dev/null
+++ b/changelogs/unreleased/213881-alerts-list-pagination.yml
@@ -0,0 +1,5 @@
+---
+title: Alerts list pagination
+merge_request: 33073
+author:
+type: added
diff --git a/db/migrate/20200527092027_add_link_type_to_release_links.rb b/db/migrate/20200527092027_add_link_type_to_release_links.rb
new file mode 100644
index 00000000000..5088775f665
--- /dev/null
+++ b/db/migrate/20200527092027_add_link_type_to_release_links.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddLinkTypeToReleaseLinks < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :release_links, :link_type, :integer, limit: 2, default: 0
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :release_links, :link_type
+ end
+ end
+end
diff --git a/db/structure.sql b/db/structure.sql
index e4b5d5d35c5..5242cde1f9b 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -5730,7 +5730,8 @@ CREATE TABLE public.release_links (
name character varying NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- filepath character varying(128)
+ filepath character varying(128),
+ link_type smallint DEFAULT 0
);
CREATE SEQUENCE public.release_links_id_seq
@@ -14031,6 +14032,7 @@ COPY "schema_migrations" (version) FROM STDIN;
20200526153844
20200526164946
20200526164947
+20200527092027
20200527094322
20200527095401
20200527151413
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index 11ea6b0f150..fdd64c20c70 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -126,10 +126,12 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `sidekiq_jobs_db_seconds` | Histogram | 12.9 | Seconds of DB time to run Sidekiq job | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` |
| `sidekiq_jobs_gitaly_seconds` | Histogram | 12.9 | Seconds of Gitaly time to run Sidekiq job | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` |
| `sidekiq_redis_requests_duration_seconds` | Histogram | 13.1 | Duration in seconds that a Sidekiq job spent querying a Redis server | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` |
+| `sidekiq_elasticsearch_requests_duration_seconds` | Histogram | 13.1 | Duration in seconds that a Sidekiq job spent in requests to an Elasticsearch server | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` |
| `sidekiq_jobs_queue_duration_seconds` | Histogram | 12.5 | Duration in seconds that a Sidekiq job was queued before being executed | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` |
| `sidekiq_jobs_failed_total` | Counter | 12.2 | Sidekiq jobs failed | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` |
| `sidekiq_jobs_retried_total` | Counter | 12.2 | Sidekiq jobs retried | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` |
| `sidekiq_redis_requests_total` | Counter | 13.1 | Redis requests during a Sidekiq job execution | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` |
+| `sidekiq_elasticsearch_requests_total` | Counter | 13.1 | Elasticsearch requests during a Sidekiq job execution | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` |
| `sidekiq_running_jobs` | Gauge | 12.2 | Number of Sidekiq jobs running | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` |
| `sidekiq_concurrency` | Gauge | 12.5 | Maximum number of Sidekiq jobs | |
| `geo_db_replication_lag_seconds` | Gauge | 10.2 | Database replication lag (seconds) | `url` |
diff --git a/doc/user/project/bulk_editing.md b/doc/user/project/bulk_editing.md
index 8a7446155f4..14a570fa17d 100644
--- a/doc/user/project/bulk_editing.md
+++ b/doc/user/project/bulk_editing.md
@@ -4,29 +4,31 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Bulk editing issues and merge requests
+# Bulk editing issues, epics, and merge requests
> **Notes:**
>
> - A permission level of `Reporter` or higher is required in order to manage
> issues.
+> - A permission level of `Reporter` or higher is required in order to manage
+> epics.
> - A permission level of `Developer` or higher is required in order to manage
> merge requests.
-Attributes can be updated simultaneously across multiple issues or merge requests
+Attributes can be updated simultaneously across multiple issues, epics, or merge requests
by using the bulk editing feature.
![Bulk editing](img/bulk-editing.png)
NOTE: **Note:**
-Bulk editing issues and merge requests is also available at the group level.
+Bulk editing issues, epics, and merge requests is also available at the group level.
For more details, see [bulk editing group issues and merge requests](../group/bulk_editing/index.md).
-To update multiple project issues or merge requests at the same time:
+To update multiple project issues, epics, or merge requests at the same time:
1. Navigate to their respective list.
-1. Click **Edit issues** or **Edit merge requests**.
+1. Click either **Edit issues**, **Edit epics**, or **Edit merge requests**.
- This will open a sidebar on the right-hand side of your screen
where editable fields will be displayed.
diff --git a/lib/gitlab/diff/formatters/base_formatter.rb b/lib/gitlab/diff/formatters/base_formatter.rb
index 9704aed82c1..31eeadc45f7 100644
--- a/lib/gitlab/diff/formatters/base_formatter.rb
+++ b/lib/gitlab/diff/formatters/base_formatter.rb
@@ -6,6 +6,7 @@ module Gitlab
class BaseFormatter
attr_reader :old_path
attr_reader :new_path
+ attr_reader :file_identifier_hash
attr_reader :base_sha
attr_reader :start_sha
attr_reader :head_sha
@@ -16,6 +17,7 @@ module Gitlab
attrs[:diff_refs] = diff_file.diff_refs
attrs[:old_path] = diff_file.old_path
attrs[:new_path] = diff_file.new_path
+ attrs[:file_identifier_hash] = diff_file.file_identifier_hash
end
if diff_refs = attrs[:diff_refs]
@@ -26,6 +28,7 @@ module Gitlab
@old_path = attrs[:old_path]
@new_path = attrs[:new_path]
+ @file_identifier_hash = attrs[:file_identifier_hash]
@base_sha = attrs[:base_sha]
@start_sha = attrs[:start_sha]
@head_sha = attrs[:head_sha]
@@ -36,7 +39,7 @@ module Gitlab
end
def to_h
- {
+ out = {
base_sha: base_sha,
start_sha: start_sha,
head_sha: head_sha,
@@ -44,6 +47,12 @@ module Gitlab
new_path: new_path,
position_type: position_type
}
+
+ if Feature.enabled?(:file_identifier_hash)
+ out[:file_identifier_hash] = file_identifier_hash
+ end
+
+ out
end
def position_type
diff --git a/lib/gitlab/diff/position.rb b/lib/gitlab/diff/position.rb
index 10ad23b7774..a5120a1b8fe 100644
--- a/lib/gitlab/diff/position.rb
+++ b/lib/gitlab/diff/position.rb
@@ -9,6 +9,7 @@ module Gitlab
delegate :old_path,
:new_path,
+ :file_identifier_hash,
:base_sha,
:start_sha,
:head_sha,
diff --git a/lib/gitlab/sidekiq_middleware/server_metrics.rb b/lib/gitlab/sidekiq_middleware/server_metrics.rb
index 00dd3b5937a..6a942a6ce06 100644
--- a/lib/gitlab/sidekiq_middleware/server_metrics.rb
+++ b/lib/gitlab/sidekiq_middleware/server_metrics.rb
@@ -49,6 +49,8 @@ module Gitlab
@metrics[:sidekiq_jobs_gitaly_seconds].observe(labels, get_gitaly_time(job))
@metrics[:sidekiq_redis_requests_total].increment(labels, get_redis_calls(job))
@metrics[:sidekiq_redis_requests_duration_seconds].observe(labels, get_redis_time(job))
+ @metrics[:sidekiq_elasticsearch_requests_total].increment(labels, get_elasticsearch_calls(job))
+ @metrics[:sidekiq_elasticsearch_requests_duration_seconds].observe(labels, get_elasticsearch_time(job))
end
end
@@ -62,9 +64,11 @@ module Gitlab
sidekiq_jobs_gitaly_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_gitaly_seconds, 'Seconds of Gitaly time to run Sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS),
sidekiq_jobs_queue_duration_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_queue_duration_seconds, 'Duration in seconds that a Sidekiq job was queued before being executed', {}, SIDEKIQ_LATENCY_BUCKETS),
sidekiq_redis_requests_duration_seconds: ::Gitlab::Metrics.histogram(:sidekiq_redis_requests_duration_seconds, 'Duration in seconds that a Sidekiq job spent requests a Redis server', {}, Gitlab::Instrumentation::Redis::QUERY_TIME_BUCKETS),
+ sidekiq_elasticsearch_requests_duration_seconds: ::Gitlab::Metrics.histogram(:sidekiq_elasticsearch_requests_duration_seconds, 'Duration in seconds that a Sidekiq job spent in requests to an Elasticsearch server', {}, SIDEKIQ_LATENCY_BUCKETS),
sidekiq_jobs_failed_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_failed_total, 'Sidekiq jobs failed'),
sidekiq_jobs_retried_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_retried_total, 'Sidekiq jobs retried'),
sidekiq_redis_requests_total: ::Gitlab::Metrics.counter(:sidekiq_redis_requests_total, 'Redis requests during a Sidekiq job execution'),
+ sidekiq_elasticsearch_requests_total: ::Gitlab::Metrics.counter(:sidekiq_elasticsearch_requests_total, 'Elasticsearch requests during a Sidekiq job execution'),
sidekiq_running_jobs: ::Gitlab::Metrics.gauge(:sidekiq_running_jobs, 'Number of Sidekiq jobs running', {}, :all),
sidekiq_concurrency: ::Gitlab::Metrics.gauge(:sidekiq_concurrency, 'Maximum number of Sidekiq jobs', {}, :all)
}
@@ -82,6 +86,14 @@ module Gitlab
job.fetch(:redis_calls, 0)
end
+ def get_elasticsearch_time(job)
+ job.fetch(:elasticsearch_duration_s, 0)
+ end
+
+ def get_elasticsearch_calls(job)
+ job.fetch(:elasticsearch_calls, 0)
+ end
+
def get_gitaly_time(job)
job.fetch(:gitaly_duration_s, 0)
end
diff --git a/spec/frontend/alert_management/components/alert_management_list_spec.js b/spec/frontend/alert_management/components/alert_management_list_spec.js
index 8d7fbbb763f..614c7a59953 100644
--- a/spec/frontend/alert_management/components/alert_management_list_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_list_spec.js
@@ -7,8 +7,10 @@ import {
GlDropdown,
GlDropdownItem,
GlIcon,
+ GlTabs,
GlTab,
GlBadge,
+ GlPagination,
} from '@gitlab/ui';
import { visitUrl } from '~/lib/utils/url_utility';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
@@ -39,19 +41,21 @@ describe('AlertManagementList', () => {
const findLoader = () => wrapper.find(GlLoadingIcon);
const findStatusDropdown = () => wrapper.find(GlDropdown);
const findStatusFilterTabs = () => wrapper.findAll(GlTab);
+ const findStatusTabs = () => wrapper.find(GlTabs);
const findStatusFilterBadge = () => wrapper.findAll(GlBadge);
const findDateFields = () => wrapper.findAll(TimeAgo);
const findFirstStatusOption = () => findStatusDropdown().find(GlDropdownItem);
const findAssignees = () => wrapper.findAll('[data-testid="assigneesField"]');
const findSeverityFields = () => wrapper.findAll('[data-testid="severityField"]');
const findSeverityColumnHeader = () => wrapper.findAll('th').at(0);
-
+ const findStartTimeColumnHeader = () => wrapper.findAll('th').at(1);
+ const findPagination = () => wrapper.find(GlPagination);
const alertsCount = {
- acknowledged: 6,
- all: 16,
open: 14,
- resolved: 2,
triggered: 10,
+ acknowledged: 6,
+ resolved: 1,
+ all: 16,
};
function mountComponent({
@@ -76,6 +80,7 @@ describe('AlertManagementList', () => {
mocks: {
$apollo: {
mutate: jest.fn(),
+ query: jest.fn(),
queries: {
alerts: {
loading,
@@ -134,7 +139,7 @@ describe('AlertManagementList', () => {
it('loading state', () => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: null, alertsCount: null },
+ data: { alerts: {}, alertsCount: null },
loading: true,
});
expect(findAlertsTable().exists()).toBe(true);
@@ -149,7 +154,7 @@ describe('AlertManagementList', () => {
it('error state', () => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: null, alertsCount: null, errored: true },
+ data: { alerts: { errors: ['error'] }, alertsCount: null, errored: true },
loading: false,
});
expect(findAlertsTable().exists()).toBe(true);
@@ -166,7 +171,7 @@ describe('AlertManagementList', () => {
it('empty state', () => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: [], alertsCount: { all: 0 }, errored: false },
+ data: { alerts: { list: [], pageInfo: {} }, alertsCount: { all: 0 }, errored: false },
loading: false,
});
expect(findAlertsTable().exists()).toBe(true);
@@ -183,7 +188,7 @@ describe('AlertManagementList', () => {
it('has data state', () => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: mockAlerts, alertsCount, errored: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
expect(findLoader().exists()).toBe(false);
@@ -199,7 +204,7 @@ describe('AlertManagementList', () => {
it('displays status dropdown', () => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: mockAlerts, alertsCount, errored: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
expect(findStatusDropdown().exists()).toBe(true);
@@ -208,7 +213,7 @@ describe('AlertManagementList', () => {
it('shows correct severity icons', () => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: mockAlerts, alertsCount, errored: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
@@ -225,7 +230,7 @@ describe('AlertManagementList', () => {
it('renders severity text', () => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: mockAlerts, alertsCount, errored: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
@@ -239,7 +244,7 @@ describe('AlertManagementList', () => {
it('renders Unassigned when no assignee(s) present', () => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: mockAlerts, alertsCount, errored: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
@@ -253,7 +258,7 @@ describe('AlertManagementList', () => {
it('renders username(s) when assignee(s) present', () => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: mockAlerts, alertsCount, errored: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
@@ -267,7 +272,7 @@ describe('AlertManagementList', () => {
it('navigates to the detail page when alert row is clicked', () => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: mockAlerts, alertsCount, errored: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
@@ -282,15 +287,17 @@ describe('AlertManagementList', () => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: {
- alerts: [
- {
- iid: 1,
- status: 'acknowledged',
- startedAt: '2020-03-17T23:18:14.996Z',
- endedAt: '2020-04-17T23:18:14.996Z',
- severity: 'high',
- },
- ],
+ alerts: {
+ list: [
+ {
+ iid: 1,
+ status: 'acknowledged',
+ startedAt: '2020-03-17T23:18:14.996Z',
+ endedAt: '2020-04-17T23:18:14.996Z',
+ severity: 'high',
+ },
+ ],
+ },
alertsCount,
errored: false,
},
@@ -326,27 +333,31 @@ describe('AlertManagementList', () => {
beforeEach(() => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: mockAlerts, errored: false, sort: 'STARTED_AT_ASC', alertsCount },
+ data: { alerts: { list: mockAlerts }, errored: false, sort: 'STARTED_AT_ASC', alertsCount },
loading: false,
+ stubs: { GlTable },
});
});
it('updates sort with new direction and column key', () => {
findSeverityColumnHeader().trigger('click');
- expect(wrapper.vm.$data.sort).toEqual('SEVERITY_ASC');
+ expect(wrapper.vm.$data.sort).toBe('SEVERITY_ASC');
findSeverityColumnHeader().trigger('click');
- expect(wrapper.vm.$data.sort).toEqual('SEVERITY_DESC');
+ expect(wrapper.vm.$data.sort).toBe('SEVERITY_DESC');
});
it('updates the `ariaSort` attribute so the sort icon appears in the proper column', () => {
- expect(mockStartedAtCol.ariaSort).toEqual('ascending');
+ expect(findStartTimeColumnHeader().attributes('aria-sort')).toBe('ascending');
findSeverityColumnHeader().trigger('click');
- expect(mockStartedAtCol.ariaSort).toEqual('none');
+ wrapper.vm.$nextTick(() => {
+ expect(findStartTimeColumnHeader().attributes('aria-sort')).toBe('none');
+ expect(findSeverityColumnHeader().attributes('aria-sort')).toBe('ascending');
+ });
});
});
@@ -367,7 +378,7 @@ describe('AlertManagementList', () => {
beforeEach(() => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: mockAlerts, alertsCount, errored: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
});
@@ -403,7 +414,7 @@ describe('AlertManagementList', () => {
jest.spyOn(Tracking, 'event');
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: mockAlerts, alertsCount },
+ data: { alerts: { list: mockAlerts }, alertsCount },
loading: false,
});
});
@@ -424,4 +435,64 @@ describe('AlertManagementList', () => {
});
});
});
+
+ describe('Pagination', () => {
+ beforeEach(() => {
+ mountComponent({
+ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
+ data: { alerts: { list: mockAlerts, pageInfo: {} }, alertsCount, errored: false },
+ loading: false,
+ });
+ });
+
+ it('does NOT show pagination control when list is smaller than default page size', () => {
+ findStatusTabs().vm.$emit('input', 3);
+ wrapper.vm.$nextTick(() => {
+ expect(findPagination().exists()).toBe(false);
+ });
+ });
+
+ it('shows pagination control when list is larger than default page size', () => {
+ findStatusTabs().vm.$emit('input', 0);
+ wrapper.vm.$nextTick(() => {
+ expect(findPagination().exists()).toBe(true);
+ });
+ });
+
+ describe('prevPage', () => {
+ it('returns prevPage number', () => {
+ findPagination().vm.$emit('input', 3);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.prevPage).toBe(2);
+ });
+ });
+
+ it('returns 0 when it is the first page', () => {
+ findPagination().vm.$emit('input', 1);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.prevPage).toBe(0);
+ });
+ });
+ });
+
+ describe('nextPage', () => {
+ it('returns nextPage number', () => {
+ findPagination().vm.$emit('input', 1);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.nextPage).toBe(2);
+ });
+ });
+
+ it('returns `null` when currentPage is already last page', () => {
+ findStatusTabs().vm.$emit('input', 3);
+ findPagination().vm.$emit('input', 1);
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.nextPage).toBeNull();
+ });
+ });
+ });
+ });
});
diff --git a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap
index 6bce68af642..bdd3d439fd4 100644
--- a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap
+++ b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap
@@ -25,7 +25,7 @@ exports[`IDE pipeline stage renders stage details & icon 1`] = `
</strong>
<div
- class="append-right-8 gl-ml-2"
+ class="gl-mr-3 gl-ml-2"
>
<span
class="badge badge-pill"
diff --git a/spec/frontend/jobs/components/job_log_spec.js b/spec/frontend/jobs/components/job_log_spec.js
index 2bb1e0af3a2..a167fe8a134 100644
--- a/spec/frontend/jobs/components/job_log_spec.js
+++ b/spec/frontend/jobs/components/job_log_spec.js
@@ -10,7 +10,7 @@ describe('Job Log', () => {
let vm;
const trace =
- '<span>Running with gitlab-runner 12.1.0 (de7731dd)<br/></span><span> on docker-auto-scale-com d5ae8d25<br/></span><div class="append-right-8" data-timestamp="1565502765" data-section="prepare-executor" role="button"></div><span class="section section-header js-s-prepare-executor">Using Docker executor with image ruby:2.6 ...<br/></span>';
+ '<span>Running with gitlab-runner 12.1.0 (de7731dd)<br/></span><span> on docker-auto-scale-com d5ae8d25<br/></span><div class="gl-mr-3" data-timestamp="1565502765" data-section="prepare-executor" role="button"></div><span class="section section-header js-s-prepare-executor">Using Docker executor with image ruby:2.6 ...<br/></span>';
beforeEach(() => {
store = createStore();
diff --git a/spec/lib/gitlab/diff/formatters/image_formatter_spec.rb b/spec/lib/gitlab/diff/formatters/image_formatter_spec.rb
index edf30ffc56f..3f88f39ba92 100644
--- a/spec/lib/gitlab/diff/formatters/image_formatter_spec.rb
+++ b/spec/lib/gitlab/diff/formatters/image_formatter_spec.rb
@@ -10,6 +10,7 @@ describe Gitlab::Diff::Formatters::ImageFormatter do
head_sha: 789,
old_path: 'old_image.png',
new_path: 'new_image.png',
+ file_identifier_hash: '777',
position_type: 'image'
}
end
diff --git a/spec/lib/gitlab/diff/formatters/text_formatter_spec.rb b/spec/lib/gitlab/diff/formatters/text_formatter_spec.rb
index fa129a20e58..50dd597c5a7 100644
--- a/spec/lib/gitlab/diff/formatters/text_formatter_spec.rb
+++ b/spec/lib/gitlab/diff/formatters/text_formatter_spec.rb
@@ -10,6 +10,7 @@ describe Gitlab::Diff::Formatters::TextFormatter do
head_sha: 789,
old_path: 'old_path.txt',
new_path: 'new_path.txt',
+ file_identifier_hash: '777',
line_range: nil
}
end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index c29a85ce624..aae4ba6e025 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -144,6 +144,7 @@ Releases::Link:
- url
- name
- filepath
+- link_type
- created_at
- updated_at
ProjectMember:
diff --git a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
index 7000a52bb5d..4b7baea25e8 100644
--- a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
@@ -34,6 +34,8 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do
let(:redis_requests_total) { double('redis calls total metric') }
let(:running_jobs_metric) { double('running jobs metric') }
let(:redis_seconds_metric) { double('redis seconds metric') }
+ let(:elasticsearch_seconds_metric) { double('elasticsearch seconds metric') }
+ let(:elasticsearch_requests_total) { double('elasticsearch calls total metric') }
before do
allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_queue_duration_seconds, anything, anything, anything).and_return(queue_duration_seconds)
@@ -42,9 +44,11 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do
allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_db_seconds, anything, anything, anything).and_return(db_seconds_metric)
allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_jobs_gitaly_seconds, anything, anything, anything).and_return(gitaly_seconds_metric)
allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_redis_requests_duration_seconds, anything, anything, anything).and_return(redis_seconds_metric)
+ allow(Gitlab::Metrics).to receive(:histogram).with(:sidekiq_elasticsearch_requests_duration_seconds, anything, anything, anything).and_return(elasticsearch_seconds_metric)
allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_jobs_failed_total, anything).and_return(failed_total_metric)
allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_jobs_retried_total, anything).and_return(retried_total_metric)
allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_redis_requests_total, anything).and_return(redis_requests_total)
+ allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_elasticsearch_requests_total, anything).and_return(elasticsearch_requests_total)
allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_running_jobs, anything, {}, :all).and_return(running_jobs_metric)
allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_concurrency, anything, {}, :all).and_return(concurrency_metric)
@@ -76,6 +80,9 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do
let(:redis_calls) { 2 }
let(:redis_duration) { 0.01 }
+ let(:elasticsearch_calls) { 8 }
+ let(:elasticsearch_duration) { 0.54 }
+
before do
allow(subject).to receive(:get_thread_cputime).and_return(thread_cputime_before, thread_cputime_after)
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(monotonic_time_before, monotonic_time_after)
@@ -86,14 +93,19 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do
job[:redis_calls] = redis_calls
job[:redis_duration_s] = redis_duration
+ job[:elasticsearch_calls] = elasticsearch_calls
+ job[:elasticsearch_duration_s] = elasticsearch_duration
+
allow(running_jobs_metric).to receive(:increment)
allow(redis_requests_total).to receive(:increment)
+ allow(elasticsearch_requests_total).to receive(:increment)
allow(queue_duration_seconds).to receive(:observe)
allow(user_execution_seconds_metric).to receive(:observe)
allow(db_seconds_metric).to receive(:observe)
allow(gitaly_seconds_metric).to receive(:observe)
allow(completion_seconds_metric).to receive(:observe)
allow(redis_seconds_metric).to receive(:observe)
+ allow(elasticsearch_seconds_metric).to receive(:observe)
end
it 'yields block' do
@@ -109,7 +121,9 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do
expect(gitaly_seconds_metric).to receive(:observe).with(labels_with_job_status, gitaly_duration)
expect(completion_seconds_metric).to receive(:observe).with(labels_with_job_status, monotonic_time_duration)
expect(redis_seconds_metric).to receive(:observe).with(labels_with_job_status, redis_duration)
+ expect(elasticsearch_seconds_metric).to receive(:observe).with(labels_with_job_status, elasticsearch_duration)
expect(redis_requests_total).to receive(:increment).with(labels_with_job_status, redis_calls)
+ expect(elasticsearch_requests_total).to receive(:increment).with(labels_with_job_status, elasticsearch_calls)
subject.call(worker, job, :test) { nil }
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 2c5d624e75f..46237c6c9c9 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -195,6 +195,10 @@ RSpec.configure do |config|
stub_feature_flags(flag => enable_rugged)
end
+ # Disable the usage of file_identifier_hash by default until it is ready
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/33867
+ stub_feature_flags(file_identifier_hash: false)
+
allow(Gitlab::GitalyClient).to receive(:can_use_disk?).and_return(enable_rugged)
end
diff --git a/spec/support/shared_examples/lib/gitlab/position_formatters_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/position_formatters_shared_examples.rb
index c9300aff3e6..326800e6dc2 100644
--- a/spec/support/shared_examples/lib/gitlab/position_formatters_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/position_formatters_shared_examples.rb
@@ -32,7 +32,21 @@ RSpec.shared_examples "position formatter" do
subject { formatter.to_h }
- it { is_expected.to eq(formatter_hash) }
+ context 'when file_identifier_hash is disabled' do
+ before do
+ stub_feature_flags(file_identifier_hash: false)
+ end
+
+ it { is_expected.to eq(formatter_hash.except(:file_identifier_hash)) }
+ end
+
+ context 'when file_identifier_hash is enabled' do
+ before do
+ stub_feature_flags(file_identifier_hash: true)
+ end
+
+ it { is_expected.to eq(formatter_hash) }
+ end
end
describe '#==' do