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--.projections.json.example22
-rw-r--r--.rubocop.yml5
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.checksum2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/assets/javascripts/blob/components/blob_content.vue17
-rw-r--r--app/assets/javascripts/blob/components/table_contents.vue1
-rw-r--r--app/assets/javascripts/feature_flags/components/empty_state.vue1
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue6
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/index.js5
-rw-r--r--app/assets/javascripts/service_desk/components/service_desk_list_app.vue18
-rw-r--r--app/assets/javascripts/service_desk/queries/label.fragment.graphql6
-rw-r--r--app/assets/javascripts/service_desk/queries/milestone.fragment.graphql4
-rw-r--r--app/assets/javascripts/service_desk/queries/search_project_labels.query.graphql14
-rw-r--r--app/assets/javascripts/service_desk/queries/search_project_milestones.query.graphql17
-rw-r--r--app/assets/javascripts/user_lists/components/user_list.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_area_chart.vue9
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue6
-rw-r--r--app/views/groups/packages/index.html.haml2
-rw-r--r--app/views/projects/edit.html.haml4
-rw-r--r--app/views/projects/feature_flags/index.html.haml2
-rw-r--r--app/views/projects/feature_flags_user_lists/index.html.haml2
-rw-r--r--app/views/projects/feature_flags_user_lists/show.html.haml2
-rw-r--r--app/views/projects/notes/_more_actions_dropdown.html.haml3
-rw-r--r--app/views/projects/packages/infrastructure_registry/show.html.haml2
-rw-r--r--app/views/projects/packages/packages/index.html.haml2
-rw-r--r--app/views/projects/pipelines/charts.html.haml1
-rw-r--r--app/views/shared/empty_states/_profile_tabs.html.haml6
-rw-r--r--app/views/shared/packages/_no_packages.html.haml3
-rw-r--r--config/feature_flags/development/sidekiq_execution_application_slis.yml8
-rw-r--r--config/feature_flags/development/sidekiq_queueing_application_slis.yml8
-rw-r--r--doc/administration/dedicated/index.md40
-rw-r--r--doc/development/documentation/site_architecture/folder_structure.md2
-rw-r--r--doc/development/documentation/styleguide/index.md99
-rw-r--r--doc/development/documentation/testing.md28
-rw-r--r--doc/user/product_analytics/index.md8
-rw-r--r--lib/gitlab/sidekiq_middleware/server_metrics.rb20
-rw-r--r--lib/sidebars/projects/menus/settings_menu.rb2
-rw-r--r--locale/gitlab.pot38
-rw-r--r--spec/frontend/feature_flags/components/feature_flags_spec.js2
-rw-r--r--spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js22
-rw-r--r--spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js1
-rw-r--r--spec/frontend/user_lists/components/user_lists_spec.js2
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb147
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb1
46 files changed, 315 insertions, 283 deletions
diff --git a/.projections.json.example b/.projections.json.example
index eb62d2ed36e..973a7c56d8c 100644
--- a/.projections.json.example
+++ b/.projections.json.example
@@ -59,27 +59,27 @@
"type": "source"
},
"app/presenters/*.rb": {
- "alternate": "spec/app/presenters/{}_spec.rb",
+ "alternate": "spec/presenters/{}_spec.rb",
"related": "ee/app/presenters/ee/{}.rb",
"type": "source"
},
"app/serializers/*.rb": {
- "alternate": "spec/app/serializers/{}_spec.rb",
+ "alternate": "spec/serializers/{}_spec.rb",
"related": "ee/app/serializers/ee/{}.rb",
"type": "source"
},
"app/services/*.rb": {
- "alternate": "spec/app/services/{}_spec.rb",
+ "alternate": "spec/services/{}_spec.rb",
"related": "ee/app/services/ee/{}.rb",
"type": "source"
},
"app/uploaders/*.rb": {
- "alternate": "spec/app/uploaders/{}_spec.rb",
+ "alternate": "spec/uploaders/{}_spec.rb",
"related": "ee/app/uploaders/ee/{}.rb",
"type": "source"
},
"app/validators/*.rb": {
- "alternate": "spec/app/validators/{}_spec.rb",
+ "alternate": "spec/validators/{}_spec.rb",
"related": "ee/app/validators/ee/{}.rb",
"type": "source"
},
@@ -94,7 +94,7 @@
"type": "source"
},
"app/workers/*.rb": {
- "alternate": "spec/app/workers/{}_spec.rb",
+ "alternate": "spec/workers/{}_spec.rb",
"related": "ee/app/workers/ee/{}.rb",
"type": "source"
},
@@ -185,22 +185,22 @@
"type": "source"
},
"ee/app/serializers/ee/*.rb": {
- "alternate": "spec/app/serializers/{}_spec.rb",
+ "alternate": "spec/serializers/{}_spec.rb",
"related": "app/serializers/{}.rb",
"type": "source"
},
"ee/app/services/ee/*.rb": {
- "alternate": "spec/app/services/{}_spec.rb",
+ "alternate": "spec/services/{}_spec.rb",
"related": "app/services/{}.rb",
"type": "source"
},
"ee/app/uploaders/ee/*.rb": {
- "alternate": "spec/app/uploaders/{}_spec.rb",
+ "alternate": "spec/uploaders/{}_spec.rb",
"related": "app/uploaders/{}.rb",
"type": "source"
},
"ee/app/validators/ee/*.rb": {
- "alternate": "spec/app/validators/{}_spec.rb",
+ "alternate": "spec/validators/{}_spec.rb",
"related": "app/validators/{}.rb",
"type": "source"
},
@@ -215,7 +215,7 @@
"type": "source"
},
"ee/app/workers/ee/*.rb": {
- "alternate": "spec/app/workers/{}_spec.rb",
+ "alternate": "spec/workers/{}_spec.rb",
"related": "app/workers/{}.rb",
"type": "source"
},
diff --git a/.rubocop.yml b/.rubocop.yml
index c3bba48bceb..25c3b79f522 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -115,6 +115,11 @@ Layout/LineLength:
Lint/LastKeywordArgument:
Safe: false
+Lint/Debugger:
+ DebuggerMethods:
+ PryShell:
+ binding.pry_shell
+
Lint/EmptyFile:
Exclude:
- 'db/seeds.rb'
diff --git a/Gemfile b/Gemfile
index cfcd00021a8..173047db127 100644
--- a/Gemfile
+++ b/Gemfile
@@ -476,7 +476,7 @@ group :test do
gem 'capybara', '~> 3.39', '>= 3.39.2'
gem 'capybara-screenshot', '~> 1.0.26'
- gem 'selenium-webdriver', '= 4.10.0'
+ gem 'selenium-webdriver', '= 4.11.0'
gem 'graphlyte', '~> 1.0.0'
diff --git a/Gemfile.checksum b/Gemfile.checksum
index 074777fb564..d53c4081989 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -564,7 +564,7 @@
{"name":"sawyer","version":"0.9.2","platform":"ruby","checksum":"fa3a72d62a4525517b18857ddb78926aab3424de0129be6772a8e2ba240e7aca"},
{"name":"sd_notify","version":"0.1.1","platform":"ruby","checksum":"cbc7ac6caa7cedd26b30a72b5eeb6f36050dc0752df263452ea24fb5a4ad3131"},
{"name":"seed-fu","version":"2.3.7","platform":"ruby","checksum":"f19673443e9af799b730e3d4eca6a89b39e5a36825015dffd00d02ea3365cf74"},
-{"name":"selenium-webdriver","version":"4.10.0","platform":"ruby","checksum":"a322af38f9a8966a6c3ab85c365b08c5556cdef72f577905b2b42469faee9d43"},
+{"name":"selenium-webdriver","version":"4.11.0","platform":"ruby","checksum":"4c7991756ec3109b3d6a4b062df3858eaa00382299d1ccbadf37503004ac4073"},
{"name":"semver_dialects","version":"1.2.1","platform":"ruby","checksum":"60a1f67659f79c51a667e8858ec9b089c1e4ce4f6d2a0f0b4ac101916946eb23"},
{"name":"sentry-rails","version":"5.8.0","platform":"ruby","checksum":"c11b2d909de2c2bfda793c45f64180fd784d54c46886338b683ee3f8efa7731b"},
{"name":"sentry-raven","version":"3.1.2","platform":"ruby","checksum":"103d3b122958810d34898ce2e705bcf549ddb9d855a70ce9a3970ee2484f364a"},
diff --git a/Gemfile.lock b/Gemfile.lock
index 93810ded26b..345e814c264 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1452,7 +1452,7 @@ GEM
seed-fu (2.3.7)
activerecord (>= 3.1)
activesupport (>= 3.1)
- selenium-webdriver (4.10.0)
+ selenium-webdriver (4.11.0)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
@@ -1980,7 +1980,7 @@ DEPENDENCIES
sassc-rails (~> 2.1.0)
sd_notify (~> 0.1.0)
seed-fu (~> 2.3.7)
- selenium-webdriver (= 4.10.0)
+ selenium-webdriver (= 4.11.0)
semver_dialects (~> 1.2.1)
sentry-rails (~> 5.8.0)
sentry-raven (~> 3.1)
diff --git a/app/assets/javascripts/blob/components/blob_content.vue b/app/assets/javascripts/blob/components/blob_content.vue
index f032e2e7fb8..cb9997b7c54 100644
--- a/app/assets/javascripts/blob/components/blob_content.vue
+++ b/app/assets/javascripts/blob/components/blob_content.vue
@@ -3,7 +3,11 @@ import { GlLoadingIcon } from '@gitlab/ui';
import { RichViewer, SimpleViewer } from '~/vue_shared/components/blob_viewers';
import BlobContentError from './blob_content_error.vue';
-import { BLOB_RENDER_EVENT_LOAD, BLOB_RENDER_EVENT_SHOW_SOURCE } from './constants';
+import {
+ BLOB_RENDER_EVENT_LOAD,
+ BLOB_RENDER_EVENT_SHOW_SOURCE,
+ RICH_BLOB_VIEWER,
+} from './constants';
export default {
name: 'BlobContent',
@@ -47,6 +51,9 @@ export default {
default: false,
},
},
+ data() {
+ return { richContentLoaded: false };
+ },
computed: {
viewer() {
switch (this.activeViewer.type) {
@@ -59,13 +66,18 @@ export default {
viewerError() {
return this.activeViewer.renderError;
},
+ isContentLoaded() {
+ return this.activeViewer.type === RICH_BLOB_VIEWER
+ ? !this.loading && this.richContentLoaded
+ : !this.loading;
+ },
},
BLOB_RENDER_EVENT_LOAD,
BLOB_RENDER_EVENT_SHOW_SOURCE,
};
</script>
<template>
- <div class="blob-viewer" :data-type="activeViewer.type" :data-loaded="!loading">
+ <div class="blob-viewer" :data-type="activeViewer.type" :data-loaded="isContentLoaded">
<gl-loading-icon v-if="loading" size="lg" color="dark" class="my-4 mx-auto" />
<template v-else>
@@ -87,6 +99,7 @@ export default {
:type="activeViewer.fileType"
:hide-line-numbers="hideLineNumbers"
data-qa-selector="blob_viewer_file_content"
+ @richContentLoaded="richContentLoaded = true"
/>
</template>
</div>
diff --git a/app/assets/javascripts/blob/components/table_contents.vue b/app/assets/javascripts/blob/components/table_contents.vue
index ee8bd23f844..d59e357877d 100644
--- a/app/assets/javascripts/blob/components/table_contents.vue
+++ b/app/assets/javascripts/blob/components/table_contents.vue
@@ -25,7 +25,6 @@ export default {
} else if (blobViewerAttr('data-loaded') === 'true') {
this.isHidden = false;
this.generateHeaders();
-
this.observer.disconnect();
}
});
diff --git a/app/assets/javascripts/feature_flags/components/empty_state.vue b/app/assets/javascripts/feature_flags/components/empty_state.vue
index a66215cdae6..60aeb297700 100644
--- a/app/assets/javascripts/feature_flags/components/empty_state.vue
+++ b/app/assets/javascripts/feature_flags/components/empty_state.vue
@@ -81,6 +81,7 @@ export default {
v-else-if="emptyState"
:title="emptyTitle"
:svg-path="errorStateSvgPath"
+ :svg-height="150"
data-testid="empty-state"
>
<template #description>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue b/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue
index 486c3ef31c5..c3999d037e3 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue
@@ -189,7 +189,11 @@ export default {
@delete="deletePackages"
>
<template #empty-state>
- <gl-empty-state :title="emptyStateTitle" :svg-path="emptyListIllustration">
+ <gl-empty-state
+ :title="emptyStateTitle"
+ :svg-path="emptyListIllustration"
+ :svg-height="150"
+ >
<template #description>
<gl-sprintf v-if="hasFilters" :message="$options.i18n.widenFilters" />
<gl-sprintf v-else :message="$options.i18n.noResultsText">
diff --git a/app/assets/javascripts/projects/pipelines/charts/index.js b/app/assets/javascripts/projects/pipelines/charts/index.js
index 0cfea401be6..35c8046bfe7 100644
--- a/app/assets/javascripts/projects/pipelines/charts/index.js
+++ b/app/assets/javascripts/projects/pipelines/charts/index.js
@@ -2,6 +2,8 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+import { TYPENAME_PROJECT } from '~/graphql_shared/constants';
import ProjectPipelinesCharts from './components/app.vue';
Vue.use(VueApollo);
@@ -12,6 +14,7 @@ const apolloProvider = new VueApollo({
const mountPipelineChartsApp = (el) => {
const {
+ projectId,
projectPath,
failedPipelinesLink,
coverageChartPath,
@@ -22,6 +25,7 @@ const mountPipelineChartsApp = (el) => {
const shouldRenderDoraCharts = parseBoolean(el.dataset.shouldRenderDoraCharts);
const shouldRenderQualitySummary = parseBoolean(el.dataset.shouldRenderQualitySummary);
+ const contextId = convertToGraphQLId(TYPENAME_PROJECT, projectId);
return new Vue({
el,
@@ -39,6 +43,7 @@ const mountPipelineChartsApp = (el) => {
defaultBranch,
testRunsEmptyStateImagePath,
projectQualitySummaryFeedbackImagePath,
+ contextId,
},
render: (createElement) => createElement(ProjectPipelinesCharts, {}),
});
diff --git a/app/assets/javascripts/service_desk/components/service_desk_list_app.vue b/app/assets/javascripts/service_desk/components/service_desk_list_app.vue
index 7ecb318f788..e4b8142e153 100644
--- a/app/assets/javascripts/service_desk/components/service_desk_list_app.vue
+++ b/app/assets/javascripts/service_desk/components/service_desk_list_app.vue
@@ -36,11 +36,11 @@ import {
} from '~/issues/list/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { TYPENAME_USER } from '~/graphql_shared/constants';
-import searchUsersQuery from '~/issues/list/queries/search_users.query.graphql';
-import searchLabelsQuery from '~/issues/list/queries/search_labels.query.graphql';
-import searchMilestonesQuery from '~/issues/list/queries/search_milestones.query.graphql';
+import searchProjectMembers from '~/graphql_shared/queries/project_user_members_search.query.graphql';
import getServiceDeskIssuesQuery from 'ee_else_ce/service_desk/queries/get_service_desk_issues.query.graphql';
import getServiceDeskIssuesCounts from 'ee_else_ce/service_desk/queries/get_service_desk_issues_counts.query.graphql';
+import searchProjectLabelsQuery from '../queries/search_project_labels.query.graphql';
+import searchProjectMilestonesQuery from '../queries/search_project_milestones.query.graphql';
import {
errorFetchingCounts,
errorFetchingIssues,
@@ -316,8 +316,8 @@ export default {
fetchUsers(search) {
return this.$apollo
.query({
- query: searchUsersQuery,
- variables: { fullPath: this.fullPath, search, isProject: this.isProject },
+ query: searchProjectMembers,
+ variables: { fullPath: this.fullPath, search },
})
.then(({ data }) =>
data[WORKSPACE_PROJECT]?.[`${WORKSPACE_PROJECT}Members`].nodes.map(
@@ -328,8 +328,8 @@ export default {
fetchMilestones(search) {
return this.$apollo
.query({
- query: searchMilestonesQuery,
- variables: { fullPath: this.fullPath, search, isProject: this.isProject },
+ query: searchProjectMilestonesQuery,
+ variables: { fullPath: this.fullPath, search },
})
.then(({ data }) => data[WORKSPACE_PROJECT]?.milestones.nodes);
},
@@ -342,8 +342,8 @@ export default {
fetchLabelsWithFetchPolicy(search, fetchPolicy = fetchPolicies.CACHE_FIRST) {
return this.$apollo
.query({
- query: searchLabelsQuery,
- variables: { fullPath: this.fullPath, search, isProject: this.isProject },
+ query: searchProjectLabelsQuery,
+ variables: { fullPath: this.fullPath, search },
fetchPolicy,
})
.then(({ data }) => data[WORKSPACE_PROJECT]?.labels.nodes)
diff --git a/app/assets/javascripts/service_desk/queries/label.fragment.graphql b/app/assets/javascripts/service_desk/queries/label.fragment.graphql
new file mode 100644
index 00000000000..bb1d8f1ac9b
--- /dev/null
+++ b/app/assets/javascripts/service_desk/queries/label.fragment.graphql
@@ -0,0 +1,6 @@
+fragment Label on Label {
+ id
+ color
+ textColor
+ title
+}
diff --git a/app/assets/javascripts/service_desk/queries/milestone.fragment.graphql b/app/assets/javascripts/service_desk/queries/milestone.fragment.graphql
new file mode 100644
index 00000000000..3cdf69bf585
--- /dev/null
+++ b/app/assets/javascripts/service_desk/queries/milestone.fragment.graphql
@@ -0,0 +1,4 @@
+fragment Milestone on Milestone {
+ id
+ title
+}
diff --git a/app/assets/javascripts/service_desk/queries/search_project_labels.query.graphql b/app/assets/javascripts/service_desk/queries/search_project_labels.query.graphql
new file mode 100644
index 00000000000..89ce14134b4
--- /dev/null
+++ b/app/assets/javascripts/service_desk/queries/search_project_labels.query.graphql
@@ -0,0 +1,14 @@
+#import "./label.fragment.graphql"
+
+query searchProjectLabels($fullPath: ID!, $search: String) {
+ project(fullPath: $fullPath) @persist {
+ id
+ labels(searchTerm: $search, includeAncestorGroups: true) {
+ __persist
+ nodes {
+ __persist
+ ...Label
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/service_desk/queries/search_project_milestones.query.graphql b/app/assets/javascripts/service_desk/queries/search_project_milestones.query.graphql
new file mode 100644
index 00000000000..f34166be87d
--- /dev/null
+++ b/app/assets/javascripts/service_desk/queries/search_project_milestones.query.graphql
@@ -0,0 +1,17 @@
+#import "./milestone.fragment.graphql"
+
+query searchProjectMilestones($fullPath: ID!, $search: String) {
+ project(fullPath: $fullPath) {
+ id
+ milestones(
+ searchTitle: $search
+ includeAncestors: true
+ sort: EXPIRED_LAST_DUE_DATE_ASC
+ state: active
+ ) {
+ nodes {
+ ...Milestone
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/user_lists/components/user_list.vue b/app/assets/javascripts/user_lists/components/user_list.vue
index e86b3f81daa..475d83dc58d 100644
--- a/app/assets/javascripts/user_lists/components/user_list.vue
+++ b/app/assets/javascripts/user_lists/components/user_list.vue
@@ -137,6 +137,7 @@ export default {
:title="$options.translations.emptyStateTitle"
:description="$options.translations.emptyStateDescription"
:svg-path="emptyStatePath"
+ :svg-height="150"
/>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue b/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue
index 2ecf686b1c3..11ce6afbb1d 100644
--- a/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue
@@ -29,6 +29,7 @@ export default {
await this.$nextTick();
handleBlobRichViewer(this.$refs.content, this.type);
handleLocationHash();
+ this.$emit('richContentLoaded');
});
},
safeHtmlConfig: {
diff --git a/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_area_chart.vue b/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_area_chart.vue
index b4751d51fcb..7889b558279 100644
--- a/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_area_chart.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_area_chart.vue
@@ -1,5 +1,6 @@
<script>
import { v4 as uuidv4 } from 'uuid';
+import { GlSkeletonLoader } from '@gitlab/ui';
import { GlAreaChart } from '@gitlab/ui/dist/charts';
import { CHART_CONTAINER_HEIGHT } from './constants';
@@ -7,6 +8,7 @@ export default {
name: 'CiCdAnalyticsAreaChart',
components: {
GlAreaChart,
+ GlSkeletonLoader,
},
props: {
chartData: {
@@ -17,6 +19,11 @@ export default {
type: Object,
required: true,
},
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data: () => ({
chartKey: uuidv4(),
@@ -35,7 +42,9 @@ export default {
<p>
<slot></slot>
</p>
+ <gl-skeleton-loader v-if="loading" :width="300" :lines="3" />
<gl-area-chart
+ v-else
v-bind="$attrs"
:key="chartKey"
responsive
diff --git a/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue b/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue
index 3b1b075559a..d1e1fe162f4 100644
--- a/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue
@@ -18,6 +18,11 @@ export default {
required: true,
type: Object,
},
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -58,6 +63,7 @@ export default {
v-bind="$attrs"
:chart-data="chart.data"
:area-chart-options="chartOptions"
+ :loading="loading"
>
<slot name="alerts"></slot>
<p>{{ dateRange }}</p>
diff --git a/app/views/groups/packages/index.html.haml b/app/views/groups/packages/index.html.haml
index 6d0f24bf08c..4fda4e2b447 100644
--- a/app/views/groups/packages/index.html.haml
+++ b/app/views/groups/packages/index.html.haml
@@ -6,7 +6,7 @@
full_path: @group.full_path,
endpoint: group_packages_path(@group),
page_type: 'groups',
- empty_list_illustration: image_path('illustrations/no-packages.svg'),
+ empty_list_illustration: image_path('illustrations/empty-state/empty-package-md.svg'),
npm_instance_url: package_registry_instance_url(:npm),
project_list_url: '',
settings_path: show_group_package_registry_settings(@group) ? group_settings_packages_and_registries_path(@group) : '',
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index b2054382668..b9149bbd7b3 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -40,8 +40,6 @@
- c.with_body do
= _('On the left sidebar, select %{merge_requests_link} to view them.').html_safe % { merge_requests_link: link_to('Settings > Merge requests', project_settings_merge_requests_path(@project)).html_safe }
-= render_if_exists 'projects/settings/analytics', expanded: expanded
-
%section.settings.no-animate{ class: ('expanded' if expanded), data: { qa_selector: 'badges_settings_content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
@@ -60,8 +58,6 @@
= render 'projects/service_desk_settings'
-= render_if_exists 'product_analytics/project_settings', expanded: expanded
-
%section.settings.advanced-settings.no-animate#js-project-advanced-settings{ class: ('expanded' if expanded), data: { qa_selector: 'advanced_settings_content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Advanced')
diff --git a/app/views/projects/feature_flags/index.html.haml b/app/views/projects/feature_flags/index.html.haml
index e473a6f3cfd..ec0830ad153 100644
--- a/app/views/projects/feature_flags/index.html.haml
+++ b/app/views/projects/feature_flags/index.html.haml
@@ -3,7 +3,7 @@
#feature-flags-vue{ data: { endpoint: project_feature_flags_path(@project, format: :json),
"project-id" => @project.id,
"project-name" => @project.name,
- "error-state-svg-path" => image_path('illustrations/feature_flag.svg'),
+ "error-state-svg-path" => image_path('illustrations/empty-state/empty-feature-flag-md.svg'),
"feature-flags-help-page-path" => help_page_path("operations/feature_flags"),
"feature-flags-client-libraries-help-page-path" => help_page_path("operations/feature_flags", anchor: "choose-a-client-library"),
"feature-flags-client-example-help-page-path" => help_page_path("operations/feature_flags", anchor: "go-application-example"),
diff --git a/app/views/projects/feature_flags_user_lists/index.html.haml b/app/views/projects/feature_flags_user_lists/index.html.haml
index c0e98b27d29..2e279d71758 100644
--- a/app/views/projects/feature_flags_user_lists/index.html.haml
+++ b/app/views/projects/feature_flags_user_lists/index.html.haml
@@ -5,4 +5,4 @@
#js-user-lists{ data: { project_id: @project.id,
feature_flags_help_page_path: help_page_path("operations/feature_flags"),
new_user_list_path: can?(current_user, :create_feature_flag, @project) ? new_project_feature_flags_user_list_path(@project): nil,
- error_state_svg_path: image_path('illustrations/feature_flag.svg') } }
+ error_state_svg_path: image_path('illustrations/empty-state/empty-feature-flag-md.svg') } }
diff --git a/app/views/projects/feature_flags_user_lists/show.html.haml b/app/views/projects/feature_flags_user_lists/show.html.haml
index 5c4e93e7707..58276eedc09 100644
--- a/app/views/projects/feature_flags_user_lists/show.html.haml
+++ b/app/views/projects/feature_flags_user_lists/show.html.haml
@@ -5,4 +5,4 @@
#js-edit-user-list{ data: { project_id: @project.id,
user_list_iid: @user_list.iid,
- empty_state_path: image_path('illustrations/feature_flag.svg') } }
+ empty_state_path: image_path('illustrations/empty-state/empty-feature-flag-md.svg') } }
diff --git a/app/views/projects/notes/_more_actions_dropdown.html.haml b/app/views/projects/notes/_more_actions_dropdown.html.haml
index 8c94a18e1b0..e3cc9199352 100644
--- a/app/views/projects/notes/_more_actions_dropdown.html.haml
+++ b/app/views/projects/notes/_more_actions_dropdown.html.haml
@@ -2,8 +2,7 @@
- if note_editable || !is_current_user
%div{ class: "dropdown more-actions note-actions-item gl-ml-0!" }
- = button_tag title: 'More actions', class: 'note-action-button more-actions-toggle has-tooltip btn gl-button btn-default-tertiary btn-icon', data: { toggle: 'dropdown', container: 'body', qa_selector: 'more_actions_dropdown' } do
- = sprite_icon('ellipsis_v', css_class: 'gl-button-icon gl-icon')
+ = render Pajamas::ButtonComponent.new(icon: 'ellipsis_v', category: :tertiary, button_options: { class: 'note-action-button more-actions-toggle has-tooltip', data: { title: 'More actions', toggle: 'dropdown', container: 'body', qa_selector: 'more_actions_dropdown' }})
%ul.dropdown-menu.more-actions-dropdown.dropdown-open-left
%li
= clipboard_button(text: noteable_note_url(note), title: _('Copy reference'), button_text: _('Copy link'), class: 'btn-clipboard', hide_tooltip: true, hide_button_icon: true)
diff --git a/app/views/projects/packages/infrastructure_registry/show.html.haml b/app/views/projects/packages/infrastructure_registry/show.html.haml
index 8624fdacda7..8410ac0091d 100644
--- a/app/views/projects/packages/infrastructure_registry/show.html.haml
+++ b/app/views/projects/packages/infrastructure_registry/show.html.haml
@@ -7,7 +7,7 @@
.col-12
#js-vue-packages-detail{ data: { package: package_from_presenter(@package),
can_delete: can?(current_user, :destroy_package, @project).to_s,
- svg_path: image_path('illustrations/no-packages.svg'),
+ svg_path: image_path('illustrations/empty-state/empty-package-md.svg'),
project_name: @project.name,
project_path: @project.root_ancestor.full_path,
gitlab_host: Gitlab.config.gitlab.host,
diff --git a/app/views/projects/packages/packages/index.html.haml b/app/views/projects/packages/packages/index.html.haml
index 5397828d48e..9fb265b08c2 100644
--- a/app/views/projects/packages/packages/index.html.haml
+++ b/app/views/projects/packages/packages/index.html.haml
@@ -6,7 +6,7 @@
full_path: @project.full_path,
endpoint: project_packages_path(@project),
page_type: 'projects',
- empty_list_illustration: image_path('illustrations/no-packages.svg'),
+ empty_list_illustration: image_path('illustrations/empty-state/empty-package-md.svg'),
npm_instance_url: package_registry_instance_url(:npm),
project_list_url: project_packages_path(@project),
settings_path: show_package_registry_settings(@project) ? project_settings_packages_and_registries_path(@project) : '',
diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml
index e16a2235e53..c3d6d0c5971 100644
--- a/app/views/projects/pipelines/charts.html.haml
+++ b/app/views/projects/pipelines/charts.html.haml
@@ -1,6 +1,7 @@
- page_title _('CI/CD Analytics')
#js-project-pipelines-charts-app{ data: { project_path: @project.full_path,
+ project_id: @project.id,
should_render_dora_charts: should_render_dora_charts.to_s,
should_render_quality_summary: should_render_quality_summary.to_s,
failed_pipelines_link: project_pipelines_path(@project, page: '1', scope: 'all', status: 'failed'),
diff --git a/app/views/shared/empty_states/_profile_tabs.html.haml b/app/views/shared/empty_states/_profile_tabs.html.haml
index ba5fbd90528..d71ed963fd1 100644
--- a/app/views/shared/empty_states/_profile_tabs.html.haml
+++ b/app/views/shared/empty_states/_profile_tabs.html.haml
@@ -12,10 +12,10 @@
- if current_user_empty_message_description.present?
%p= current_user_empty_message_description
- - if secondary_button_link.present?
- = link_button_to secondary_button_label, secondary_button_link, variant: :confirm, category: :secondary
-
- if primary_button_link.present?
= link_button_to primary_button_label, primary_button_link, variant: :confirm
+
+ - if secondary_button_link.present?
+ = link_button_to secondary_button_label, secondary_button_link, variant: :confirm, category: :secondary
- else
%h5= visitor_empty_message
diff --git a/app/views/shared/packages/_no_packages.html.haml b/app/views/shared/packages/_no_packages.html.haml
index ae5c2cfd378..7cc8110fb6b 100644
--- a/app/views/shared/packages/_no_packages.html.haml
+++ b/app/views/shared/packages/_no_packages.html.haml
@@ -1,4 +1,5 @@
-.svg-content= image_tag 'illustrations/no-packages.svg'
+.svg-content.svg-150
+ = image_tag 'illustrations/empty-state/empty-package-md.svg'
.text-content
%h4.text-center= _('There are no packages yet')
%p
diff --git a/config/feature_flags/development/sidekiq_execution_application_slis.yml b/config/feature_flags/development/sidekiq_execution_application_slis.yml
deleted file mode 100644
index 4c1dcda82c0..00000000000
--- a/config/feature_flags/development/sidekiq_execution_application_slis.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: sidekiq_execution_application_slis
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/116827
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/407325
-milestone: '15.11'
-type: development
-group: group::scalability
-default_enabled: false
diff --git a/config/feature_flags/development/sidekiq_queueing_application_slis.yml b/config/feature_flags/development/sidekiq_queueing_application_slis.yml
deleted file mode 100644
index 9968948e42b..00000000000
--- a/config/feature_flags/development/sidekiq_queueing_application_slis.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: sidekiq_queueing_application_slis
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121141
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/412092
-milestone: '16.2'
-type: development
-group: group::scalability
-default_enabled: false
diff --git a/doc/administration/dedicated/index.md b/doc/administration/dedicated/index.md
index c99e0593f05..828ea110d23 100644
--- a/doc/administration/dedicated/index.md
+++ b/doc/administration/dedicated/index.md
@@ -35,15 +35,41 @@ To request the creation of a new GitLab Dedicated environment for your organizat
### Maintenance window
-When onboarding, you must also specify your preference for the weekly four-hour time slot that GitLab uses to perform maintenance and upgrade operations on the tenant instance.
+When onboarding, you must also specify your preference for the weekly four-hour time slot that GitLab uses to perform routine maintenance and upgrade operations on all tenant instances.
-- APAC (outside working hours): Wednesday 1 AM - 5 PM UTC
-- EU (outside working hours): Tuesday 1 AM - 5 AM UTC
-- AMER Option 1 (outside working hours): Tuesday 7 AM - 11 AM UTC
-- AMER Option 2 (outside working hours): Sunday 9 PM - Monday 1 AM UTC
+Available scheduled mainenance windows, performed outside standard working hours:
-NOTE:
-Some downtime may be incurred during this window. This downtime is not counting towards [the system SLA](https://about.gitlab.com/handbook/engineering/infrastructure/team/gitlab-dedicated/slas/).
+- APAC: Wednesday 1 AM - 5 PM UTC
+- EU: Tuesday 1 AM - 5 AM UTC
+- AMER Option 1: Tuesday 7 AM - 11 AM UTC
+- AMER Option 2: Sunday 9 PM - Monday 1 AM UTC
+
+Consider the following notes:
+
+- Some downtime might be incurred during this window. This downtime does not count toward
+ [the system SLA](https://about.gitlab.com/handbook/engineering/infrastructure/team/gitlab-dedicated/slas/).
+- The weekly scheduled mainenance window can be postponed into another window within the same week.
+ This option needs to be agreed with the assigned Customer Success Manager at least one week in advance.
+- The scheduled weekly maintenance window is different from
+ [emergency maintenance](#emergency-maintenance).
+
+#### Emergency maintenance
+
+In an event of a platform outage, degradation or a security event requiring urgent action,
+emergency maintenance will be carried out per
+[the emergency change processes](https://about.gitlab.com/handbook/engineering/infrastructure/emergency-change-processes/).
+
+The emergency maintenance is initiated urgently when urgent actions need to be executed by GitLab
+on a Dedicated tenant instance.
+Communication with the customer will be provided on best effort basis prior to commencing the
+maintenance, and full communication will follow after the immediate action is carried out.
+
+For example, when a critical security process is initiated to address an S1 vulnerability in GitLab,
+emergency maintenance is carried out to upgrade GitLab to the non-vulnerable version and that
+can occur outside of a scheduled maintenance window.
+Postponing emergency maintenance is not possible, because the same process must be applied to all
+existing Dedicated customers, and the primary concern is to ensure safety and availability of
+Dedicated tenant instances.
## Configuration changes
diff --git a/doc/development/documentation/site_architecture/folder_structure.md b/doc/development/documentation/site_architecture/folder_structure.md
index 1c9fc1441c4..d4a3c856e0a 100644
--- a/doc/development/documentation/site_architecture/folder_structure.md
+++ b/doc/development/documentation/site_architecture/folder_structure.md
@@ -75,7 +75,7 @@ place for it.
## Avoid duplication
Do not include the same information in multiple places.
-[Link to a single source of truth instead.](../styleguide/index.md#link-instead-of-repeating-text)
+Link to a single source of truth instead.
For example, if you have code in a repository other than the [primary repositories](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/architecture.md),
and documentation in the same repository, you can keep the documentation in that repository.
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index 512424a0da3..2d5963f82cc 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -33,66 +33,33 @@ This policy prevents information silos, making it easier to find information
about GitLab products. It also informs decisions about the kinds of content that
is included in the documentation.
-### Topic types
+## Topic types
-In the software industry, it is a best practice to organize documentation in
-different types. For example:
+GitLab uses [topic types](../topic_types/index.md) to organize the product documentation.
-- Concepts
-- Tasks
-- Reference
-- Troubleshooting
+Topic types help users digest information more quickly. They also help address these issues:
-At GitLab, we have not traditionally used topic types. However, we are starting to
-move in this direction, so we can address these issues:
-
-- **Content is hard to find.** Our docs are comprehensive and include a large amount of
- useful information. Topic types create repeatable patterns that make our content easier
+- **Content is hard to find.** The GitLab docs are comprehensive and include a large amount of
+ useful information. Topic types create repeatable patterns that make the content easier
to scan and parse.
-- **Content is often written from the contributor's point of view.** Our docs
- are written by contributors. Topic types (tasks specifically) help put
+- **Content is often written from the contributor's point of view.** The GitLab docs
+ are written by a variety of contributors. Topic types (tasks, specifically) help put
information into a format that is geared toward helping others, rather than
documenting how a feature was implemented.
-GitLab uses these [topic types](../topic_types/index.md).
-
-### Link instead of repeating text
-
-Rather than repeating information from another topic, link to the single source
-of truth and explain why it is important.
+## Docs-first methodology
-### Docs-first methodology
-
-We employ a documentation-first methodology. This method ensures the documentation
-remains a complete and trusted resource, and makes communicating about the use
-of GitLab more efficient.
+The product documentation should be a complete and trusted resource.
- If the answer to a question exists in documentation, share the link to the
documentation instead of rephrasing the information.
-- When you encounter new information not available in GitLab documentation (for
- example, when working on a support case or testing a feature), your first step
- should be to create a merge request (MR) to add this information to the
- documentation. You can then share the MR to communicate this information.
-
-New information that would be useful toward the future usage or troubleshooting
-of GitLab should not be written directly in a forum or other messaging system,
-but added to a documentation MR and then referenced, as described above.
+- When you encounter information that's not available in GitLab documentation,
+ create a merge request (MR) to add the information to the
+ documentation. Then share the MR to communicate the information.
The more we reflexively add information to the documentation, the more
the documentation helps others efficiently accomplish tasks and solve problems.
-If you have questions when considering, authoring, or editing documentation, ask
-the Technical Writing team. They're available on Slack in `#docs` or in GitLab by
-mentioning [the writer for](https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments)
-the applicable [DevOps stage or group](https://about.gitlab.com/handbook/product/categories/#devops-stages).
-Otherwise, forge ahead with your best effort. It does not need to be perfect;
-the team is happy to review and improve upon your content. Review the
-[Documentation guidelines](index.md) before you begin your first documentation MR.
-
-Maintaining a knowledge base separate from the documentation would
-be against the documentation-first methodology because the content would overlap with
-the documentation.
-
## Writing for localization
The GitLab documentation is not localized, but we follow guidelines that
@@ -112,7 +79,7 @@ also aid in consistency, which is important for localization.
## Markdown
-All GitLab documentation is written using [Markdown](https://en.wikipedia.org/wiki/Markdown).
+All GitLab documentation is written in [Markdown](https://en.wikipedia.org/wiki/Markdown).
The [documentation website](https://docs.gitlab.com) uses [GitLab Kramdown](https://gitlab.com/gitlab-org/ruby/gems/gitlab_kramdown),
a "flavored" Kramdown engine to render pages from Markdown to HTML. The use of Kramdown
@@ -122,6 +89,8 @@ linked style guide. You can't use Kramdown-specific markup (for example, `{:.cla
For a complete Kramdown reference, see the
[GitLab Markdown Guide](https://about.gitlab.com/handbook/markdown-guide/).
+The Markdown format is [tested](../testing.md) by using markdownlint and Vale.
+
### HTML in Markdown
Hard-coded HTML is valid, although it's discouraged from being used. HTML is permitted if:
@@ -153,44 +122,6 @@ Use backticks for:
- Commands, parameters, and filenames.
- Values. For example: "In the **Name** text box, type `test`."
-### Markdown Rules
-
-GitLab ensures that the Markdown used across all documentation is consistent, as
-well as easy to review and maintain, by [testing documentation changes](../testing.md)
-with [markdownlint](../testing.md#markdownlint). This lint test fails when any
-document has an issue with Markdown formatting that may cause the page to render
-incorrectly in GitLab. It also fails when a document has
-non-standard Markdown (which may render correctly, but is not the current
-standard for GitLab documentation).
-
-#### Markdown rule `MD044/proper-names` (capitalization)
-
-A rule that could cause confusion is `MD044/proper-names`, as it might not be
-immediately clear what caused markdownlint to fail, or how to correct the
-failure. This rule checks a list of known words, listed in the `.markdownlint.yml`
-file in each project, to verify proper use of capitalization and backticks.
-Words in backticks are ignored by markdownlint.
-
-In general, product names should follow the exact capitalization of the official
-names of the products, protocols, and so on.
-
-Some examples fail if incorrect capitalization is used:
-
-- MinIO (needs capital `IO`)
-- NGINX (needs all capitals)
-- runit (needs lowercase `r`)
-
-Additionally, commands, parameters, values, filenames, and so on must be
-included in backticks. For example:
-
-- "Change the `needs` keyword in your `.gitlab-ci.yml`..."
- - `needs` is a parameter, and `.gitlab-ci.yml` is a file, so both need backticks.
- Additionally, `.gitlab-ci.yml` without backticks fails markdownlint because it
- does not have capital G or L.
-- "Run `git clone` to clone a Git repository..."
- - `git clone` is a command, so it must be lowercase, while Git is the product,
- so it must have a capital G.
-
## Metadata
Each documentation Markdown page contains YAML front matter.
diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md
index 781ab8e2139..d556d486b67 100644
--- a/doc/development/documentation/testing.md
+++ b/doc/development/documentation/testing.md
@@ -274,6 +274,34 @@ You can use markdownlint:
- [In a code editor](#configure-editors).
- [In a `pre-push` hook](#configure-pre-push-hooks).
+#### Markdown rule `MD044/proper-names` (capitalization)
+
+A rule that can cause confusion is `MD044/proper-names`. The failure, or
+how to correct it, might not be immediately clear.
+This rule checks a list of known words, listed in the `.markdownlint.yml`
+file in each project, to verify proper use of capitalization and backticks.
+Words in backticks are ignored by markdownlint.
+
+In general, product names should follow the exact capitalization of the official
+names of the products, protocols, and so on.
+
+Some examples fail if incorrect capitalization is used:
+
+- MinIO (needs capital `IO`)
+- NGINX (needs all capitals)
+- runit (needs lowercase `r`)
+
+Additionally, commands, parameters, values, filenames, and so on must be
+included in backticks. For example:
+
+- "Change the `needs` keyword in your `.gitlab-ci.yml`..."
+ - `needs` is a parameter, and `.gitlab-ci.yml` is a file, so both need backticks.
+ Additionally, `.gitlab-ci.yml` without backticks fails markdownlint because it
+ does not have capital G or L.
+- "Run `git clone` to clone a Git repository..."
+ - `git clone` is a command, so it must be lowercase, while Git is the product,
+ so it must have a capital G.
+
### Vale
[Vale](https://vale.sh/) is a grammar, style, and word usage linter for the
diff --git a/doc/user/product_analytics/index.md b/doc/user/product_analytics/index.md
index e04c61b2c00..c2aefb3eead 100644
--- a/doc/user/product_analytics/index.md
+++ b/doc/user/product_analytics/index.md
@@ -94,11 +94,9 @@ Prerequisites:
- Product analytics must be enabled at the instance-level.
- You must have at least the Maintainer role for the project or group the project belongs to.
-1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
-1. Select **Admin Area**.
-1. Select **Settings > General**
-1. Expand **Product Analytics**.
-1. In the **Connect to your instance** section, enter the configuration values.
+1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
+1. Select **Settings > Analytics**.
+1. Expand **Configure** and enter the configuration values.
1. Select **Save changes**.
## Instrument a GitLab project
diff --git a/lib/gitlab/sidekiq_middleware/server_metrics.rb b/lib/gitlab/sidekiq_middleware/server_metrics.rb
index 058c23178f8..e7c6b586da4 100644
--- a/lib/gitlab/sidekiq_middleware/server_metrics.rb
+++ b/lib/gitlab/sidekiq_middleware/server_metrics.rb
@@ -18,7 +18,7 @@ module Gitlab
SIDEKIQ_QUEUE_DURATION_BUCKETS = [10, 60].freeze
# These labels from Gitlab::SidekiqMiddleware::MetricsHelper are included in SLI metrics
- SIDEKIQ_SLI_LABELS = [:worker, :feature_category, :urgency, :external_dependencies].freeze
+ SIDEKIQ_SLI_LABELS = [:worker, :feature_category, :urgency, :external_dependencies, :queue].freeze
class << self
include ::Gitlab::SidekiqMiddleware::MetricsHelper
@@ -64,8 +64,8 @@ module Gitlab
end
end
- Gitlab::Metrics::SidekiqSlis.initialize_execution_slis!(possible_sli_labels) if ::Feature.enabled?(:sidekiq_execution_application_slis)
- Gitlab::Metrics::SidekiqSlis.initialize_queueing_slis!(possible_sli_labels) if ::Feature.enabled?(:sidekiq_queueing_application_slis)
+ Gitlab::Metrics::SidekiqSlis.initialize_execution_slis!(possible_sli_labels)
+ Gitlab::Metrics::SidekiqSlis.initialize_queueing_slis!(possible_sli_labels)
end
end
@@ -143,16 +143,10 @@ module Gitlab
@metrics[:sidekiq_load_balancing_count].increment(labels.merge(load_balancing_labels), 1)
end
- if ::Feature.enabled?(:sidekiq_execution_application_slis)
- sli_labels = labels.slice(*SIDEKIQ_SLI_LABELS)
- Gitlab::Metrics::SidekiqSlis.record_execution_apdex(sli_labels, monotonic_time) if job_succeeded
- Gitlab::Metrics::SidekiqSlis.record_execution_error(sli_labels, !job_succeeded)
- end
-
- if ::Feature.enabled?(:sidekiq_queueing_application_slis)
- sli_labels = labels.slice(*SIDEKIQ_SLI_LABELS)
- Gitlab::Metrics::SidekiqSlis.record_queueing_apdex(sli_labels, queue_duration) if queue_duration
- end
+ sli_labels = labels.slice(*SIDEKIQ_SLI_LABELS)
+ Gitlab::Metrics::SidekiqSlis.record_execution_apdex(sli_labels, monotonic_time) if job_succeeded
+ Gitlab::Metrics::SidekiqSlis.record_execution_error(sli_labels, !job_succeeded)
+ Gitlab::Metrics::SidekiqSlis.record_queueing_apdex(sli_labels, queue_duration) if queue_duration
end
end
diff --git a/lib/sidebars/projects/menus/settings_menu.rb b/lib/sidebars/projects/menus/settings_menu.rb
index 9219312ede8..142d803037b 100644
--- a/lib/sidebars/projects/menus/settings_menu.rb
+++ b/lib/sidebars/projects/menus/settings_menu.rb
@@ -162,3 +162,5 @@ module Sidebars
end
end
end
+
+Sidebars::Projects::Menus::SettingsMenu.prepend_mod_with('Sidebars::Projects::Menus::SettingsMenu')
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index ed098833a0d..03cf80c6dac 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -5294,6 +5294,9 @@ msgstr ""
msgid "Analytics dashboards"
msgstr ""
+msgid "Analytics settings"
+msgstr ""
+
msgid "Analytics|A visualization with that name already exists."
msgstr ""
@@ -5309,6 +5312,9 @@ msgstr ""
msgid "Analytics|Analytics dashboards"
msgstr ""
+msgid "Analytics|Analytics settings for '%{project_name}' were successfully updated."
+msgstr ""
+
msgid "Analytics|Browser"
msgstr ""
@@ -14292,6 +14298,9 @@ msgstr ""
msgid "DORA4Metrics|Deploys"
msgstr ""
+msgid "DORA4Metrics|Failed to generate forecast. Try again later. If the problem persists, consider %{linkStart}creating an issue%{linkEnd}."
+msgstr ""
+
msgid "DORA4Metrics|Failed to load DORA performance scores for Namespace: %{fullPath}"
msgstr ""
@@ -14438,6 +14447,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DORA4Metrics|The forecast might be inaccurate. To improve it, select a wider time frame or try again when more data is available"
+msgstr ""
+
msgid "DORA4Metrics|This is a lower-bound approximation. Your group has too many issues and MRs to calculate in real time."
msgstr ""
@@ -36427,6 +36439,9 @@ msgstr ""
msgid "ProjectSettings|All merge requests and commits are made against this branch unless you specify a different one."
msgstr ""
+msgid "ProjectSettings|All your dashboard data sources."
+msgstr ""
+
msgid "ProjectSettings|Allow"
msgstr ""
@@ -36484,13 +36499,10 @@ msgstr ""
msgid "ProjectSettings|Combine git tags with release notes, release evidence, and assets to create a release."
msgstr ""
-msgid "ProjectSettings|Configure analytics features for this project"
-msgstr ""
-
msgid "ProjectSettings|Configure your infrastructure."
msgstr ""
-msgid "ProjectSettings|Connect to your instance"
+msgid "ProjectSettings|Connect your instance"
msgstr ""
msgid "ProjectSettings|Contact an admin to change this setting."
@@ -36505,9 +36517,15 @@ msgstr ""
msgid "ProjectSettings|Cube API key"
msgstr ""
+msgid "ProjectSettings|Custom dashboard projects"
+msgstr ""
+
msgid "ProjectSettings|Customize this project's badges."
msgstr ""
+msgid "ProjectSettings|Data sources"
+msgstr ""
+
msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
msgstr ""
@@ -36598,9 +36616,6 @@ msgstr ""
msgid "ProjectSettings|Instrument your application"
msgstr ""
-msgid "ProjectSettings|Instrument your application to track events and behaviors."
-msgstr ""
-
msgid "ProjectSettings|Instrumentation details"
msgstr ""
@@ -36697,6 +36712,9 @@ msgstr ""
msgid "ProjectSettings|Private"
msgstr ""
+msgid "ProjectSettings|Product analytics"
+msgstr ""
+
msgid "ProjectSettings|Product analytics configurator connection string"
msgstr ""
@@ -36781,6 +36799,9 @@ msgstr ""
msgid "ProjectSettings|Status checks must succeed"
msgstr ""
+msgid "ProjectSettings|Store custom configuration files."
+msgstr ""
+
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr ""
@@ -36883,9 +36904,6 @@ msgstr ""
msgid "ProjectSettings|What are merge trains?"
msgstr ""
-msgid "ProjectSettings|What is Analytics Dashboards?"
-msgstr ""
-
msgid "ProjectSettings|What is squashing?"
msgstr ""
diff --git a/spec/frontend/feature_flags/components/feature_flags_spec.js b/spec/frontend/feature_flags/components/feature_flags_spec.js
index c0cfec384f0..790568b2450 100644
--- a/spec/frontend/feature_flags/components/feature_flags_spec.js
+++ b/spec/frontend/feature_flags/components/feature_flags_spec.js
@@ -30,7 +30,7 @@ describe('Feature flags', () => {
userListPath: '/user-list',
unleashApiUrl: `${TEST_HOST}/api/unleash`,
projectName: 'fakeProjectName',
- errorStateSvgPath: '/assets/illustrations/feature_flag.svg',
+ errorStateSvgPath: '/assets/illustrations/empty-state/empty-feature-flag-md.svg',
};
const mockState = {
diff --git a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js
index 38760a724ff..94cfa53d1cd 100644
--- a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js
@@ -82,15 +82,25 @@ describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', (
]);
});
- it('should select a different chart on change', async () => {
- findSegmentedControl().vm.$emit('input', 1);
+ describe('when the date range is updated', () => {
+ let chart;
- const chart = wrapper.findComponent(CiCdAnalyticsAreaChart);
+ beforeEach(async () => {
+ chart = wrapper.findComponent(CiCdAnalyticsAreaChart);
- await nextTick();
+ await findSegmentedControl().vm.$emit('input', 1);
+ });
+
+ it('should select a different chart on change', () => {
+ expect(chart.props('chartData')).toEqual(transformedAreaChartData);
+ expect(chart.text()).toBe('Date range: test range 2');
+ });
- expect(chart.props('chartData')).toEqual(transformedAreaChartData);
- expect(chart.text()).toBe('Date range: test range 2');
+ it('will emit a `select-chart` event', () => {
+ expect(wrapper.emitted()).toEqual({
+ 'select-chart': [[1]],
+ });
+ });
});
});
diff --git a/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js b/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js
index ab2a12219e5..137100be34e 100644
--- a/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/pipeline_charts_spec.js
@@ -72,6 +72,7 @@ describe('~/projects/pipelines/charts/components/pipeline_charts.vue', () => {
expect(charts.props()).toEqual({
charts: wrapper.vm.areaCharts,
chartOptions: wrapper.vm.$options.areaChartOptions,
+ loading: false,
});
});
});
diff --git a/spec/frontend/user_lists/components/user_lists_spec.js b/spec/frontend/user_lists/components/user_lists_spec.js
index 2da2eb0dd5f..0164e7e49b2 100644
--- a/spec/frontend/user_lists/components/user_lists_spec.js
+++ b/spec/frontend/user_lists/components/user_lists_spec.js
@@ -19,7 +19,7 @@ describe('~/user_lists/components/user_lists.vue', () => {
const mockProvide = {
newUserListPath: '/user-lists/new',
featureFlagsHelpPagePath: '/help/feature-flags',
- errorStateSvgPath: '/assets/illustrations/feature_flag.svg',
+ errorStateSvgPath: '/assets/illustrations/empty-state/empty-feature-flag-md.svg',
};
const mockState = {
diff --git a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
index bc69f232d9e..e674d37ece6 100644
--- a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
@@ -59,35 +59,6 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
described_class.initialize_process_metrics
end
- shared_examples "initializes sidekiq SLIs for the workers in the current process" do
- before do
- allow(Gitlab::SidekiqConfig)
- .to receive(:current_worker_queue_mappings)
- .and_return('MergeWorker' => 'merge', 'Ci::BuildFinishedWorker' => 'default')
- allow(completion_seconds_metric).to receive(:get)
- end
-
- it "initializes the SLIs with labels" do
- expect(Gitlab::Metrics::SidekiqSlis)
- .to receive(initialize_sli_method).with([
- {
- worker: 'MergeWorker',
- urgency: 'high',
- feature_category: 'source_code_management',
- external_dependencies: 'no'
- },
- {
- worker: 'Ci::BuildFinishedWorker',
- urgency: 'high',
- feature_category: 'continuous_integration',
- external_dependencies: 'no'
- }
- ])
-
- described_class.initialize_process_metrics
- end
- end
-
shared_examples "not initializing sidekiq SLIs" do
it 'does not initialize sidekiq SLIs' do
expect(Gitlab::Metrics::SidekiqSlis)
@@ -97,35 +68,38 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
end
end
- context 'initializing execution SLIs' do
- let(:initialize_sli_method) { :initialize_execution_slis! }
-
- context 'when sidekiq_execution_application_slis FF is turned on' do
- it_behaves_like "initializes sidekiq SLIs for the workers in the current process"
- end
-
- context 'when sidekiq_execution_application_slis FF is turned off' do
- before do
- stub_feature_flags(sidekiq_execution_application_slis: false)
- end
-
- it_behaves_like "not initializing sidekiq SLIs"
+ context 'initializing execution and queueing SLIs' do
+ before do
+ allow(Gitlab::SidekiqConfig)
+ .to receive(:current_worker_queue_mappings)
+ .and_return('MergeWorker' => 'merge', 'Ci::BuildFinishedWorker' => 'default')
+ allow(completion_seconds_metric).to receive(:get)
end
- end
- context 'initializing queueing SLIs' do
- let(:initialize_sli_method) { :initialize_queueing_slis! }
+ it "initializes the execution and queueing SLIs with labels" do
+ expected_labels = [
+ {
+ worker: 'MergeWorker',
+ urgency: 'high',
+ feature_category: 'source_code_management',
+ external_dependencies: 'no',
+ queue: 'merge'
+ },
+ {
+ worker: 'Ci::BuildFinishedWorker',
+ urgency: 'high',
+ feature_category: 'continuous_integration',
+ external_dependencies: 'no',
+ queue: 'default'
+ }
+ ]
- context 'when sidekiq_queueing_application_slis FF is turned on' do
- it_behaves_like "initializes sidekiq SLIs for the workers in the current process"
- end
-
- context 'when sidekiq_queueing_application_slis FF is turned off' do
- before do
- stub_feature_flags(sidekiq_queueing_application_slis: false)
- end
+ expect(Gitlab::Metrics::SidekiqSlis)
+ .to receive(:initialize_execution_slis!).with(expected_labels)
+ expect(Gitlab::Metrics::SidekiqSlis)
+ .to receive(:initialize_queueing_slis!).with(expected_labels)
- it_behaves_like "not initializing sidekiq SLIs"
+ described_class.initialize_process_metrics
end
end
@@ -192,20 +166,26 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
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)
expect(sidekiq_mem_total_bytes).to receive(:set).with(labels_with_job_status, mem_total_bytes)
- expect(Gitlab::Metrics::SidekiqSlis).to receive(:record_execution_apdex).with(labels.slice(:worker,
- :feature_category,
- :urgency,
- :external_dependencies), monotonic_time_duration)
- expect(Gitlab::Metrics::SidekiqSlis).to receive(:record_execution_error).with(labels.slice(:worker,
- :feature_category,
- :urgency,
- :external_dependencies), false)
+ expect(Gitlab::Metrics::SidekiqSlis).to receive(:record_execution_apdex)
+ .with(labels.slice(:worker,
+ :feature_category,
+ :urgency,
+ :external_dependencies,
+ :queue), monotonic_time_duration)
+ expect(Gitlab::Metrics::SidekiqSlis).to receive(:record_execution_error)
+ .with(labels.slice(:worker,
+ :feature_category,
+ :urgency,
+ :external_dependencies,
+ :queue), false)
if queue_duration_for_job
- expect(Gitlab::Metrics::SidekiqSlis).to receive(:record_queueing_apdex).with(labels.slice(:worker,
- :feature_category,
- :urgency,
- :external_dependencies), queue_duration_for_job)
+ expect(Gitlab::Metrics::SidekiqSlis).to receive(:record_queueing_apdex)
+ .with(labels.slice(:worker,
+ :feature_category,
+ :urgency,
+ :external_dependencies,
+ :queue), queue_duration_for_job)
end
subject.call(worker, job, :test) { nil }
@@ -260,10 +240,12 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
it 'records sidekiq SLI error but does not record sidekiq SLI apdex' do
expect(failed_total_metric).to receive(:increment)
expect(Gitlab::Metrics::SidekiqSlis).not_to receive(:record_execution_apdex)
- expect(Gitlab::Metrics::SidekiqSlis).to receive(:record_execution_error).with(labels.slice(:worker,
- :feature_category,
- :urgency,
- :external_dependencies), true)
+ expect(Gitlab::Metrics::SidekiqSlis).to receive(:record_execution_error)
+ .with(labels.slice(:worker,
+ :feature_category,
+ :urgency,
+ :external_dependencies,
+ :queue), true)
expect { subject.call(worker, job, :test) { raise StandardError, "Failed" } }.to raise_error(StandardError, "Failed")
end
@@ -288,31 +270,6 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
subject.call(worker, job, :test) { nil }
end
end
-
- context 'when sidekiq_execution_application_slis FF is turned off' do
- before do
- stub_feature_flags(sidekiq_execution_application_slis: false)
- end
-
- it 'does not call record_execution_apdex nor record_execution_error' do
- expect(Gitlab::Metrics::SidekiqSlis).not_to receive(:record_execution_apdex)
- expect(Gitlab::Metrics::SidekiqSlis).not_to receive(:record_execution_error)
-
- subject.call(worker, job, :test) { nil }
- end
- end
-
- context 'when sidekiq_queueing_application_slis FF is turned off' do
- before do
- stub_feature_flags(sidekiq_queueing_application_slis: false)
- end
-
- it 'does not call record_queueing_apdex' do
- expect(Gitlab::Metrics::SidekiqSlis).not_to receive(:record_queueing_apdex)
-
- subject.call(worker, job, :test) { nil }
- end
- end
end
end
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
index 0abf688566a..112b90029b8 100644
--- a/spec/support/shared_contexts/navbar_structure_context.rb
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -112,6 +112,7 @@ RSpec.shared_context 'project navbar structure' do
_('CI/CD'),
_('Packages and registries'),
_('Monitor'),
+ (_('Analytics') if Gitlab.ee?),
s_('UsageQuota|Usage Quotas')
]
}