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