@@ -74,7 +83,7 @@ export default {
-
+
{
this.isLoading = false;
- eventHub.$emit('updateTable');
+ this.$emit('refresh-pipeline-table');
})
.catch(() => {
this.isLoading = false;
diff --git a/app/assets/javascripts/ci/pipelines_page/pipelines.vue b/app/assets/javascripts/ci/pipelines_page/pipelines.vue
index 87ee5463bb0..f4105040f31 100644
--- a/app/assets/javascripts/ci/pipelines_page/pipelines.vue
+++ b/app/assets/javascripts/ci/pipelines_page/pipelines.vue
@@ -13,7 +13,7 @@ import {
RAW_TEXT_WARNING,
TRACKING_CATEGORIES,
} from '~/ci/constants';
-import PipelinesTableComponent from '~/ci/common/pipelines_table.vue';
+import PipelinesTable from '~/ci/common/pipelines_table.vue';
import PipelinesMixin from '~/ci/pipeline_details/mixins/pipelines_mixin';
import { validateParams } from '~/ci/pipeline_details/utils';
import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
@@ -37,7 +37,7 @@ export default {
NavigationTabs,
NavigationControls,
PipelinesFilteredSearch,
- PipelinesTableComponent,
+ PipelinesTable,
TablePagination,
},
mixins: [PipelinesMixin, Tracking.mixin()],
@@ -431,12 +431,15 @@ export default {
/>
diff --git a/app/assets/javascripts/commit/pipelines/legacy_pipelines_table_wrapper.vue b/app/assets/javascripts/commit/pipelines/legacy_pipelines_table_wrapper.vue
index 5e84dcbe48e..5586032233c 100644
--- a/app/assets/javascripts/commit/pipelines/legacy_pipelines_table_wrapper.vue
+++ b/app/assets/javascripts/commit/pipelines/legacy_pipelines_table_wrapper.vue
@@ -2,7 +2,7 @@
import { GlButton, GlEmptyState, GlLoadingIcon, GlModal, GlLink, GlSprintf } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
import { getParameterByName } from '~/lib/utils/url_utility';
-import PipelinesTableComponent from '~/ci/common/pipelines_table.vue';
+import PipelinesTable from '~/ci/common/pipelines_table.vue';
import { PipelineKeyOptions } from '~/ci/constants';
import eventHub from '~/ci/event_hub';
import PipelinesMixin from '~/ci/pipeline_details/mixins/pipelines_mixin';
@@ -21,7 +21,7 @@ export default {
GlLoadingIcon,
GlModal,
GlSprintf,
- PipelinesTableComponent,
+ PipelinesTable,
TablePagination,
},
mixins: [PipelinesMixin, glFeatureFlagMixin()],
@@ -279,11 +279,14 @@ export default {
{{ $options.i18n.runPipelineText }}
-
@@ -296,7 +299,7 @@ export default {
-
+
Pipelines Tab > Pipelines Table (projects:commit:pipelines)
* - Merge request details View > Pipelines Tab > Pipelines Table (projects:merge_requests:show)
* - New merge request View > Pipelines Tab > Pipelines Table (projects:merge_requests:creations:new)
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 1bc67522e82..03518d5fdd1 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -93,7 +93,7 @@ function mountPipelines() {
const { mrWidgetData } = gl;
const table = new Vue({
components: {
- CommitPipelinesTable: () => {
+ MergeRequestPipelinesTable: () => {
return gon.features.mrPipelinesGraphql
? import('~/ci/merge_requests/components/pipelines_table_wrapper.vue')
: import('~/commit/pipelines/legacy_pipelines_table_wrapper.vue');
@@ -112,7 +112,7 @@ function mountPipelines() {
withFailedJobsDetails: true,
},
render(createElement) {
- return createElement('commit-pipelines-table', {
+ return createElement('merge-request-pipelines-table', {
props: {
endpoint: pipelineTableViewEl.dataset.endpoint,
emptyStateSvgPath: pipelineTableViewEl.dataset.emptyStateSvgPath,
@@ -347,11 +347,11 @@ export default class MergeRequestTabs {
}
// this.hideSidebar();
this.resetViewContainer();
- this.commitPipelinesTable = destroyPipelines(this.commitPipelinesTable);
+ this.mergeRequestPipelinesTable = destroyPipelines(this.mergeRequestPipelinesTable);
} else if (action === 'new') {
this.expandView();
this.resetViewContainer();
- this.commitPipelinesTable = destroyPipelines(this.commitPipelinesTable);
+ this.mergeRequestPipelinesTable = destroyPipelines(this.mergeRequestPipelinesTable);
} else if (this.isDiffAction(action)) {
if (!isInVueNoteablePage()) {
/*
@@ -366,7 +366,7 @@ export default class MergeRequestTabs {
}
// this.hideSidebar();
this.expandViewContainer();
- this.commitPipelinesTable = destroyPipelines(this.commitPipelinesTable);
+ this.mergeRequestPipelinesTable = destroyPipelines(this.mergeRequestPipelinesTable);
this.commitsTab.classList.remove('active');
} else if (action === 'pipelines') {
// this.hideSidebar();
@@ -384,7 +384,7 @@ export default class MergeRequestTabs {
// this.showSidebar();
this.resetViewContainer();
- this.commitPipelinesTable = destroyPipelines(this.commitPipelinesTable);
+ this.mergeRequestPipelinesTable = destroyPipelines(this.mergeRequestPipelinesTable);
}
renderGFM(document.querySelector('.detail-page-description'));
@@ -522,7 +522,7 @@ export default class MergeRequestTabs {
}
mountPipelinesView() {
- this.commitPipelinesTable = mountPipelines();
+ this.mergeRequestPipelinesTable = mountPipelines();
}
// load the diff tab content from the backend
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index a90a16e120c..bdb2744be71 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -78,10 +78,6 @@ module MergeRequestsHelper
.execute(include_routes: true)
end
- def merge_request_button_visibility(merge_request, closed)
- return 'hidden' if merge_request_button_hidden?(merge_request, closed)
- end
-
def merge_request_button_hidden?(merge_request, closed)
merge_request.closed? == closed || (merge_request.merged? == closed && !merge_request.closed?) || merge_request.closed_or_merged_without_fork?
end
diff --git a/app/models/analytics/cycle_analytics/issue_stage_event.rb b/app/models/analytics/cycle_analytics/issue_stage_event.rb
index 837eb35c839..4930788c8b5 100644
--- a/app/models/analytics/cycle_analytics/issue_stage_event.rb
+++ b/app/models/analytics/cycle_analytics/issue_stage_event.rb
@@ -17,12 +17,42 @@ module Analytics
where(condition.arel.exists)
end
- def self.issuable_id_column
- :issue_id
- end
+ class << self
+ def project_column
+ :project_id
+ end
- def self.issuable_model
- ::Issue
+ def issuable_id_column
+ :issue_id
+ end
+
+ def issuable_model
+ ::Issue
+ end
+
+ def select_columns
+ [
+ *super,
+ issuable_model.arel_table[:weight],
+ issuable_model.arel_table[:sprint_id]
+ ]
+ end
+
+ def column_list
+ [
+ *super,
+ :weight,
+ :sprint_id
+ ]
+ end
+
+ def insert_column_list
+ [
+ *super,
+ :weight,
+ :sprint_id
+ ]
+ end
end
end
end
diff --git a/app/models/analytics/cycle_analytics/merge_request_stage_event.rb b/app/models/analytics/cycle_analytics/merge_request_stage_event.rb
index 0dfa322b2c3..7f85d284034 100644
--- a/app/models/analytics/cycle_analytics/merge_request_stage_event.rb
+++ b/app/models/analytics/cycle_analytics/merge_request_stage_event.rb
@@ -17,6 +17,10 @@ module Analytics
where(condition.arel.exists)
end
+ def self.project_column
+ :target_project_id
+ end
+
def self.issuable_id_column
:merge_request_id
end
diff --git a/app/models/concerns/analytics/cycle_analytics/stage_event_model.rb b/app/models/concerns/analytics/cycle_analytics/stage_event_model.rb
index d268c32c088..8f20e3880b3 100644
--- a/app/models/concerns/analytics/cycle_analytics/stage_event_model.rb
+++ b/app/models/concerns/analytics/cycle_analytics/stage_event_model.rb
@@ -57,45 +57,19 @@ module Analytics
class_methods do
def upsert_data(data)
- upsert_values = data.map do |row|
- row.values_at(
- :stage_event_hash_id,
- :issuable_id,
- :group_id,
- :project_id,
- :milestone_id,
- :author_id,
- :state_id,
- :start_event_timestamp,
- :end_event_timestamp
- )
- end
+ upsert_values = data.map { |row| row.values_at(*column_list) }
value_list = Arel::Nodes::ValuesList.new(upsert_values).to_sql
query = <<~SQL
INSERT INTO #{quoted_table_name}
(
- stage_event_hash_id,
- #{connection.quote_column_name(issuable_id_column)},
- group_id,
- project_id,
- milestone_id,
- author_id,
- state_id,
- start_event_timestamp,
- end_event_timestamp
+ #{insert_column_list.join(",\n")}
)
#{value_list}
ON CONFLICT(stage_event_hash_id, #{issuable_id_column})
DO UPDATE SET
- group_id = excluded.group_id,
- project_id = excluded.project_id,
- milestone_id = excluded.milestone_id,
- author_id = excluded.author_id,
- state_id = excluded.state_id,
- start_event_timestamp = excluded.start_event_timestamp,
- end_event_timestamp = excluded.end_event_timestamp
+ #{column_updates.join(",\n")}
SQL
result = connection.execute(query)
@@ -113,6 +87,51 @@ module Analytics
def arel_order(arel_node, direction)
direction.to_sym == :desc ? arel_node.desc : arel_node.asc
end
+
+ def select_columns
+ [
+ issuable_model.arel_table[:id],
+ issuable_model.arel_table[project_column].as('project_id'),
+ issuable_model.arel_table[:milestone_id],
+ issuable_model.arel_table[:author_id],
+ issuable_model.arel_table[:state_id],
+ Project.arel_table[:parent_id].as('group_id')
+ ]
+ end
+
+ def column_list
+ [
+ :stage_event_hash_id,
+ :issuable_id,
+ :group_id,
+ :project_id,
+ :milestone_id,
+ :author_id,
+ :state_id,
+ :start_event_timestamp,
+ :end_event_timestamp
+ ]
+ end
+
+ def insert_column_list
+ [
+ :stage_event_hash_id,
+ connection.quote_column_name(issuable_id_column),
+ :group_id,
+ :project_id,
+ :milestone_id,
+ :author_id,
+ :state_id,
+ :start_event_timestamp,
+ :end_event_timestamp
+ ]
+ end
+
+ def column_updates
+ insert_column_list.map do |column|
+ "#{column} = excluded.#{column}"
+ end
+ end
end
end
end
diff --git a/app/views/admin/application_settings/_sentry.html.haml b/app/views/admin/application_settings/_sentry.html.haml
index 9f2a40e4e54..7058a4b5cca 100644
--- a/app/views/admin/application_settings/_sentry.html.haml
+++ b/app/views/admin/application_settings/_sentry.html.haml
@@ -1,28 +1,31 @@
= gitlab_ui_form_for @application_setting, url: metrics_and_profiling_admin_application_settings_path(anchor: 'js-sentry-settings'), html: { class: 'fieldset-form', id: 'sentry-settings' } do |f|
= form_errors(@application_setting)
- %span.text-muted
- = _('Changing any setting here requires an application restart')
+ %fieldset.gl-text-secondary
+ = safe_format(s_('AdminSettings|GitLab uses the %{bold_start}Rails%{bold_end} and %{bold_start}Browser JavaScript%{bold_end} Sentry SDKs to send events to Sentry. For changes to Rails integration settings to take effect, restart GitLab.'), tag_pair(tag.b, :bold_start, :bold_end))
%fieldset
.form-group
- = f.gitlab_ui_checkbox_component :sentry_enabled, _('Enable Sentry error tracking')
- .form-group
- = f.label :sentry_dsn, _('DSN'), class: 'label-light'
- = f.text_field :sentry_dsn, class: 'form-control gl-form-input', placeholder: 'https://public@sentry.example.com/1'
- .form-group
- = f.label :sentry_clientside_dsn, _('Clientside DSN'), class: 'label-light'
- = f.text_field :sentry_clientside_dsn, class: 'form-control gl-form-input', placeholder: 'https://public@sentry.example.com/2'
+ = f.gitlab_ui_checkbox_component :sentry_enabled, s_('AdminSettings|Enable Sentry for Rails and Browser JavaScript')
.form-group
= f.label :sentry_environment, _('Environment'), class: 'label-light'
= f.text_field :sentry_environment, class: 'form-control gl-form-input', placeholder: Rails.env
-
- %p.text-muted
- = _("Changing any setting bellow doesn't require an application restart")
-
- %fieldset
+ .form-text.text-muted
+ = safe_format(s_('AdminSettings|%{setting_name} value used by both Rails and Browser JavaScript SDKs.'), setting_name: content_tag(:code, 'environment'))
+ .form-group
+ = f.label :sentry_dsn, _('DSN'), class: 'label-light'
+ = f.text_field :sentry_dsn, class: 'form-control gl-form-input', placeholder: 'https://public@sentry.example.com/1'
+ .form-text.text-muted
+ = safe_format(s_('AdminSettings|%{setting_name} value used by the Rails SDK.'), setting_name: content_tag(:code, 'dsn'))
+ .form-group
+ = f.label :sentry_clientside_dsn, _('Clientside DSN'), class: 'label-light'
+ = f.text_field :sentry_clientside_dsn, class: 'form-control gl-form-input', placeholder: 'https://public@sentry.example.com/2'
+ .form-text.text-muted
+ = safe_format(s_('AdminSettings|%{setting_name} value used by the Browser JavaScript SDK.'), setting_name: content_tag(:code, 'dsn'))
.form-group
= f.label :sentry_clientside_traces_sample_rate, _('Clientside traces sample rate'), class: 'label-light'
= f.number_field :sentry_clientside_traces_sample_rate, class: 'form-control gl-form-input', placeholder: '0.5', min: 0, max: 1, step: 0.001
+ .form-text.text-muted
+ = safe_format(s_('AdminSettings|%{setting_name} value used by the Browser JavaScript SDK.'), setting_name: content_tag(:code, 'tracesSampleRate'))
= f.submit _('Save changes'), pajamas_button: true
diff --git a/db/migrate/20230918123357_add_sprint_id_and_weight_to_vsa_issues.rb b/db/migrate/20230918123357_add_sprint_id_and_weight_to_vsa_issues.rb
new file mode 100644
index 00000000000..0c3b7b3086a
--- /dev/null
+++ b/db/migrate/20230918123357_add_sprint_id_and_weight_to_vsa_issues.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddSprintIdAndWeightToVsaIssues < Gitlab::Database::Migration[2.1]
+ enable_lock_retries!
+
+ def up
+ add_column :analytics_cycle_analytics_issue_stage_events, :weight, :integer
+ add_column :analytics_cycle_analytics_issue_stage_events, :sprint_id, :bigint
+ end
+
+ def down
+ remove_column :analytics_cycle_analytics_issue_stage_events, :sprint_id
+ remove_column :analytics_cycle_analytics_issue_stage_events, :weight
+ end
+end
diff --git a/db/schema_migrations/20230918123357 b/db/schema_migrations/20230918123357
new file mode 100644
index 00000000000..5fc1d62a963
--- /dev/null
+++ b/db/schema_migrations/20230918123357
@@ -0,0 +1 @@
+99e55170557dcda361f441d1333f4dc9d99133a469f1d17805478f3407d2a093
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index bd055a1ba70..e4f04117e69 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -720,7 +720,9 @@ CREATE TABLE analytics_cycle_analytics_issue_stage_events (
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
)
PARTITION BY HASH (stage_event_hash_id);
@@ -733,7 +735,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_00 FOR VALUES WITH (modulus 32, remainder 0);
@@ -746,7 +750,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_01 FOR VALUES WITH (modulus 32, remainder 1);
@@ -759,7 +765,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_02 FOR VALUES WITH (modulus 32, remainder 2);
@@ -772,7 +780,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_03 FOR VALUES WITH (modulus 32, remainder 3);
@@ -785,7 +795,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_04 FOR VALUES WITH (modulus 32, remainder 4);
@@ -798,7 +810,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_05 FOR VALUES WITH (modulus 32, remainder 5);
@@ -811,7 +825,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_06 FOR VALUES WITH (modulus 32, remainder 6);
@@ -824,7 +840,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_07 FOR VALUES WITH (modulus 32, remainder 7);
@@ -837,7 +855,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_08 FOR VALUES WITH (modulus 32, remainder 8);
@@ -850,7 +870,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_09 FOR VALUES WITH (modulus 32, remainder 9);
@@ -863,7 +885,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_10 FOR VALUES WITH (modulus 32, remainder 10);
@@ -876,7 +900,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_11 FOR VALUES WITH (modulus 32, remainder 11);
@@ -889,7 +915,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_12 FOR VALUES WITH (modulus 32, remainder 12);
@@ -902,7 +930,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_13 FOR VALUES WITH (modulus 32, remainder 13);
@@ -915,7 +945,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_14 FOR VALUES WITH (modulus 32, remainder 14);
@@ -928,7 +960,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_15 FOR VALUES WITH (modulus 32, remainder 15);
@@ -941,7 +975,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_16 FOR VALUES WITH (modulus 32, remainder 16);
@@ -954,7 +990,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_17 FOR VALUES WITH (modulus 32, remainder 17);
@@ -967,7 +1005,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_18 FOR VALUES WITH (modulus 32, remainder 18);
@@ -980,7 +1020,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_19 FOR VALUES WITH (modulus 32, remainder 19);
@@ -993,7 +1035,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_20 FOR VALUES WITH (modulus 32, remainder 20);
@@ -1006,7 +1050,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_21 FOR VALUES WITH (modulus 32, remainder 21);
@@ -1019,7 +1065,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_22 FOR VALUES WITH (modulus 32, remainder 22);
@@ -1032,7 +1080,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_23 FOR VALUES WITH (modulus 32, remainder 23);
@@ -1045,7 +1095,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_24 FOR VALUES WITH (modulus 32, remainder 24);
@@ -1058,7 +1110,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_25 FOR VALUES WITH (modulus 32, remainder 25);
@@ -1071,7 +1125,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_26 FOR VALUES WITH (modulus 32, remainder 26);
@@ -1084,7 +1140,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_27 FOR VALUES WITH (modulus 32, remainder 27);
@@ -1097,7 +1155,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_28 FOR VALUES WITH (modulus 32, remainder 28);
@@ -1110,7 +1170,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_29 FOR VALUES WITH (modulus 32, remainder 29);
@@ -1123,7 +1185,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_30 FOR VALUES WITH (modulus 32, remainder 30);
@@ -1136,7 +1200,9 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_issue_stage_even
author_id bigint,
start_event_timestamp timestamp with time zone NOT NULL,
end_event_timestamp timestamp with time zone,
- state_id smallint DEFAULT 1 NOT NULL
+ state_id smallint DEFAULT 1 NOT NULL,
+ weight integer,
+ sprint_id bigint
);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_31 FOR VALUES WITH (modulus 32, remainder 31);
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 2bf98cdc780..5d568647f4d 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -3375,6 +3375,15 @@ msgstr ""
msgid "AdminProjects|Delete Project %{projectName}?"
msgstr ""
+msgid "AdminSettings|%{setting_name} value used by both Rails and Browser JavaScript SDKs."
+msgstr ""
+
+msgid "AdminSettings|%{setting_name} value used by the Browser JavaScript SDK."
+msgstr ""
+
+msgid "AdminSettings|%{setting_name} value used by the Rails SDK."
+msgstr ""
+
msgid "AdminSettings|%{strongStart}WARNING:%{strongEnd} Environment variable %{environment_variable} does not exist or is not pointing to a valid directory. %{icon_link}"
msgstr ""
@@ -3450,6 +3459,9 @@ msgstr ""
msgid "AdminSettings|Enable Registration Features"
msgstr ""
+msgid "AdminSettings|Enable Sentry for Rails and Browser JavaScript"
+msgstr ""
+
msgid "AdminSettings|Enable Service Ping"
msgstr ""
@@ -3492,6 +3504,9 @@ msgstr ""
msgid "AdminSettings|Git abuse rate limit"
msgstr ""
+msgid "AdminSettings|GitLab uses the %{bold_start}Rails%{bold_end} and %{bold_start}Browser JavaScript%{bold_end} Sentry SDKs to send events to Sentry. For changes to Rails integration settings to take effect, restart GitLab."
+msgstr ""
+
msgid "AdminSettings|Group runners expiration"
msgstr ""
@@ -9610,12 +9625,6 @@ msgstr ""
msgid "Changes:"
msgstr ""
-msgid "Changing any setting bellow doesn't require an application restart"
-msgstr ""
-
-msgid "Changing any setting here requires an application restart"
-msgstr ""
-
msgid "Characters left"
msgstr ""
@@ -17959,9 +17968,6 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
-msgid "Enable Sentry error tracking"
-msgstr ""
-
msgid "Enable Snowplow tracking"
msgstr ""
@@ -34963,7 +34969,7 @@ msgstr ""
msgid "Pipeline|We are currently unable to fetch pipeline data"
msgstr ""
-msgid "Pipeline|You’re about to stop pipeline #%{pipelineId}."
+msgid "Pipeline|You're about to stop pipeline #%{pipelineId}."
msgstr ""
msgid "Pipeline|for"
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index cfd6bbf3094..e4e1772f08e 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe 'Database schema', feature_category: :database do
approvers: %w[target_id user_id],
analytics_cycle_analytics_aggregations: %w[last_full_issues_id last_full_merge_requests_id last_incremental_issues_id last_full_run_issues_id last_full_run_merge_requests_id last_incremental_merge_requests_id last_consistency_check_issues_stage_event_hash_id last_consistency_check_issues_issuable_id last_consistency_check_merge_requests_stage_event_hash_id last_consistency_check_merge_requests_issuable_id],
analytics_cycle_analytics_merge_request_stage_events: %w[author_id group_id merge_request_id milestone_id project_id stage_event_hash_id state_id],
- analytics_cycle_analytics_issue_stage_events: %w[author_id group_id issue_id milestone_id project_id stage_event_hash_id state_id],
+ analytics_cycle_analytics_issue_stage_events: %w[author_id group_id issue_id milestone_id project_id stage_event_hash_id state_id sprint_id],
audit_events: %w[author_id entity_id target_id],
award_emoji: %w[awardable_id user_id],
aws_roles: %w[role_external_id],
diff --git a/spec/frontend/ci/common/pipelines_table_spec.js b/spec/frontend/ci/common/pipelines_table_spec.js
index 26dd1a2fcc5..1ddeb901e59 100644
--- a/spec/frontend/ci/common/pipelines_table_spec.js
+++ b/spec/frontend/ci/common/pipelines_table_spec.js
@@ -1,9 +1,7 @@
-import '~/commons';
import { GlTableLite } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
import fixture from 'test_fixtures/pipelines/pipelines.json';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import LegacyPipelineMiniGraph from '~/ci/pipeline_mini_graph/legacy_pipeline_mini_graph.vue';
import PipelineFailedJobsWidget from '~/ci/pipelines_page/components/failure_widget/pipeline_failed_jobs_widget.vue';
import PipelineOperations from '~/ci/pipelines_page/components/pipeline_operations.vue';
@@ -20,14 +18,12 @@ import {
import CiBadgeLink from '~/vue_shared/components/ci_badge_link.vue';
-jest.mock('~/ci/event_hub');
-
describe('Pipelines Table', () => {
- let pipeline;
let wrapper;
let trackingSpy;
const defaultProvide = {
+ fullPath: '/my-project/',
glFeatures: {},
withFailedJobsDetails: false,
};
@@ -39,32 +35,31 @@ describe('Pipelines Table', () => {
withFailedJobsDetails: true,
};
+ const { pipelines } = fixture;
+
const defaultProps = {
- pipelines: [],
+ pipelines,
viewType: 'root',
pipelineKeyOption: PipelineKeyOptions[0],
};
- const createMockPipeline = () => {
- // Clone fixture as it could be modified by tests
- const { pipelines } = JSON.parse(JSON.stringify(fixture));
- return pipelines.find((p) => p.user !== null && p.commit !== null);
- };
+ const [firstPipeline] = pipelines;
- const createComponent = (props = {}, provide = {}) => {
- wrapper = extendedWrapper(
- mount(PipelinesTable, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- provide: {
- ...defaultProvide,
- ...provide,
- },
- stubs: ['PipelineFailedJobsWidget'],
- }),
- );
+ const createComponent = ({ props = {}, provide = {}, stubs = {} } = {}) => {
+ wrapper = mountExtended(PipelinesTable, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ provide: {
+ ...defaultProvide,
+ ...provide,
+ },
+ stubs: {
+ PipelineOperations: true,
+ ...stubs,
+ },
+ });
};
const findGlTableLite = () => wrapper.findComponent(GlTableLite);
@@ -84,13 +79,9 @@ describe('Pipelines Table', () => {
const findRetryBtn = () => wrapper.findByTestId('pipelines-retry-button');
const findCancelBtn = () => wrapper.findByTestId('pipelines-cancel-button');
- beforeEach(() => {
- pipeline = createMockPipeline();
- });
-
describe('Pipelines Table', () => {
beforeEach(() => {
- createComponent({ pipelines: [pipeline], viewType: 'root' });
+ createComponent({ props: { viewType: 'root' } });
});
it('displays table', () => {
@@ -105,7 +96,7 @@ describe('Pipelines Table', () => {
});
it('should display a table row', () => {
- expect(findTableRows()).toHaveLength(1);
+ expect(findTableRows()).toHaveLength(pipelines.length);
});
describe('status cell', () => {
@@ -120,7 +111,7 @@ describe('Pipelines Table', () => {
});
it('should display the pipeline id', () => {
- expect(findPipelineInfo().text()).toContain(`#${pipeline.id}`);
+ expect(findPipelineInfo().text()).toContain(`#${firstPipeline.id}`);
});
});
@@ -130,24 +121,33 @@ describe('Pipelines Table', () => {
});
it('should render the right number of stages', () => {
- const stagesLength = pipeline.details.stages.length;
- expect(findLegacyPipelineMiniGraph().props('stages').length).toBe(stagesLength);
+ const stagesLength = firstPipeline.details.stages.length;
+ expect(findLegacyPipelineMiniGraph().props('stages')).toHaveLength(stagesLength);
});
it('should render the latest downstream pipelines only', () => {
// component receives two downstream pipelines. one of them is already outdated
// because we retried the trigger job, so the mini pipeline graph will only
// render the newly created downstream pipeline instead
- expect(pipeline.triggered).toHaveLength(2);
+ expect(firstPipeline.triggered).toHaveLength(2);
expect(findLegacyPipelineMiniGraph().props('downstreamPipelines')).toHaveLength(1);
});
describe('when pipeline does not have stages', () => {
beforeEach(() => {
- pipeline = createMockPipeline();
- pipeline.details.stages = [];
-
- createComponent({ pipelines: [pipeline] });
+ createComponent({
+ props: {
+ pipelines: [
+ {
+ ...firstPipeline,
+ details: {
+ ...firstPipeline.details,
+ stages: [],
+ },
+ },
+ ],
+ },
+ });
});
it('stages are not rendered', () => {
@@ -163,6 +163,10 @@ describe('Pipelines Table', () => {
});
describe('operations cell', () => {
+ beforeEach(() => {
+ createComponent({ stubs: { PipelineOperations } });
+ });
+
it('should render pipeline operations', () => {
expect(findActions().exists()).toBe(true);
});
@@ -186,11 +190,11 @@ describe('Pipelines Table', () => {
describe('row', () => {
describe('when the FF is disabled', () => {
beforeEach(() => {
- createComponent({ pipelines: [pipeline] });
+ createComponent();
});
it('does not render', () => {
- expect(findTableRows()).toHaveLength(1);
+ expect(findTableRows()).toHaveLength(pipelines.length);
expect(findPipelineFailureWidget().exists()).toBe(false);
});
});
@@ -198,20 +202,21 @@ describe('Pipelines Table', () => {
describe('when the FF is enabled', () => {
describe('and `withFailedJobsDetails` value is provided', () => {
beforeEach(() => {
- createComponent({ pipelines: [pipeline] }, provideWithDetails);
+ createComponent({ provide: provideWithDetails });
});
it('renders', () => {
- expect(findTableRows()).toHaveLength(2);
+ // We have 2 rows per pipeline with the widget
+ expect(findTableRows()).toHaveLength(pipelines.length * 2);
expect(findPipelineFailureWidget().exists()).toBe(true);
});
it('passes the expected props', () => {
expect(findPipelineFailureWidget().props()).toStrictEqual({
- failedJobsCount: pipeline.failed_builds.length,
- isPipelineActive: pipeline.active,
- pipelineIid: pipeline.iid,
- pipelinePath: pipeline.path,
+ failedJobsCount: firstPipeline.failed_builds.length,
+ isPipelineActive: firstPipeline.active,
+ pipelineIid: firstPipeline.iid,
+ pipelinePath: firstPipeline.path,
// Make sure the forward slash was removed
projectPath: 'frontend-fixtures/pipelines-project',
});
@@ -220,14 +225,13 @@ describe('Pipelines Table', () => {
describe('and `withFailedJobsDetails` value is not provided', () => {
beforeEach(() => {
- createComponent(
- { pipelines: [pipeline] },
- { glFeatures: { ciJobFailuresInMr: true } },
- );
+ createComponent({
+ provide: { glFeatures: { ciJobFailuresInMr: true } },
+ });
});
it('does not render', () => {
- expect(findTableRows()).toHaveLength(1);
+ expect(findTableRows()).toHaveLength(pipelines.length);
expect(findPipelineFailureWidget().exists()).toBe(false);
});
});
@@ -235,6 +239,42 @@ describe('Pipelines Table', () => {
});
});
+ describe('events', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ describe('when confirming to cancel a pipeline', () => {
+ beforeEach(async () => {
+ await findActions().vm.$emit('cancel-pipeline', firstPipeline);
+ });
+
+ it('emits the `cancel-pipeline` event', () => {
+ expect(wrapper.emitted('cancel-pipeline')).toEqual([[firstPipeline]]);
+ });
+ });
+
+ describe('when retrying a pipeline', () => {
+ beforeEach(() => {
+ findActions().vm.$emit('retry-pipeline', firstPipeline);
+ });
+
+ it('emits the `retry-pipeline` event', () => {
+ expect(wrapper.emitted('retry-pipeline')).toEqual([[firstPipeline]]);
+ });
+ });
+
+ describe('when refreshing pipelines', () => {
+ beforeEach(() => {
+ findActions().vm.$emit('refresh-pipelines-table');
+ });
+
+ it('emits the `refresh-pipelines-table` event', () => {
+ expect(wrapper.emitted('refresh-pipelines-table')).toEqual([[]]);
+ });
+ });
+ });
+
describe('tracking', () => {
beforeEach(() => {
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
@@ -252,22 +292,6 @@ describe('Pipelines Table', () => {
});
});
- it('tracks retry pipeline button click', () => {
- findRetryBtn().vm.$emit('click');
-
- expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_retry_button', {
- label: TRACKING_CATEGORIES.table,
- });
- });
-
- it('tracks cancel pipeline button click', () => {
- findCancelBtn().vm.$emit('click');
-
- expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_cancel_button', {
- label: TRACKING_CATEGORIES.table,
- });
- });
-
it('tracks pipeline mini graph stage click', () => {
findLegacyPipelineMiniGraph().vm.$emit('miniGraphStageClick');
diff --git a/spec/frontend/ci/pipelines_page/components/pipeline_operations_spec.js b/spec/frontend/ci/pipelines_page/components/pipeline_operations_spec.js
index d2eab64b317..6205a37e291 100644
--- a/spec/frontend/ci/pipelines_page/components/pipeline_operations_spec.js
+++ b/spec/frontend/ci/pipelines_page/components/pipeline_operations_spec.js
@@ -1,10 +1,13 @@
+import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import PipelinesManualActions from '~/ci/pipelines_page/components/pipelines_manual_actions.vue';
import PipelineMultiActions from '~/ci/pipelines_page/components/pipeline_multi_actions.vue';
import PipelineOperations from '~/ci/pipelines_page/components/pipeline_operations.vue';
-import eventHub from '~/ci/event_hub';
+import PipelineStopModal from '~/ci/pipelines_page/components/pipeline_stop_modal.vue';
+import { TRACKING_CATEGORIES } from '~/ci/constants';
describe('Pipeline operations', () => {
+ let trackingSpy;
let wrapper;
const defaultProps = {
@@ -36,6 +39,7 @@ describe('Pipeline operations', () => {
const findMultiActions = () => wrapper.findComponent(PipelineMultiActions);
const findRetryBtn = () => wrapper.findByTestId('pipelines-retry-button');
const findCancelBtn = () => wrapper.findByTestId('pipelines-cancel-button');
+ const findPipelineStopModal = () => wrapper.findComponent(PipelineStopModal);
it('should display pipeline manual actions', () => {
createComponent();
@@ -49,28 +53,71 @@ describe('Pipeline operations', () => {
expect(findMultiActions().exists()).toBe(true);
});
+ it('does not show the confirmation modal', () => {
+ createComponent();
+
+ expect(findPipelineStopModal().props().showConfirmationModal).toBe(false);
+ });
+
+ describe('when cancelling a pipeline', () => {
+ beforeEach(async () => {
+ createComponent();
+ await findCancelBtn().vm.$emit('click');
+ });
+
+ it('should show a confirmation modal', () => {
+ expect(findPipelineStopModal().props().showConfirmationModal).toBe(true);
+ });
+
+ it('should emit cancel-pipeline event when confirming', async () => {
+ await findPipelineStopModal().vm.$emit('submit');
+
+ expect(wrapper.emitted('cancel-pipeline')).toEqual([[defaultProps.pipeline]]);
+ expect(findPipelineStopModal().props().showConfirmationModal).toBe(false);
+ });
+
+ it('should hide the modal when closing', async () => {
+ await findPipelineStopModal().vm.$emit('close-modal');
+
+ expect(findPipelineStopModal().props().showConfirmationModal).toBe(false);
+ });
+ });
+
describe('events', () => {
beforeEach(() => {
createComponent();
-
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
});
it('should emit retryPipeline event', () => {
findRetryBtn().vm.$emit('click');
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'retryPipeline',
- defaultProps.pipeline.retry_path,
- );
+ expect(wrapper.emitted('retry-pipeline')).toEqual([[defaultProps.pipeline]]);
+ });
+ });
+
+ describe('tracking', () => {
+ beforeEach(() => {
+ createComponent();
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
- it('should emit openConfirmationModal event', () => {
+ afterEach(() => {
+ unmockTracking();
+ });
+
+ it('tracks retry pipeline button click', () => {
+ findRetryBtn().vm.$emit('click');
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_retry_button', {
+ label: TRACKING_CATEGORIES.table,
+ });
+ });
+
+ it('tracks cancel pipeline button click', () => {
findCancelBtn().vm.$emit('click');
- expect(eventHub.$emit).toHaveBeenCalledWith('openConfirmationModal', {
- pipeline: defaultProps.pipeline,
- endpoint: defaultProps.pipeline.cancel_path,
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_cancel_button', {
+ label: TRACKING_CATEGORIES.table,
});
});
});
diff --git a/spec/frontend/ci/pipelines_page/components/pipeline_stop_modal_spec.js b/spec/frontend/ci/pipelines_page/components/pipeline_stop_modal_spec.js
index 4d78a923542..1e276840c07 100644
--- a/spec/frontend/ci/pipelines_page/components/pipeline_stop_modal_spec.js
+++ b/spec/frontend/ci/pipelines_page/components/pipeline_stop_modal_spec.js
@@ -1,15 +1,17 @@
import { shallowMount } from '@vue/test-utils';
-import { GlSprintf } from '@gitlab/ui';
+import { GlModal, GlSprintf } from '@gitlab/ui';
import { mockPipelineHeader } from 'jest/ci/pipeline_details/mock_data';
import PipelineStopModal from '~/ci/pipelines_page/components/pipeline_stop_modal.vue';
describe('PipelineStopModal', () => {
let wrapper;
- const createComponent = () => {
+ const createComponent = ({ props = {} } = {}) => {
wrapper = shallowMount(PipelineStopModal, {
propsData: {
pipeline: mockPipelineHeader,
+ showConfirmationModal: false,
+ ...props,
},
stubs: {
GlSprintf,
@@ -17,11 +19,43 @@ describe('PipelineStopModal', () => {
});
};
+ const findModal = () => wrapper.findComponent(GlModal);
+
beforeEach(() => {
createComponent();
});
- it('should render "stop pipeline" warning', () => {
- expect(wrapper.text()).toMatch(`You’re about to stop pipeline #${mockPipelineHeader.id}.`);
+ describe('when `showConfirmationModal` is false', () => {
+ it('passes the visiblity value to the modal', () => {
+ expect(findModal().props().visible).toBe(false);
+ });
+ });
+
+ describe('when `showConfirmationModal` is true', () => {
+ beforeEach(() => {
+ createComponent({ props: { showConfirmationModal: true } });
+ });
+
+ it('passes the visiblity value to the modal', () => {
+ expect(findModal().props().visible).toBe(true);
+ });
+
+ it('renders "stop pipeline" warning', () => {
+ expect(wrapper.text()).toMatch(`You're about to stop pipeline #${mockPipelineHeader.id}.`);
+ });
+ });
+
+ describe('events', () => {
+ beforeEach(() => {
+ createComponent({ props: { showConfirmationModal: true } });
+ });
+
+ it('emits the close-modal event when the visiblity changes', async () => {
+ expect(wrapper.emitted('close-modal')).toBeUndefined();
+
+ await findModal().vm.$emit('change', false);
+
+ expect(wrapper.emitted('close-modal')).toEqual([[]]);
+ });
});
});
diff --git a/spec/frontend/commit/pipelines/legacy_pipelines_table_wrapper_spec.js b/spec/frontend/commit/pipelines/legacy_pipelines_table_wrapper_spec.js
index 4af292e3588..d58b139dae3 100644
--- a/spec/frontend/commit/pipelines/legacy_pipelines_table_wrapper_spec.js
+++ b/spec/frontend/commit/pipelines/legacy_pipelines_table_wrapper_spec.js
@@ -1,13 +1,13 @@
import { GlLoadingIcon, GlModal, GlTableLite } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import fixture from 'test_fixtures/pipelines/pipelines.json';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { stubComponent } from 'helpers/stub_component';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
-import LegacyPipelinesTableWraper from '~/commit/pipelines/legacy_pipelines_table_wrapper.vue';
+import LegacyPipelinesTableWrapper from '~/commit/pipelines/legacy_pipelines_table_wrapper.vue';
+import PipelinesTable from '~/ci/common/pipelines_table.vue';
import {
HTTP_STATUS_BAD_REQUEST,
HTTP_STATUS_INTERNAL_SERVER_ERROR,
@@ -39,27 +39,26 @@ describe('Pipelines table in Commits and Merge requests', () => {
const findTableRows = () => wrapper.findAllByTestId('pipeline-table-row');
const findModal = () => wrapper.findComponent(GlModal);
const findMrPipelinesDocsLink = () => wrapper.findByTestId('mr-pipelines-docs-link');
+ const findPipelinesTable = () => wrapper.findComponent(PipelinesTable);
- const createComponent = ({ props = {} } = {}) => {
- wrapper = extendedWrapper(
- mount(LegacyPipelinesTableWraper, {
- propsData: {
- endpoint: 'endpoint.json',
- emptyStateSvgPath: 'foo',
- errorStateSvgPath: 'foo',
- ...props,
- },
- mocks: {
- $toast,
- },
- stubs: {
- GlModal: stubComponent(GlModal, {
- template: '',
- methods: { show: showMock },
- }),
- },
- }),
- );
+ const createComponent = ({ props = {}, mountFn = mountExtended } = {}) => {
+ wrapper = mountFn(LegacyPipelinesTableWrapper, {
+ propsData: {
+ endpoint: 'endpoint.json',
+ emptyStateSvgPath: 'foo',
+ errorStateSvgPath: 'foo',
+ ...props,
+ },
+ mocks: {
+ $toast,
+ },
+ stubs: {
+ GlModal: stubComponent(GlModal, {
+ template: '',
+ methods: { show: showMock },
+ }),
+ },
+ });
};
beforeEach(() => {
@@ -116,7 +115,6 @@ describe('Pipelines table in Commits and Merge requests', () => {
it('should make an API request when using pagination', async () => {
expect(mock.history.get).toHaveLength(1);
- expect(mock.history.get[0].params.page).toBe('1');
wrapper.find('.next-page-item').trigger('click');
@@ -359,4 +357,53 @@ describe('Pipelines table in Commits and Merge requests', () => {
);
});
});
+
+ describe('events', () => {
+ beforeEach(async () => {
+ mock.onGet('endpoint.json').reply(HTTP_STATUS_OK, [pipeline]);
+
+ createComponent({ mountFn: shallowMountExtended });
+
+ await waitForPromises();
+ });
+
+ describe('When cancelling a pipeline', () => {
+ it('sends the cancel action', async () => {
+ expect(mock.history.post).toHaveLength(0);
+
+ findPipelinesTable().vm.$emit('cancel-pipeline', pipeline);
+
+ await waitForPromises();
+
+ expect(mock.history.post).toHaveLength(1);
+ expect(mock.history.post[0].url).toContain('cancel.json');
+ });
+ });
+
+ describe('When retrying a pipeline', () => {
+ it('sends the retry action', async () => {
+ expect(mock.history.post).toHaveLength(0);
+
+ findPipelinesTable().vm.$emit('retry-pipeline', pipeline);
+
+ await waitForPromises();
+
+ expect(mock.history.post).toHaveLength(1);
+ expect(mock.history.post[0].url).toContain('retry.json');
+ });
+ });
+
+ describe('When refreshing a pipeline', () => {
+ it('calls the pipelines endpoint again', async () => {
+ expect(mock.history.get).toHaveLength(1);
+
+ findPipelinesTable().vm.$emit('refresh-pipelines-table');
+
+ await waitForPromises();
+
+ expect(mock.history.get).toHaveLength(2);
+ expect(mock.history.get[1].url).toContain('endpoint.json');
+ });
+ });
+ });
});