Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
		
							parent
							
								
									5bc7b9357e
								
							
						
					
					
						commit
						1b8bee4713
					
				|  | @ -1 +1 @@ | |||
| 2d62ba38be14d081d99e91d4c44e6371f9deddde | ||||
| 7d35879381a67a26332ecdd66392a2ad30bf64ca | ||||
|  |  | |||
|  | @ -1,31 +1,19 @@ | |||
| <script> | ||||
| import { GlTabs, GlTab } from '@gitlab/ui'; | ||||
| import { mergeUrlParams, updateHistory, getParameterValues } from '~/lib/utils/url_utility'; | ||||
| import { __, s__ } from '~/locale'; | ||||
| import { InternalEvents } from '~/tracking'; | ||||
| import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; | ||||
| import PipelineCharts from './pipeline_charts.vue'; | ||||
| import PipelineChartsNew from './pipeline_charts_new.vue'; | ||||
| import PipelinesDashboard from './pipelines_dashboard.vue'; | ||||
| import PipelinesDashboardClickhouse from './pipelines_dashboard_clickhouse.vue'; | ||||
| 
 | ||||
| const URL_PARAM_KEY = 'chart'; | ||||
| 
 | ||||
| export default { | ||||
|   components: { | ||||
|     GlTabs, | ||||
|     GlTab, | ||||
|     PipelineCharts, | ||||
|     PipelineChartsNew, | ||||
|     DeploymentFrequencyCharts: () => | ||||
|       import('ee_component/dora/components/deployment_frequency_charts.vue'), | ||||
|     LeadTimeCharts: () => import('ee_component/dora/components/lead_time_charts.vue'), | ||||
|     TimeToRestoreServiceCharts: () => | ||||
|       import('ee_component/dora/components/time_to_restore_service_charts.vue'), | ||||
|     ChangeFailureRateCharts: () => | ||||
|       import('ee_component/dora/components/change_failure_rate_charts.vue'), | ||||
|     ProjectQualitySummary: () => import('ee_component/project_quality_summary/app.vue'), | ||||
|   }, | ||||
|   pipelinesTabEvent: 'p_analytics_ci_cd_pipelines', | ||||
|   deploymentFrequencyTabEvent: 'p_analytics_ci_cd_deployment_frequency', | ||||
|   leadTimeTabEvent: 'p_analytics_ci_cd_lead_time', | ||||
|   timeToRestoreServiceTabEvent: 'visit_ci_cd_time_to_restore_service_tab', | ||||
|   changeFailureRateTabEvent: 'visit_ci_cd_failure_rate_tab', | ||||
|   mixins: [InternalEvents.mixin(), glFeatureFlagsMixin()], | ||||
|   inject: { | ||||
|     shouldRenderDoraCharts: { | ||||
|  | @ -38,50 +26,83 @@ export default { | |||
|     }, | ||||
|   }, | ||||
|   data() { | ||||
|     const tabs = [ | ||||
|       { | ||||
|         key: 'pipelines', | ||||
|         event: 'p_analytics_ci_cd_pipelines', | ||||
|         title: __('Pipelines'), | ||||
|         componentIs: this.glFeatures?.ciImprovedProjectPipelineAnalytics | ||||
|           ? PipelinesDashboardClickhouse | ||||
|           : PipelinesDashboard, | ||||
|         lazy: true, | ||||
|       }, | ||||
|     ]; | ||||
| 
 | ||||
|     if (this.shouldRenderDoraCharts) { | ||||
|       tabs.push( | ||||
|         { | ||||
|           key: 'deployment-frequency', | ||||
|           event: 'p_analytics_ci_cd_deployment_frequency', | ||||
|           title: __('Deployment frequency'), | ||||
|           componentIs: () => import('ee_component/dora/components/deployment_frequency_charts.vue'), | ||||
|           lazy: true, | ||||
|         }, | ||||
|         { | ||||
|           key: 'lead-time', | ||||
|           event: 'p_analytics_ci_cd_lead_time', | ||||
|           title: __('Lead time'), | ||||
|           componentIs: () => import('ee_component/dora/components/lead_time_charts.vue'), | ||||
|           lazy: true, | ||||
|         }, | ||||
|         { | ||||
|           key: 'time-to-restore-service', | ||||
|           event: 'visit_ci_cd_time_to_restore_service_tab', | ||||
|           title: s__('DORA4Metrics|Time to restore service'), | ||||
|           componentIs: () => | ||||
|             import('ee_component/dora/components/time_to_restore_service_charts.vue'), | ||||
|           lazy: true, | ||||
|         }, | ||||
|         { | ||||
|           key: 'change-failure-rate', | ||||
|           event: 'visit_ci_cd_failure_rate_tab', | ||||
|           title: s__('DORA4Metrics|Change failure rate'), | ||||
|           componentIs: () => import('ee_component/dora/components/change_failure_rate_charts.vue'), | ||||
|           lazy: true, | ||||
|         }, | ||||
|       ); | ||||
|     } | ||||
| 
 | ||||
|     if (this.shouldRenderQualitySummary) { | ||||
|       tabs.push({ | ||||
|         key: 'project-quality', | ||||
|         title: s__('QualitySummary|Project quality'), | ||||
|         componentIs: () => import('ee_component/project_quality_summary/app.vue'), | ||||
|         lazy: true, | ||||
|       }); | ||||
|     } | ||||
| 
 | ||||
|     return { | ||||
|       selectedTab: 0, | ||||
|       activeTabIndex: 0, | ||||
|       tabs, | ||||
|     }; | ||||
|   }, | ||||
|   computed: { | ||||
|     charts() { | ||||
|       const chartsToShow = ['pipelines']; | ||||
| 
 | ||||
|       if (this.shouldRenderDoraCharts) { | ||||
|         chartsToShow.push( | ||||
|           'deployment-frequency', | ||||
|           'lead-time', | ||||
|           'time-to-restore-service', | ||||
|           'change-failure-rate', | ||||
|         ); | ||||
|       } | ||||
| 
 | ||||
|       if (this.shouldRenderQualitySummary) { | ||||
|         chartsToShow.push('project-quality'); | ||||
|       } | ||||
| 
 | ||||
|       return chartsToShow; | ||||
|     }, | ||||
|     pipelineChartsComponent() { | ||||
|       if (this.glFeatures?.ciImprovedProjectPipelineAnalytics) { | ||||
|         return PipelineChartsNew; | ||||
|       } | ||||
|       return PipelineCharts; | ||||
|     }, | ||||
|   }, | ||||
|   created() { | ||||
|     this.selectTab(); | ||||
|     window.addEventListener('popstate', this.selectTab); | ||||
|     this.syncActiveTab(); | ||||
|     window.addEventListener('popstate', this.syncActiveTab); | ||||
|   }, | ||||
|   methods: { | ||||
|     selectTab() { | ||||
|       const [chart] = getParameterValues('chart') || this.charts; | ||||
|       const tab = this.charts.indexOf(chart); | ||||
|       this.selectedTab = tab >= 0 ? tab : 0; | ||||
|     syncActiveTab() { | ||||
|       const paramValue = getParameterValues(URL_PARAM_KEY)?.[0]; | ||||
|       const selectedIndex = this.tabs.map((tab) => tab.key).indexOf(paramValue); | ||||
|       this.activeTabIndex = selectedIndex >= 0 ? selectedIndex : 0; | ||||
|     }, | ||||
|     onTabChange(index) { | ||||
|       if (index !== this.selectedTab) { | ||||
|         this.selectedTab = index; | ||||
|         const path = mergeUrlParams({ chart: this.charts[index] }, window.location.pathname); | ||||
|     onTabInput(index) { | ||||
|       if (index !== this.activeTabIndex) { | ||||
|         const tab = this.tabs[index]; | ||||
|         const path = mergeUrlParams({ [URL_PARAM_KEY]: tab.key }, window.location.pathname); | ||||
| 
 | ||||
|         this.activeTabIndex = index; | ||||
|         tab.lazy = false; // mount the tab permanently after it is shown | ||||
|         updateHistory({ url: path, title: window.title }); | ||||
|       } | ||||
|     }, | ||||
|  | @ -90,48 +111,17 @@ export default { | |||
| </script> | ||||
| <template> | ||||
|   <div> | ||||
|     <gl-tabs v-if="charts.length > 1" :value="selectedTab" @input="onTabChange"> | ||||
|     <gl-tabs v-if="tabs.length > 1" :value="activeTabIndex" @input="onTabInput"> | ||||
|       <gl-tab | ||||
|         :title="__('Pipelines')" | ||||
|         data-testid="pipelines-tab" | ||||
|         @click="trackEvent($options.pipelinesTabEvent)" | ||||
|         v-for="tab in tabs" | ||||
|         :key="tab.key" | ||||
|         :title="tab.title" | ||||
|         :lazy="tab.lazy" | ||||
|         @click="tab.event && trackEvent(tab.event)" | ||||
|       > | ||||
|         <component :is="pipelineChartsComponent" /> | ||||
|       </gl-tab> | ||||
|       <template v-if="shouldRenderDoraCharts"> | ||||
|         <gl-tab | ||||
|           :title="__('Deployment frequency')" | ||||
|           data-testid="deployment-frequency-tab" | ||||
|           @click="trackEvent($options.deploymentFrequencyTabEvent)" | ||||
|         > | ||||
|           <deployment-frequency-charts /> | ||||
|         </gl-tab> | ||||
|         <gl-tab | ||||
|           :title="__('Lead time')" | ||||
|           data-testid="lead-time-tab" | ||||
|           @click="trackEvent($options.leadTimeTabEvent)" | ||||
|         > | ||||
|           <lead-time-charts /> | ||||
|         </gl-tab> | ||||
|         <gl-tab | ||||
|           :title="s__('DORA4Metrics|Time to restore service')" | ||||
|           data-testid="time-to-restore-service-tab" | ||||
|           @click="trackEvent($options.timeToRestoreServiceTabEvent)" | ||||
|         > | ||||
|           <time-to-restore-service-charts /> | ||||
|         </gl-tab> | ||||
|         <gl-tab | ||||
|           :title="s__('DORA4Metrics|Change failure rate')" | ||||
|           data-testid="change-failure-rate-tab" | ||||
|           @click="trackEvent($options.changeFailureRateTabEvent)" | ||||
|         > | ||||
|           <change-failure-rate-charts /> | ||||
|         </gl-tab> | ||||
|       </template> | ||||
|       <gl-tab v-if="shouldRenderQualitySummary" :title="s__('QualitySummary|Project quality')"> | ||||
|         <project-quality-summary /> | ||||
|         <component :is="tab.componentIs" /> | ||||
|       </gl-tab> | ||||
|     </gl-tabs> | ||||
|     <component :is="pipelineChartsComponent" v-else /> | ||||
|     <component :is="tabs[0].componentIs" v-else /> | ||||
|   </div> | ||||
| </template> | ||||
|  |  | |||
|  | @ -47,6 +47,7 @@ const defaultCountValues = { | |||
| }; | ||||
| 
 | ||||
| export default { | ||||
|   name: 'PipelinesDashboard', | ||||
|   components: { | ||||
|     GlAlert, | ||||
|     GlColumnChart, | ||||
|  | @ -16,6 +16,7 @@ import PipelineDurationChart from './pipeline_duration_chart.vue'; | |||
| import PipelineStatusChart from './pipeline_status_chart.vue'; | ||||
| 
 | ||||
| export default { | ||||
|   name: 'PipelinesDashboardClickhouse', | ||||
|   components: { | ||||
|     GlCollapsibleListbox, | ||||
|     GlFormGroup, | ||||
|  | @ -8,15 +8,6 @@ description: TODO | |||
| introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/9d6fe7bfdf9ff3f68ee73baa0e3d0aa7df13c351 | ||||
| milestone: '10.8' | ||||
| gitlab_schema: gitlab_ci | ||||
| desired_sharding_key: | ||||
|   project_id: | ||||
|     references: projects | ||||
|     backfill_via: | ||||
|       parent: | ||||
|         foreign_key: build_id | ||||
|         table: p_ci_builds | ||||
|         sharding_key: project_id | ||||
|         belongs_to: build | ||||
|         foreign_key_name: fk_89e29fa5ee_p | ||||
| desired_sharding_key_migration_job_name: BackfillCiBuildTraceChunksProjectId | ||||
| table_size: small | ||||
| sharding_key: | ||||
|   project_id: projects | ||||
|  |  | |||
|  | @ -0,0 +1,14 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| class AddCiBuildTraceChunksProjectIdNotNull < Gitlab::Database::Migration[2.2] | ||||
|   milestone '17.11' | ||||
|   disable_ddl_transaction! | ||||
| 
 | ||||
|   def up | ||||
|     add_not_null_constraint :ci_build_trace_chunks, :project_id | ||||
|   end | ||||
| 
 | ||||
|   def down | ||||
|     remove_not_null_constraint :ci_build_trace_chunks, :project_id | ||||
|   end | ||||
| end | ||||
|  | @ -0,0 +1 @@ | |||
| 739b48db5ebc3b2e03dff587bd1e4661764e06dc4025300a16a364271e7313e6 | ||||
|  | @ -10460,7 +10460,8 @@ CREATE TABLE ci_build_trace_chunks ( | |||
|     lock_version integer DEFAULT 0 NOT NULL, | ||||
|     build_id bigint NOT NULL, | ||||
|     partition_id bigint NOT NULL, | ||||
|     project_id bigint | ||||
|     project_id bigint, | ||||
|     CONSTRAINT check_b374316678 CHECK ((project_id IS NOT NULL)) | ||||
| ); | ||||
| 
 | ||||
| CREATE SEQUENCE ci_build_trace_chunks_id_seq | ||||
|  |  | |||
|  | @ -5650,7 +5650,11 @@ trigger-multi-project-pipeline: | |||
| Use `trigger:include` to declare that a job is a "trigger job" which starts a | ||||
| [child pipeline](../pipelines/downstream_pipelines.md#parent-child-pipelines). | ||||
| 
 | ||||
| Use `trigger:include:artifact` to trigger a [dynamic child pipeline](../pipelines/downstream_pipelines.md#dynamic-child-pipelines). | ||||
| Additionally, use: | ||||
| 
 | ||||
| - `trigger:include:artifact` to trigger a [dynamic child pipeline](../pipelines/downstream_pipelines.md#dynamic-child-pipelines). | ||||
| - `trigger:include:inputs` to set the [inputs](inputs.md) when the downstream pipeline configuration | ||||
|   uses [`spec:inputs`](#specinputs). | ||||
| 
 | ||||
| **Keyword type**: Job keyword. You can use it only as part of a job. | ||||
| 
 | ||||
|  | @ -5744,6 +5748,26 @@ successfully complete before starting. | |||
| - If the downstream pipeline has a failed job, but the job uses [`allow_failure: true`](#allow_failure), | ||||
|   the downstream pipeline is considered successful and the trigger job shows **success**. | ||||
| 
 | ||||
| #### `trigger:inputs` | ||||
| 
 | ||||
| {{< history >}} | ||||
| 
 | ||||
| - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/519963) in GitLab 17.11 [with a flag](../../administration/feature_flags.md) named `ci_inputs_for_pipelines`. Disabled by default. | ||||
| 
 | ||||
| {{</history >}} | ||||
| 
 | ||||
| Use `trigger:inputs` to set the [inputs](inputs.md) when the downstream pipeline configuration | ||||
| uses [`spec:inputs`](#specinputs). | ||||
| 
 | ||||
| **Example of `trigger:inputs`**: | ||||
| 
 | ||||
| ```yaml | ||||
| trigger: | ||||
|   - project: 'my-group/my-project' | ||||
|     inputs: | ||||
|       website: "My website" | ||||
| ``` | ||||
| 
 | ||||
| #### `trigger:forward` | ||||
| 
 | ||||
| {{< history >}} | ||||
|  |  | |||
|  | @ -1213,6 +1213,7 @@ ee: | |||
|             - :iterations_cadence | ||||
|       - protected_branches: | ||||
|         - :unprotect_access_levels | ||||
|         - :squash_option | ||||
|       - protected_environments: | ||||
|         - :deploy_access_levels | ||||
|       - :security_setting | ||||
|  | @ -1357,6 +1358,9 @@ ee: | |||
|       - :iid | ||||
|     vulnerability_read: | ||||
|       - :project_id | ||||
|     squash_option: | ||||
|       - :squash_option | ||||
|       - :project_id | ||||
|   excluded_attributes: | ||||
|     project: | ||||
|       - :vulnerability_hooks_integrations | ||||
|  |  | |||
|  | @ -42,7 +42,8 @@ module Gitlab | |||
|                       committer: 'MergeRequest::DiffCommitUser', | ||||
|                       merge_request_diff_commits: 'MergeRequestDiffCommit', | ||||
|                       work_item_type: 'WorkItems::Type', | ||||
|                       user_contributions: 'User' }.freeze | ||||
|                       user_contributions: 'User', | ||||
|                       squash_option: 'Projects::BranchRules::SquashOption' }.freeze | ||||
| 
 | ||||
|         BUILD_MODELS = %i[Ci::Build Ci::Bridge commit_status generic_commit_status].freeze | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,13 +10,8 @@ RSpec.describe 'Container registry (JavaScript fixtures)', feature_category: :co | |||
|   describe GraphQL::Query, type: :request do | ||||
|     let_it_be(:group) { create(:group, path: 'container-registry-group') } | ||||
|     let_it_be(:project) { create(:project, group: group, path: 'container-registry-project') } | ||||
|     let_it_be(:owner) { create(:user) } | ||||
|     let_it_be(:user) { create(:user) } | ||||
| 
 | ||||
|     before_all do | ||||
|       project.add_owner(owner) | ||||
|     end | ||||
| 
 | ||||
|     describe 'Protected container image tags' do | ||||
|       base_path = 'packages_and_registries/settings/project/graphql' | ||||
|       project_container_protection_tag_rules_query_path = | ||||
|  | @ -28,26 +23,35 @@ RSpec.describe 'Container registry (JavaScript fixtures)', feature_category: :co | |||
|       update_container_protection_tag_rule_mutation_path = | ||||
|         "#{base_path}/mutations/update_container_protection_tag_rule.mutation.graphql" | ||||
| 
 | ||||
|       let(:query) { get_graphql_query_as_string(project_container_protection_tag_rules_query_path) } | ||||
| 
 | ||||
|       let(:variables) do | ||||
|         { | ||||
|           projectPath: project.full_path, | ||||
|           first: 5 | ||||
|         } | ||||
|       end | ||||
| 
 | ||||
|       before do | ||||
|         stub_gitlab_api_client_to_support_gitlab_api(supported: true) | ||||
|       end | ||||
| 
 | ||||
|       context 'when user does not have access to the project' do | ||||
|         it "graphql/#{project_container_protection_tag_rules_query_path}.null_project.json" do | ||||
|           query = get_graphql_query_as_string(project_container_protection_tag_rules_query_path) | ||||
| 
 | ||||
|           post_graphql(query, current_user: user, variables: { projectPath: project.full_path, first: 5 }) | ||||
|           post_graphql(query, current_user: user, variables: variables) | ||||
| 
 | ||||
|           expect_graphql_errors_to_be_empty | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|       context 'when user has access to the project &' do | ||||
|         before_all do | ||||
|           project.add_owner(user) | ||||
|         end | ||||
| 
 | ||||
|         context 'with no tag protection rules' do | ||||
|           it "graphql/#{project_container_protection_tag_rules_query_path}.empty_rules.json" do | ||||
|             query = get_graphql_query_as_string(project_container_protection_tag_rules_query_path) | ||||
| 
 | ||||
|             post_graphql(query, current_user: owner, variables: { projectPath: project.full_path, first: 5 }) | ||||
|             post_graphql(query, current_user: user, variables: variables) | ||||
| 
 | ||||
|             expect_graphql_errors_to_be_empty | ||||
|           end | ||||
|  | @ -63,9 +67,7 @@ RSpec.describe 'Container registry (JavaScript fixtures)', feature_category: :co | |||
|           end | ||||
| 
 | ||||
|           it "graphql/#{project_container_protection_tag_rules_query_path}.json" do | ||||
|             query = get_graphql_query_as_string(project_container_protection_tag_rules_query_path) | ||||
| 
 | ||||
|             post_graphql(query, current_user: owner, variables: { projectPath: project.full_path, first: 5 }) | ||||
|             post_graphql(query, current_user: user, variables: variables) | ||||
| 
 | ||||
|             expect_graphql_errors_to_be_empty | ||||
|           end | ||||
|  | @ -81,129 +83,117 @@ RSpec.describe 'Container registry (JavaScript fixtures)', feature_category: :co | |||
|           end | ||||
| 
 | ||||
|           it "graphql/#{project_container_protection_tag_rules_query_path}.max_rules.json" do | ||||
|             query = get_graphql_query_as_string(project_container_protection_tag_rules_query_path) | ||||
| 
 | ||||
|             post_graphql(query, current_user: owner, variables: { projectPath: project.full_path, first: 5 }) | ||||
|             post_graphql(query, current_user: user, variables: variables) | ||||
| 
 | ||||
|             expect_graphql_errors_to_be_empty | ||||
|           end | ||||
|         end | ||||
| 
 | ||||
|         context 'when there are no errors deleting a rule' do | ||||
|           let_it_be(:container_protection_tag_rule) do | ||||
|             create(:container_registry_protection_tag_rule, | ||||
|               project: project, | ||||
|               minimum_access_level_for_push: Gitlab::Access::MAINTAINER, | ||||
|               minimum_access_level_for_delete: Gitlab::Access::OWNER | ||||
|             ) | ||||
|         describe 'deleting a rule' do | ||||
|           let(:mutation) { get_graphql_query_as_string(delete_container_protection_tag_rule_mutation_path) } | ||||
| 
 | ||||
|           context 'when there are no errors' do | ||||
|             let_it_be(:container_protection_tag_rule) do | ||||
|               create(:container_registry_protection_tag_rule, | ||||
|                 project: project, | ||||
|                 minimum_access_level_for_push: Gitlab::Access::MAINTAINER, | ||||
|                 minimum_access_level_for_delete: Gitlab::Access::OWNER | ||||
|               ) | ||||
|             end | ||||
| 
 | ||||
|             it "graphql/#{delete_container_protection_tag_rule_mutation_path}.json" do | ||||
|               post_graphql( | ||||
|                 mutation, | ||||
|                 current_user: user, | ||||
|                 variables: { | ||||
|                   input: { | ||||
|                     id: "gid://gitlab/ContainerRegistry::Protection::TagRule/#{container_protection_tag_rule.id}" | ||||
|                   } | ||||
|                 } | ||||
|               ) | ||||
| 
 | ||||
|               expect_graphql_errors_to_be_empty | ||||
|             end | ||||
|           end | ||||
| 
 | ||||
|           it "graphql/#{delete_container_protection_tag_rule_mutation_path}.json" do | ||||
|             mutation = get_graphql_query_as_string(delete_container_protection_tag_rule_mutation_path) | ||||
| 
 | ||||
|             post_graphql( | ||||
|               mutation, | ||||
|               current_user: owner, | ||||
|               variables: { | ||||
|                 input: { | ||||
|                   id: "gid://gitlab/ContainerRegistry::Protection::TagRule/#{container_protection_tag_rule.id}" | ||||
|           context 'when there are errors' do | ||||
|             it "graphql/#{delete_container_protection_tag_rule_mutation_path}.errors.json" do | ||||
|               post_graphql( | ||||
|                 mutation, | ||||
|                 current_user: user, | ||||
|                 variables: { | ||||
|                   input: { | ||||
|                     id: 'gid://gitlab/ContainerRegistry::Protection::TagRule/non-existent' | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|             ) | ||||
|               ) | ||||
| 
 | ||||
|             expect_graphql_errors_to_be_empty | ||||
|               expect_graphql_errors_to_include( | ||||
|                 "The resource that you are attempting to access does not exist or " \ | ||||
|                   "you don't have permission to perform this action" | ||||
|               ) | ||||
|             end | ||||
|           end | ||||
|         end | ||||
| 
 | ||||
|         context 'when there are errors deleting a rule' do | ||||
|           it "graphql/#{delete_container_protection_tag_rule_mutation_path}.errors.json" do | ||||
|             mutation = get_graphql_query_as_string(delete_container_protection_tag_rule_mutation_path) | ||||
|         describe 'creating a rule' do | ||||
|           let(:mutation) { get_graphql_query_as_string(create_container_protection_tag_rule_mutation_path) } | ||||
| 
 | ||||
|             post_graphql( | ||||
|               mutation, | ||||
|               current_user: owner, | ||||
|               variables: { | ||||
|                 input: { | ||||
|                   id: 'gid://gitlab/ContainerRegistry::Protection::TagRule/non-existent' | ||||
|                 } | ||||
|           let(:variables) do | ||||
|             { | ||||
|               input: { | ||||
|                 projectPath: project.full_path, | ||||
|                 tagNamePattern: 'v.*', | ||||
|                 minimumAccessLevelForPush: 'MAINTAINER', | ||||
|                 minimumAccessLevelForDelete: 'OWNER' | ||||
|               } | ||||
|             ) | ||||
| 
 | ||||
|             expect_graphql_errors_to_include( | ||||
|               "The resource that you are attempting to access does not exist or " \ | ||||
|                 "you don't have permission to perform this action" | ||||
|             ) | ||||
|           end | ||||
|         end | ||||
| 
 | ||||
|         context 'when there are no errors creating a rule' do | ||||
|           it "graphql/#{create_container_protection_tag_rule_mutation_path}.json" do | ||||
|             mutation = get_graphql_query_as_string(create_container_protection_tag_rule_mutation_path) | ||||
| 
 | ||||
|             post_graphql( | ||||
|               mutation, | ||||
|               current_user: owner, | ||||
|               variables: { | ||||
|                 input: { | ||||
|                   projectPath: project.full_path, | ||||
|                   tagNamePattern: 'v.*', | ||||
|                   minimumAccessLevelForPush: 'MAINTAINER', | ||||
|                   minimumAccessLevelForDelete: 'OWNER' | ||||
|                 } | ||||
|               } | ||||
|             ) | ||||
| 
 | ||||
|             expect_graphql_errors_to_be_empty | ||||
|           end | ||||
|         end | ||||
| 
 | ||||
|         context 'when there are field errors creating a rule' do | ||||
|           it "graphql/#{create_container_protection_tag_rule_mutation_path}.server_errors.json" do | ||||
|             mutation = get_graphql_query_as_string(create_container_protection_tag_rule_mutation_path) | ||||
| 
 | ||||
|             post_graphql( | ||||
|               mutation, | ||||
|               current_user: owner, | ||||
|               variables: { | ||||
|                 input: { | ||||
|                   project_path: project.full_path, | ||||
|                   tagNamePattern: '', | ||||
|                   minimumAccessLevelForPush: 'MAINTAINER', | ||||
|                   minimumAccessLevelForDelete: 'OWNER' | ||||
|                 } | ||||
|               } | ||||
|             ) | ||||
| 
 | ||||
|             expect_graphql_errors_to_include( | ||||
|               "tagNamePattern can't be blank" | ||||
|             ) | ||||
|           end | ||||
|         end | ||||
| 
 | ||||
|         context 'when there are errors creating a rule' do | ||||
|           before do | ||||
|             create(:container_registry_protection_tag_rule, project: project, | ||||
|               tag_name_pattern: "v.*") | ||||
|             } | ||||
|           end | ||||
| 
 | ||||
|           it "graphql/#{create_container_protection_tag_rule_mutation_path}.errors.json" do | ||||
|             mutation = get_graphql_query_as_string(create_container_protection_tag_rule_mutation_path) | ||||
|           context 'when there are no errors' do | ||||
|             it "graphql/#{create_container_protection_tag_rule_mutation_path}.json" do | ||||
|               post_graphql( | ||||
|                 mutation, | ||||
|                 current_user: user, | ||||
|                 variables: variables | ||||
|               ) | ||||
| 
 | ||||
|             post_graphql( | ||||
|               mutation, | ||||
|               current_user: owner, | ||||
|               variables: { | ||||
|                 input: { | ||||
|                   project_path: project.full_path, | ||||
|                   tagNamePattern: 'v.*', | ||||
|                   minimumAccessLevelForPush: 'MAINTAINER', | ||||
|                   minimumAccessLevelForDelete: 'OWNER' | ||||
|                 } | ||||
|               } | ||||
|             ) | ||||
|               expect_graphql_errors_to_be_empty | ||||
|             end | ||||
|           end | ||||
| 
 | ||||
|             expect(graphql_data_at('createContainerProtectionTagRule', 'errors')) | ||||
|               .to include('Tag name pattern has already been taken') | ||||
|           context 'when there are field errors' do | ||||
|             it "graphql/#{create_container_protection_tag_rule_mutation_path}.server_errors.json" do | ||||
|               variables[:input][:tagNamePattern] = '' | ||||
| 
 | ||||
|               post_graphql( | ||||
|                 mutation, | ||||
|                 current_user: user, | ||||
|                 variables: variables | ||||
|               ) | ||||
| 
 | ||||
|               expect_graphql_errors_to_include( | ||||
|                 "tagNamePattern can't be blank" | ||||
|               ) | ||||
|             end | ||||
|           end | ||||
| 
 | ||||
|           context 'when there are errors' do | ||||
|             before do | ||||
|               create(:container_registry_protection_tag_rule, project: project, | ||||
|                 tag_name_pattern: "v.*") | ||||
|             end | ||||
| 
 | ||||
|             it "graphql/#{create_container_protection_tag_rule_mutation_path}.errors.json" do | ||||
|               post_graphql( | ||||
|                 mutation, | ||||
|                 current_user: user, | ||||
|                 variables: variables | ||||
|               ) | ||||
| 
 | ||||
|               expect(graphql_data_at('createContainerProtectionTagRule', 'errors')) | ||||
|                 .to include('Tag name pattern has already been taken') | ||||
|             end | ||||
|           end | ||||
|         end | ||||
| 
 | ||||
|  | @ -216,21 +206,26 @@ RSpec.describe 'Container registry (JavaScript fixtures)', feature_category: :co | |||
|             ) | ||||
|           end | ||||
| 
 | ||||
|           let(:mutation) { get_graphql_query_as_string(update_container_protection_tag_rule_mutation_path) } | ||||
|           let(:variables) do | ||||
|             { | ||||
|               input: { | ||||
|                 id: "gid://gitlab/ContainerRegistry::Protection::TagRule/#{container_protection_tag_rule.id}", | ||||
|                 tagNamePattern: 'v.*', | ||||
|                 minimumAccessLevelForPush: 'MAINTAINER', | ||||
|                 minimumAccessLevelForDelete: 'OWNER' | ||||
|               } | ||||
|             } | ||||
|           end | ||||
| 
 | ||||
|           context 'when there are no errors' do | ||||
|             it "graphql/#{update_container_protection_tag_rule_mutation_path}.json" do | ||||
|               mutation = get_graphql_query_as_string(update_container_protection_tag_rule_mutation_path) | ||||
| 
 | ||||
|               post_graphql( | ||||
|                 mutation, | ||||
|                 current_user: owner, | ||||
|                 variables: { | ||||
|                   input: { | ||||
|                     id: "gid://gitlab/ContainerRegistry::Protection::TagRule/#{container_protection_tag_rule.id}", | ||||
|                     tagNamePattern: 'v.*', | ||||
|                     minimumAccessLevelForPush: 'ADMIN', | ||||
|                     minimumAccessLevelForDelete: 'ADMIN' | ||||
|                   } | ||||
|                 } | ||||
|                 current_user: user, | ||||
|                 variables: variables | ||||
|               ) | ||||
| 
 | ||||
|               expect_graphql_errors_to_be_empty | ||||
|  | @ -239,19 +234,12 @@ RSpec.describe 'Container registry (JavaScript fixtures)', feature_category: :co | |||
| 
 | ||||
|           context 'when there are field errors' do | ||||
|             it "graphql/#{update_container_protection_tag_rule_mutation_path}.server_errors.json" do | ||||
|               mutation = get_graphql_query_as_string(update_container_protection_tag_rule_mutation_path) | ||||
|               variables[:input][:tagNamePattern] = '' | ||||
| 
 | ||||
|               post_graphql( | ||||
|                 mutation, | ||||
|                 current_user: owner, | ||||
|                 variables: { | ||||
|                   input: { | ||||
|                     id: "gid://gitlab/ContainerRegistry::Protection::TagRule/#{container_protection_tag_rule.id}", | ||||
|                     tagNamePattern: '', | ||||
|                     minimumAccessLevelForPush: 'MAINTAINER', | ||||
|                     minimumAccessLevelForDelete: 'OWNER' | ||||
|                   } | ||||
|                 } | ||||
|                 current_user: user, | ||||
|                 variables: variables | ||||
|               ) | ||||
| 
 | ||||
|               expect_graphql_errors_to_include( | ||||
|  | @ -271,15 +259,8 @@ RSpec.describe 'Container registry (JavaScript fixtures)', feature_category: :co | |||
| 
 | ||||
|               post_graphql( | ||||
|                 mutation, | ||||
|                 current_user: owner, | ||||
|                 variables: { | ||||
|                   input: { | ||||
|                     id: "gid://gitlab/ContainerRegistry::Protection::TagRule/#{container_protection_tag_rule.id}", | ||||
|                     tagNamePattern: 'v.*', | ||||
|                     minimumAccessLevelForPush: 'MAINTAINER', | ||||
|                     minimumAccessLevelForDelete: 'OWNER' | ||||
|                   } | ||||
|                 } | ||||
|                 current_user: user, | ||||
|                 variables: variables | ||||
|               ) | ||||
| 
 | ||||
|               expect(graphql_data_at('updateContainerProtectionTagRule', 'errors')) | ||||
|  |  | |||
|  | @ -1,261 +1,52 @@ | |||
| import { GlTabs, GlTab } from '@gitlab/ui'; | ||||
| import { merge } from 'lodash'; | ||||
| import { nextTick } from 'vue'; | ||||
| import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; | ||||
| import setWindowLocation from 'helpers/set_window_location_helper'; | ||||
| import { TEST_HOST } from 'helpers/test_constants'; | ||||
| import { mergeUrlParams, updateHistory, getParameterValues } from '~/lib/utils/url_utility'; | ||||
| import Component from '~/projects/pipelines/charts/components/app.vue'; | ||||
| import PipelineCharts from '~/projects/pipelines/charts/components/pipeline_charts.vue'; | ||||
| import PipelineChartsNew from '~/projects/pipelines/charts/components/pipeline_charts_new.vue'; | ||||
| import API from '~/api'; | ||||
| import { mockTracking } from 'helpers/tracking_helper'; | ||||
| import { SNOWPLOW_DATA_SOURCE, SNOWPLOW_SCHEMA } from '~/projects/pipelines/charts/constants'; | ||||
| import { GlTabs } from '@gitlab/ui'; | ||||
| import { shallowMount } from '@vue/test-utils'; | ||||
| 
 | ||||
| jest.mock('~/lib/utils/url_utility'); | ||||
| import App from '~/projects/pipelines/charts/components/app.vue'; | ||||
| 
 | ||||
| const DeploymentFrequencyChartsStub = { name: 'DeploymentFrequencyCharts', render: () => {} }; | ||||
| const LeadTimeChartsStub = { name: 'LeadTimeCharts', render: () => {} }; | ||||
| const TimeToRestoreServiceChartsStub = { name: 'TimeToRestoreServiceCharts', render: () => {} }; | ||||
| const ChangeFailureRateChartsStub = { name: 'ChangeFailureRateCharts', render: () => {} }; | ||||
| const ProjectQualitySummaryStub = { name: 'ProjectQualitySummary', render: () => {} }; | ||||
| import PipelinesDashboard from '~/projects/pipelines/charts/components/pipelines_dashboard.vue'; | ||||
| import PipelinesDashboardClickhouse from '~/projects/pipelines/charts/components/pipelines_dashboard_clickhouse.vue'; | ||||
| 
 | ||||
| describe('ProjectsPipelinesChartsApp', () => { | ||||
|   let wrapper; | ||||
| 
 | ||||
|   function createComponent(mountOptions = {}) { | ||||
|     wrapper = shallowMountExtended( | ||||
|       Component, | ||||
|       merge( | ||||
|         {}, | ||||
|         { | ||||
|           provide: { | ||||
|             shouldRenderDoraCharts: true, | ||||
|             shouldRenderQualitySummary: true, | ||||
|           }, | ||||
|           stubs: { | ||||
|             DeploymentFrequencyCharts: DeploymentFrequencyChartsStub, | ||||
|             LeadTimeCharts: LeadTimeChartsStub, | ||||
|             TimeToRestoreServiceCharts: TimeToRestoreServiceChartsStub, | ||||
|             ChangeFailureRateCharts: ChangeFailureRateChartsStub, | ||||
|             ProjectQualitySummary: ProjectQualitySummaryStub, | ||||
|           }, | ||||
|         }, | ||||
|         mountOptions, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|   const createWrapper = ({ provide, ...options } = {}) => { | ||||
|     wrapper = shallowMount(App, { | ||||
|       provide: { | ||||
|         ...provide, | ||||
|       }, | ||||
|       ...options, | ||||
|     }); | ||||
|   }; | ||||
| 
 | ||||
|   const findGlTabs = () => wrapper.findComponent(GlTabs); | ||||
|   const findAllGlTabs = () => wrapper.findAllComponents(GlTab); | ||||
|   const findGlTabAtIndex = (index) => findAllGlTabs().at(index); | ||||
|   const findLeadTimeCharts = () => wrapper.findComponent(LeadTimeChartsStub); | ||||
|   const findTimeToRestoreServiceCharts = () => | ||||
|     wrapper.findComponent(TimeToRestoreServiceChartsStub); | ||||
|   const findChangeFailureRateCharts = () => wrapper.findComponent(ChangeFailureRateChartsStub); | ||||
|   const findDeploymentFrequencyCharts = () => wrapper.findComponent(DeploymentFrequencyChartsStub); | ||||
|   const findPipelineCharts = () => wrapper.findComponent(PipelineCharts); | ||||
|   const findPipelineChartsNew = () => wrapper.findComponent(PipelineChartsNew); | ||||
|   const findProjectQualitySummary = () => wrapper.findComponent(ProjectQualitySummaryStub); | ||||
| 
 | ||||
|   describe('when all charts are available', () => { | ||||
|   const findPipelinesDashboard = () => wrapper.findComponent(PipelinesDashboard); | ||||
|   const findPipelinesDashboardClickhouse = () => | ||||
|     wrapper.findComponent(PipelinesDashboardClickhouse); | ||||
| 
 | ||||
|   describe('when showing only pipelines dashboard', () => { | ||||
|     beforeEach(() => { | ||||
|       createComponent(); | ||||
|     }); | ||||
| 
 | ||||
|     describe.each` | ||||
|       title                        | finderFn                          | index | ||||
|       ${'Pipelines'}               | ${findPipelineCharts}             | ${0} | ||||
|       ${'Deployment frequency'}    | ${findDeploymentFrequencyCharts}  | ${1} | ||||
|       ${'Lead time'}               | ${findLeadTimeCharts}             | ${2} | ||||
|       ${'Time to restore service'} | ${findTimeToRestoreServiceCharts} | ${3} | ||||
|       ${'Change failure rate'}     | ${findChangeFailureRateCharts}    | ${4} | ||||
|       ${'Project quality'}         | ${findProjectQualitySummary}      | ${5} | ||||
|     `('Tabs', ({ title, finderFn, index }) => {
 | ||||
|       it(`renders tab with a title ${title} at index ${index}`, () => { | ||||
|         expect(findGlTabAtIndex(index).attributes('title')).toBe(title); | ||||
|       }); | ||||
| 
 | ||||
|       it(`renders the ${title} chart`, () => { | ||||
|         expect(finderFn().exists()).toBe(true); | ||||
|       }); | ||||
| 
 | ||||
|       it(`updates the current tab and url when the ${title} tab is clicked`, async () => { | ||||
|         let chartsPath; | ||||
|         const tabName = title.toLowerCase().replace(/\s/g, '-'); | ||||
| 
 | ||||
|         setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`); | ||||
| 
 | ||||
|         mergeUrlParams.mockImplementation(({ chart }, path) => { | ||||
|           expect(chart).toBe(tabName); | ||||
|           expect(path).toBe(window.location.pathname); | ||||
|           chartsPath = `${path}?chart=${chart}`; | ||||
|           return chartsPath; | ||||
|         }); | ||||
| 
 | ||||
|         updateHistory.mockImplementation(({ url }) => { | ||||
|           expect(url).toBe(chartsPath); | ||||
|         }); | ||||
|         const tabs = findGlTabs(); | ||||
| 
 | ||||
|         expect(tabs.attributes('value')).toBe('0'); | ||||
| 
 | ||||
|         tabs.vm.$emit('input', index); | ||||
| 
 | ||||
|         await nextTick(); | ||||
| 
 | ||||
|         expect(tabs.attributes('value')).toBe(index.toString()); | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     it('should not try to push history if the tab does not change', async () => { | ||||
|       setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts`); | ||||
| 
 | ||||
|       mergeUrlParams.mockImplementation(({ chart }, path) => `${path}?chart=${chart}`); | ||||
| 
 | ||||
|       const tabs = findGlTabs(); | ||||
| 
 | ||||
|       expect(tabs.attributes('value')).toBe('0'); | ||||
| 
 | ||||
|       tabs.vm.$emit('input', 0); | ||||
| 
 | ||||
|       await nextTick(); | ||||
| 
 | ||||
|       expect(updateHistory).not.toHaveBeenCalled(); | ||||
|     }); | ||||
| 
 | ||||
|     describe('event tracking', () => { | ||||
|       describe('Internal Events RedisHLL events', () => { | ||||
|         it.each` | ||||
|           testId                           | event | ||||
|           ${'pipelines-tab'}               | ${'p_analytics_ci_cd_pipelines'} | ||||
|           ${'deployment-frequency-tab'}    | ${'p_analytics_ci_cd_deployment_frequency'} | ||||
|           ${'lead-time-tab'}               | ${'p_analytics_ci_cd_lead_time'} | ||||
|           ${'time-to-restore-service-tab'} | ${'visit_ci_cd_time_to_restore_service_tab'} | ||||
|           ${'change-failure-rate-tab'}     | ${'visit_ci_cd_failure_rate_tab'} | ||||
|         `('tracks the $event event when clicked', ({ testId, event }) => {
 | ||||
|           const trackApiSpy = jest.spyOn(API, 'trackInternalEvent'); | ||||
| 
 | ||||
|           expect(trackApiSpy).not.toHaveBeenCalled(); | ||||
| 
 | ||||
|           wrapper.findByTestId(testId).vm.$emit('click'); | ||||
| 
 | ||||
|           expect(trackApiSpy).toHaveBeenCalledWith(event, {}); | ||||
|         }); | ||||
|       }); | ||||
| 
 | ||||
|       describe('Snowplow events', () => { | ||||
|         it.each` | ||||
|           testId                        | event | ||||
|           ${'pipelines-tab'}            | ${'p_analytics_ci_cd_pipelines'} | ||||
|           ${'deployment-frequency-tab'} | ${'p_analytics_ci_cd_deployment_frequency'} | ||||
|           ${'lead-time-tab'}            | ${'p_analytics_ci_cd_lead_time'} | ||||
|         `('tracks the $event event when clicked', ({ testId, event }) => {
 | ||||
|           const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); | ||||
| 
 | ||||
|           wrapper.findByTestId(testId).vm.$emit('click'); | ||||
| 
 | ||||
|           expect(trackingSpy).toHaveBeenCalledWith(undefined, event, { | ||||
|             context: { | ||||
|               schema: SNOWPLOW_SCHEMA, | ||||
|               data: { | ||||
|                 event_name: event, | ||||
|                 data_source: SNOWPLOW_DATA_SOURCE, | ||||
|               }, | ||||
|             }, | ||||
|           }); | ||||
|         }); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('when provided with a query param', () => { | ||||
|     it.each` | ||||
|       chart                        | tab | ||||
|       ${'change-failure-rate'}     | ${'4'} | ||||
|       ${'time-to-restore-service'} | ${'3'} | ||||
|       ${'lead-time'}               | ${'2'} | ||||
|       ${'deployment-frequency'}    | ${'1'} | ||||
|       ${'pipelines'}               | ${'0'} | ||||
|       ${'fake'}                    | ${'0'} | ||||
|       ${''}                        | ${'0'} | ||||
|     `('shows the correct tab for URL parameter "$chart"', ({ chart, tab }) => {
 | ||||
|       setWindowLocation(`${TEST_HOST}/gitlab-org/gitlab-test/-/pipelines/charts?chart=${chart}`); | ||||
|       getParameterValues.mockImplementation((name) => { | ||||
|         expect(name).toBe('chart'); | ||||
|         return chart ? [chart] : []; | ||||
|       }); | ||||
|       createComponent(); | ||||
|       expect(findGlTabs().attributes('value')).toBe(tab); | ||||
|     }); | ||||
| 
 | ||||
|     it('should set the tab when the back button is clicked', async () => { | ||||
|       let popstateHandler; | ||||
| 
 | ||||
|       window.addEventListener = jest.fn(); | ||||
| 
 | ||||
|       window.addEventListener.mockImplementation((event, handler) => { | ||||
|         if (event === 'popstate') { | ||||
|           popstateHandler = handler; | ||||
|         } | ||||
|       }); | ||||
| 
 | ||||
|       getParameterValues.mockImplementation((name) => { | ||||
|         expect(name).toBe('chart'); | ||||
|         return []; | ||||
|       }); | ||||
| 
 | ||||
|       createComponent(); | ||||
| 
 | ||||
|       expect(findGlTabs().attributes('value')).toBe('0'); | ||||
| 
 | ||||
|       getParameterValues.mockImplementationOnce((name) => { | ||||
|         expect(name).toBe('chart'); | ||||
|         return ['deployment-frequency']; | ||||
|       }); | ||||
| 
 | ||||
|       popstateHandler(); | ||||
| 
 | ||||
|       await nextTick(); | ||||
| 
 | ||||
|       expect(findGlTabs().attributes('value')).toBe('1'); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('when the dora charts are not available and project quality summary is not available', () => { | ||||
|     beforeEach(() => { | ||||
|       createComponent({ | ||||
|         provide: { shouldRenderDoraCharts: false, shouldRenderQualitySummary: false }, | ||||
|       }); | ||||
|       createWrapper(); | ||||
|     }); | ||||
| 
 | ||||
|     it('does not render tabs', () => { | ||||
|       // tabs are only shown in EE
 | ||||
|       expect(findGlTabs().exists()).toBe(false); | ||||
|     }); | ||||
| 
 | ||||
|     it('renders the pipeline charts', () => { | ||||
|       expect(findPipelineCharts().exists()).toBe(true); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('when the project quality summary is not available', () => { | ||||
|     beforeEach(() => { | ||||
|       createComponent({ provide: { shouldRenderQualitySummary: false } }); | ||||
|     }); | ||||
| 
 | ||||
|     it('does not render the tab', () => { | ||||
|       expect(findProjectQualitySummary().exists()).toBe(false); | ||||
|     it('shows pipelines dashboard', () => { | ||||
|       expect(wrapper.findComponent(PipelinesDashboard).exists()).toBe(true); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('ci_improved_project_pipeline_analytics feature flag', () => { | ||||
|     describe.each` | ||||
|       status   | finderFn | ||||
|       ${false} | ${findPipelineCharts} | ||||
|       ${true}  | ${findPipelineChartsNew} | ||||
|       ${false} | ${findPipelinesDashboard} | ||||
|       ${true}  | ${findPipelinesDashboardClickhouse} | ||||
|     `('when flag is $status', ({ status, finderFn }) => {
 | ||||
|       it('renders component', () => { | ||||
|         createComponent({ | ||||
|         createWrapper({ | ||||
|           provide: { | ||||
|             glFeatures: { | ||||
|               ciImprovedProjectPipelineAnalytics: status, | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import Vue from 'vue'; | |||
| import VueApollo from 'vue-apollo'; | ||||
| import createMockApollo from 'helpers/mock_apollo_helper'; | ||||
| import waitForPromises from 'helpers/wait_for_promises'; | ||||
| import PipelineChartsNew from '~/projects/pipelines/charts/components/pipeline_charts_new.vue'; | ||||
| import PipelinesDashboardClickhouse from '~/projects/pipelines/charts/components/pipelines_dashboard_clickhouse.vue'; | ||||
| import StatisticsList from '~/projects/pipelines/charts/components/statistics_list.vue'; | ||||
| import PipelineDurationChart from '~/projects/pipelines/charts/components/pipeline_duration_chart.vue'; | ||||
| import PipelineStatusChart from '~/projects/pipelines/charts/components/pipeline_status_chart.vue'; | ||||
|  | @ -19,7 +19,7 @@ jest.mock('~/alert'); | |||
| 
 | ||||
| const projectPath = 'gitlab-org/gitlab'; | ||||
| 
 | ||||
| describe('~/projects/pipelines/charts/components/pipeline_charts_new.vue', () => { | ||||
| describe('PipelinesDashboardClickhouse', () => { | ||||
|   useFakeDate('2022-02-15T08:30'); // a date with a time
 | ||||
| 
 | ||||
|   let wrapper; | ||||
|  | @ -32,7 +32,7 @@ describe('~/projects/pipelines/charts/components/pipeline_charts_new.vue', () => | |||
|   const findAllSingleStats = () => wrapper.findAllComponents(GlSingleStat); | ||||
| 
 | ||||
|   const createComponent = ({ mountFn = shallowMount } = {}) => { | ||||
|     wrapper = mountFn(PipelineChartsNew, { | ||||
|     wrapper = mountFn(PipelinesDashboardClickhouse, { | ||||
|       provide: { | ||||
|         projectPath, | ||||
|       }, | ||||
|  | @ -4,7 +4,7 @@ import Vue from 'vue'; | |||
| import VueApollo from 'vue-apollo'; | ||||
| import createMockApollo from 'helpers/mock_apollo_helper'; | ||||
| import waitForPromises from 'helpers/wait_for_promises'; | ||||
| import PipelineCharts from '~/projects/pipelines/charts/components/pipeline_charts.vue'; | ||||
| import PipelinesDashboard from '~/projects/pipelines/charts/components/pipelines_dashboard.vue'; | ||||
| import StatisticsList from '~/projects/pipelines/charts/components/statistics_list.vue'; | ||||
| import getPipelineCountByStatus from '~/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql'; | ||||
| import getProjectPipelineStatistics from '~/projects/pipelines/charts/graphql/queries/get_project_pipeline_statistics.query.graphql'; | ||||
|  | @ -14,7 +14,7 @@ import { mockPipelineCount, mockPipelineStatistics } from '../mock_data'; | |||
| const projectPath = 'gitlab-org/gitlab'; | ||||
| Vue.use(VueApollo); | ||||
| 
 | ||||
| describe('~/projects/pipelines/charts/components/pipeline_charts.vue', () => { | ||||
| describe('PipelinesDashboard', () => { | ||||
|   let wrapper; | ||||
| 
 | ||||
|   function createMockApolloProvider() { | ||||
|  | @ -27,7 +27,7 @@ describe('~/projects/pipelines/charts/components/pipeline_charts.vue', () => { | |||
|   } | ||||
| 
 | ||||
|   beforeEach(async () => { | ||||
|     wrapper = shallowMount(PipelineCharts, { | ||||
|     wrapper = shallowMount(PipelinesDashboard, { | ||||
|       provide: { | ||||
|         projectPath, | ||||
|       }, | ||||
|  | @ -61,6 +61,7 @@ RSpec.describe 'new tables missing sharding_key', feature_category: :cell do | |||
|       'ci_pipeline_messages.project_id', | ||||
|       # LFK already present on ci_pipeline_schedules and cascade delete all ci resources. | ||||
|       'ci_pipeline_schedule_variables.project_id', | ||||
|       'ci_build_trace_chunks.project_id', # LFK already present on p_ci_builds and cascade delete all ci resources | ||||
|       'p_ci_job_annotations.project_id', # LFK already present on p_ci_builds and cascade delete all ci resources | ||||
|       'ci_builds_runner_session.project_id', # LFK already present on p_ci_builds and cascade delete all ci resources | ||||
|       'p_ci_pipelines_config.project_id', # LFK already present on p_ci_pipelines and cascade delete all ci resources | ||||
|  |  | |||
|  | @ -569,6 +569,8 @@ create_access_levels: | |||
| - protected_tag | ||||
| - group | ||||
| - deploy_key | ||||
| squash_option: | ||||
| - protected_branch | ||||
| container_repositories: | ||||
| - project | ||||
| - name | ||||
|  |  | |||
|  | @ -47,6 +47,7 @@ RSpec.describe 'Test coverage of the Project Import', feature_category: :importe | |||
|       project.ci_pipelines.notes.events | ||||
|       project.ci_pipelines.notes.events.push_event_payload | ||||
|       project.protected_branches.unprotect_access_levels | ||||
|       project.protected_branches.squash_option | ||||
|       project.boards.lists.label.priorities | ||||
|       project.service_desk_setting | ||||
|       project.security_setting | ||||
|  |  | |||
|  | @ -1129,3 +1129,6 @@ Vulnerabilities::Identifier: | |||
|   - url | ||||
| Vulnerabilities::Read: | ||||
|   - project_id | ||||
| Projects::BranchRules::SquashOption: | ||||
|   - squash_option | ||||
|   - project_id | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue