Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.rubocop_todo/security/open.yml4
-rw-r--r--.rubocop_todo/style/single_argument_dig.yml12
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue2
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue5
-rw-r--r--app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue61
-rw-r--r--app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue65
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/actions.js76
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/getters.js45
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/index.js17
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/mutation_types.js5
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/mutations.js20
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/state.js28
-rw-r--r--app/assets/javascripts/reports/components/issue_body.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue291
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue137
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue119
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue23
-rw-r--r--app/assets/javascripts/vue_shared/components/url_sync.vue17
-rw-r--r--app/assets/stylesheets/page_bundles/merge_requests.scss4
-rw-r--r--app/controllers/projects/incidents_controller.rb1
-rw-r--r--app/controllers/projects/issues_controller.rb1
-rw-r--r--app/controllers/projects/merge_requests_controller.rb1
-rw-r--r--app/services/bulk_imports/create_pipeline_trackers_service.rb2
-rw-r--r--app/services/incident_management/timeline_events/create_service.rb1
-rw-r--r--app/services/incident_management/timeline_events/destroy_service.rb2
-rw-r--r--app/services/incident_management/timeline_events/update_service.rb2
-rw-r--r--app/views/admin/application_settings/_package_registry.html.haml8
-rw-r--r--app/views/admin/application_settings/_terms.html.haml2
-rw-r--r--app/views/admin/deploy_keys/edit.html.haml4
-rw-r--r--app/views/admin/groups/_form.html.haml4
-rw-r--r--app/views/projects/hooks/index.html.haml2
-rw-r--r--app/workers/bulk_imports/entity_worker.rb8
-rw-r--r--app/workers/bulk_imports/pipeline_worker.rb12
-rw-r--r--config/feature_flags/development/incident_timeline.yml8
-rw-r--r--config/feature_flags/development/refactor_mr_widgets_extensions.yml8
-rw-r--r--config/feature_flags/development/refactor_mr_widgets_extensions_user.yml8
-rw-r--r--doc/administration/job_artifacts.md2
-rw-r--r--doc/administration/lfs/index.md1
-rw-r--r--doc/administration/raketasks/uploads/migrate.md9
-rw-r--r--doc/operations/incident_management/incident_timeline_events.md8
-rw-r--r--lib/tasks/gitlab/seed.rake35
-rw-r--r--locale/gitlab.pot45
-rw-r--r--scripts/lib/glfm/update_specification.rb2
-rw-r--r--spec/features/incidents/incident_timeline_events_spec.rb1
-rw-r--r--spec/features/issues/incident_issue_spec.rb16
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb2
-rw-r--r--spec/frontend/issues/show/components/incidents/incident_tabs_spec.js19
-rw-r--r--spec/frontend/reports/accessibility_report/components/accessibility_issue_body_spec.js112
-rw-r--r--spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js125
-rw-r--r--spec/frontend/reports/accessibility_report/mock_data.js53
-rw-r--r--spec/frontend/reports/accessibility_report/store/actions_spec.js115
-rw-r--r--spec/frontend/reports/accessibility_report/store/getters_spec.js149
-rw-r--r--spec/frontend/reports/accessibility_report/store/mutations_spec.js64
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap2
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js2
-rw-r--r--spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js175
-rw-r--r--spec/frontend/vue_merge_request_widget/components/terraform/terraform_plan_spec.js93
-rw-r--r--spec/frontend/vue_shared/components/url_sync_spec.js62
-rw-r--r--spec/scripts/lib/glfm/update_specification_spec.rb10
-rw-r--r--spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb4
-rw-r--r--spec/services/incident_management/timeline_events/create_service_spec.rb82
-rw-r--r--spec/services/incident_management/timeline_events/destroy_service_spec.rb20
-rw-r--r--spec/services/incident_management/timeline_events/update_service_spec.rb14
-rw-r--r--spec/support/capybara_slow_finder.rb7
-rw-r--r--spec/support_specs/capybara_slow_finder_spec.rb28
-rw-r--r--spec/views/admin/application_settings/_package_registry.html.haml_spec.rb2
-rw-r--r--spec/workers/bulk_imports/entity_worker_spec.rb12
-rw-r--r--spec/workers/bulk_imports/pipeline_worker_spec.rb16
69 files changed, 365 insertions, 1932 deletions
diff --git a/.rubocop_todo/security/open.yml b/.rubocop_todo/security/open.yml
deleted file mode 100644
index 9626b442a92..00000000000
--- a/.rubocop_todo/security/open.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-Security/Open:
- Exclude:
- - 'scripts/lib/glfm/update_specification.rb'
diff --git a/.rubocop_todo/style/single_argument_dig.yml b/.rubocop_todo/style/single_argument_dig.yml
index 860183426e9..3ffd27d26ae 100644
--- a/.rubocop_todo/style/single_argument_dig.yml
+++ b/.rubocop_todo/style/single_argument_dig.yml
@@ -1,9 +1,7 @@
---
# Cop supports --auto-correct.
Style/SingleArgumentDig:
- # Offense count: 150
- # Temporarily disabled due to too many offenses
- Enabled: false
+ Details: grace period
Exclude:
- 'app/graphql/resolvers/namespace_projects_resolver.rb'
- 'app/models/ci/build.rb'
@@ -22,6 +20,7 @@ Style/SingleArgumentDig:
- 'ee/app/workers/concerns/elastic/migration_helper.rb'
- 'ee/lib/gitlab/ci/parsers/security/dependency_list.rb'
- 'ee/lib/gitlab/subscription_portal/clients/graphql.rb'
+ - 'ee/spec/elastic/migrate/20220119120500_populate_commit_permissions_in_main_index_spec.rb'
- 'ee/spec/graphql/mutations/vulnerabilities/create_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/parsers/security/common_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/pipeline/chain/validate/external_spec.rb'
@@ -35,10 +34,11 @@ Style/SingleArgumentDig:
- 'ee/spec/requests/api/graphql/project/dast_site_profiles_spec.rb'
- 'ee/spec/requests/api/graphql/project/requirements_management/requirements_spec.rb'
- 'ee/spec/requests/api/internal/upcoming_reconciliations_spec.rb'
+ - 'ee/spec/services/vulnerabilities/findings/find_or_create_from_security_finding_service_spec.rb'
- 'ee/spec/services/vulnerabilities/manually_create_service_spec.rb'
+ - 'lib/gitlab/auth/o_auth/auth_hash.rb'
- 'lib/gitlab/ci/badge/coverage/template.rb'
- - 'lib/gitlab/ci/badge/pipeline/template.rb'
- - 'lib/gitlab/ci/badge/release/template.rb'
+ - 'lib/gitlab/ci/badge/template.rb'
- 'lib/gitlab/ci/lint.rb'
- 'lib/gitlab/ci/parsers/accessibility/pa11y.rb'
- 'lib/gitlab/ci/parsers/security/common.rb'
@@ -51,11 +51,13 @@ Style/SingleArgumentDig:
- 'lib/gitlab/database/transaction/observer.rb'
- 'lib/gitlab/serverless/service.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb'
+ - 'qa/qa/vendor/mail_hog/api.rb'
- 'spec/controllers/graphql_controller_spec.rb'
- 'spec/graphql/types/release_links_type_spec.rb'
- 'spec/helpers/projects_helper_spec.rb'
- 'spec/lib/gitlab/ci/yaml_processor_spec.rb'
- 'spec/requests/api/ci/runner/jobs_request_post_spec.rb'
+ - 'spec/requests/api/graphql/ci/instance_variables_spec.rb'
- 'spec/requests/api/graphql/container_repository/container_repository_details_spec.rb'
- 'spec/requests/api/graphql/project/container_repositories_spec.rb'
- 'spec/requests/api/graphql/project/jira_import_spec.rb'
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index 0e5acd0928b..c970f0f8942 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -128,7 +128,7 @@ export default {
:img-src="authorAvatar"
:img-alt="authorName"
:img-size="32"
- class="avatar-cell d-none d-sm-block"
+ class="avatar-cell d-none d-sm-block gl-my-2 gl-mr-4"
/>
</div>
<div
diff --git a/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue b/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue
index dd84a1d7d67..5725d0f8d6a 100644
--- a/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue
+++ b/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue
@@ -52,9 +52,6 @@ export default {
loading() {
return this.$apollo.queries.alert.loading;
},
- incidentTabEnabled() {
- return this.glFeatures.incidentTimeline;
- },
},
mounted() {
this.trackPageViews();
@@ -112,7 +109,7 @@ export default {
>
<alert-details-table :alert="alert" :loading="loading" />
</gl-tab>
- <timeline-tab v-if="incidentTabEnabled" />
+ <timeline-tab />
</gl-tabs>
</div>
</template>
diff --git a/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue b/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue
deleted file mode 100644
index 05ab5c2cc90..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue
+++ /dev/null
@@ -1,61 +0,0 @@
-<script>
-import { GlBadge, GlLink } from '@gitlab/ui';
-
-export default {
- name: 'AccessibilityIssueBody',
- components: {
- GlBadge,
- GlLink,
- },
- props: {
- issue: {
- type: Object,
- required: true,
- },
- isNew: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- parsedTECHSCode() {
- /*
- * In issue code looks like "WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail"
- * or "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent"
- *
- * The TECHS code is the "G18", "G168", "H91", etc. from the code which is used for the documentation.
- * Here we simply split the string on `.` and get the code in the 5th position
- */
- return this.issue.code?.split('.')[4];
- },
- learnMoreUrl() {
- // eslint-disable-next-line @gitlab/require-i18n-strings
- return `https://www.w3.org/TR/WCAG20-TECHS/${this.parsedTECHSCode || 'Overview'}.html`;
- },
- },
-};
-</script>
-<template>
- <div class="report-block-list-issue-description gl-mt-2 gl-mb-2">
- <div ref="accessibility-issue-description" class="report-block-list-issue-description-text">
- <gl-badge v-if="isNew" class="gl-mr-2" variant="danger">{{
- s__('AccessibilityReport|New')
- }}</gl-badge>
- <div>
- {{
- sprintf(
- s__(
- 'AccessibilityReport|The accessibility scanning found an error of the following type: %{code}',
- ),
- { code: issue.code },
- )
- }}
- <gl-link ref="accessibility-issue-learn-more" :href="learnMoreUrl" target="_blank">{{
- s__('AccessibilityReport|Learn more')
- }}</gl-link>
- </div>
- {{ sprintf(s__('AccessibilityReport|Message: %{message}'), { message: issue.message }) }}
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue b/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue
deleted file mode 100644
index 99cdeae545e..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/grouped_accessibility_reports_app.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-<script>
-import { mapActions, mapGetters } from 'vuex';
-import { componentNames } from '~/reports/components/issue_body';
-import IssuesList from '~/reports/components/issues_list.vue';
-import ReportSection from '~/reports/components/report_section.vue';
-import createStore from './store';
-
-export default {
- name: 'GroupedAccessibilityReportsApp',
- store: createStore(),
- components: {
- ReportSection,
- IssuesList,
- },
- props: {
- endpoint: {
- type: String,
- required: true,
- },
- },
- componentNames,
- computed: {
- ...mapGetters([
- 'summaryStatus',
- 'groupedSummaryText',
- 'shouldRenderIssuesList',
- 'unresolvedIssues',
- 'resolvedIssues',
- 'newIssues',
- ]),
- },
- created() {
- this.setEndpoint(this.endpoint);
-
- this.fetchReport();
- },
- methods: {
- ...mapActions(['fetchReport', 'setEndpoint']),
- },
-};
-</script>
-<template>
- <report-section
- :status="summaryStatus"
- :success-text="groupedSummaryText"
- :loading-text="groupedSummaryText"
- :error-text="groupedSummaryText"
- :has-issues="shouldRenderIssuesList"
- track-action="users_expanding_testing_accessibility_report"
- class="mr-widget-section grouped-security-reports mr-report"
- >
- <template #body>
- <div class="mr-widget-grouped-section report-block">
- <issues-list
- v-if="shouldRenderIssuesList"
- :unresolved-issues="unresolvedIssues"
- :new-issues="newIssues"
- :resolved-issues="resolvedIssues"
- :component="$options.componentNames.AccessibilityIssueBody"
- class="report-block-group-list"
- />
- </div>
- </template>
- </report-section>
-</template>
diff --git a/app/assets/javascripts/reports/accessibility_report/store/actions.js b/app/assets/javascripts/reports/accessibility_report/store/actions.js
deleted file mode 100644
index e0142a35291..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/store/actions.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import Visibility from 'visibilityjs';
-import axios from '~/lib/utils/axios_utils';
-import httpStatusCodes from '~/lib/utils/http_status';
-import Poll from '~/lib/utils/poll';
-import * as types from './mutation_types';
-
-let eTagPoll;
-
-export const clearEtagPoll = () => {
- eTagPoll = null;
-};
-
-export const stopPolling = () => {
- if (eTagPoll) eTagPoll.stop();
-};
-
-export const restartPolling = () => {
- if (eTagPoll) eTagPoll.restart();
-};
-
-export const setEndpoint = ({ commit }, endpoint) => commit(types.SET_ENDPOINT, endpoint);
-
-/**
- * We need to poll the report endpoint while they are being parsed in the Backend.
- * This can take up to one minute.
- *
- * Poll.js will handle etag response.
- * While http status code is 204, it means it's parsing, and we'll keep polling
- * When http status code is 200, it means parsing is done, we can show the results & stop polling
- * When http status code is 500, it means parsing went wrong and we stop polling
- */
-export const fetchReport = ({ state, dispatch, commit }) => {
- commit(types.REQUEST_REPORT);
-
- eTagPoll = new Poll({
- resource: {
- getReport(endpoint) {
- return axios.get(endpoint);
- },
- },
- data: state.endpoint,
- method: 'getReport',
- successCallback: ({ status, data }) => dispatch('receiveReportSuccess', { status, data }),
- errorCallback: () => dispatch('receiveReportError'),
- });
-
- if (!Visibility.hidden()) {
- eTagPoll.makeRequest();
- } else {
- axios
- .get(state.endpoint)
- .then(({ status, data }) => dispatch('receiveReportSuccess', { status, data }))
- .catch(() => dispatch('receiveReportError'));
- }
-
- Visibility.change(() => {
- if (!Visibility.hidden() && state.isLoading) {
- dispatch('restartPolling');
- } else {
- dispatch('stopPolling');
- }
- });
-};
-
-export const receiveReportSuccess = ({ commit, dispatch }, { status, data }) => {
- if (status === httpStatusCodes.OK) {
- commit(types.RECEIVE_REPORT_SUCCESS, data);
- // Stop polling since we have the information already parsed and it won't be changing
- dispatch('stopPolling');
- }
-};
-
-export const receiveReportError = ({ commit, dispatch }) => {
- commit(types.RECEIVE_REPORT_ERROR);
- dispatch('stopPolling');
-};
diff --git a/app/assets/javascripts/reports/accessibility_report/store/getters.js b/app/assets/javascripts/reports/accessibility_report/store/getters.js
deleted file mode 100644
index 20506b1bfd1..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/store/getters.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import { s__, n__ } from '~/locale';
-import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '../../constants';
-
-export const groupedSummaryText = (state) => {
- if (state.isLoading) {
- return s__('Reports|Accessibility scanning results are being parsed');
- }
-
- if (state.hasError) {
- return s__('Reports|Accessibility scanning failed loading results');
- }
-
- const numberOfResults = state.report?.summary?.errored || 0;
- if (numberOfResults === 0) {
- return s__('Reports|Accessibility scanning detected no issues for the source branch only');
- }
-
- return n__(
- 'Reports|Accessibility scanning detected %d issue for the source branch only',
- 'Reports|Accessibility scanning detected %d issues for the source branch only',
- numberOfResults,
- );
-};
-
-export const summaryStatus = (state) => {
- if (state.isLoading) {
- return LOADING;
- }
-
- if (state.hasError || state.status === STATUS_FAILED) {
- return ERROR;
- }
-
- return SUCCESS;
-};
-
-export const shouldRenderIssuesList = (state) =>
- Object.values(state.report).some((x) => Array.isArray(x) && x.length > 0);
-
-// We could just map state, but we're going to iterate in the future
-// to add notes and warnings to these issue lists, so I'm going to
-// keep these as getters
-export const unresolvedIssues = (state) => state.report.existing_errors;
-export const resolvedIssues = (state) => state.report.resolved_errors;
-export const newIssues = (state) => state.report.new_errors;
diff --git a/app/assets/javascripts/reports/accessibility_report/store/index.js b/app/assets/javascripts/reports/accessibility_report/store/index.js
deleted file mode 100644
index 5bfcd69edec..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/store/index.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
-import * as actions from './actions';
-import * as getters from './getters';
-import mutations from './mutations';
-import state from './state';
-
-Vue.use(Vuex);
-
-export const getStoreConfig = (initialState) => ({
- actions,
- getters,
- mutations,
- state: state(initialState),
-});
-
-export default (initialState) => new Vuex.Store(getStoreConfig(initialState));
diff --git a/app/assets/javascripts/reports/accessibility_report/store/mutation_types.js b/app/assets/javascripts/reports/accessibility_report/store/mutation_types.js
deleted file mode 100644
index 22e2330e1ea..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/store/mutation_types.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export const SET_ENDPOINT = 'SET_ENDPOINT';
-
-export const REQUEST_REPORT = 'REQUEST_REPORT';
-export const RECEIVE_REPORT_SUCCESS = 'RECEIVE_REPORT_SUCCESS';
-export const RECEIVE_REPORT_ERROR = 'RECEIVE_REPORT_ERROR';
diff --git a/app/assets/javascripts/reports/accessibility_report/store/mutations.js b/app/assets/javascripts/reports/accessibility_report/store/mutations.js
deleted file mode 100644
index 20d3e5be9a3..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/store/mutations.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import * as types from './mutation_types';
-
-export default {
- [types.SET_ENDPOINT](state, endpoint) {
- state.endpoint = endpoint;
- },
- [types.REQUEST_REPORT](state) {
- state.isLoading = true;
- },
- [types.RECEIVE_REPORT_SUCCESS](state, report) {
- state.hasError = false;
- state.isLoading = false;
- state.report = report;
- },
- [types.RECEIVE_REPORT_ERROR](state) {
- state.isLoading = false;
- state.hasError = true;
- state.report = {};
- },
-};
diff --git a/app/assets/javascripts/reports/accessibility_report/store/state.js b/app/assets/javascripts/reports/accessibility_report/store/state.js
deleted file mode 100644
index 2a4cefea5e6..00000000000
--- a/app/assets/javascripts/reports/accessibility_report/store/state.js
+++ /dev/null
@@ -1,28 +0,0 @@
-export default (initialState = {}) => ({
- endpoint: initialState.endpoint || '',
-
- isLoading: initialState.isLoading || false,
- hasError: initialState.hasError || false,
-
- /**
- * Report will have the following format:
- * {
- * status: {String},
- * summary: {
- * total: {Number},
- * resolved: {Number},
- * errored: {Number},
- * },
- * existing_errors: {Array.<Object>},
- * existing_notes: {Array.<Object>},
- * existing_warnings: {Array.<Object>},
- * new_errors: {Array.<Object>},
- * new_notes: {Array.<Object>},
- * new_warnings: {Array.<Object>},
- * resolved_errors: {Array.<Object>},
- * resolved_notes: {Array.<Object>},
- * resolved_warnings: {Array.<Object>},
- * }
- */
- report: initialState.report || {},
-});
diff --git a/app/assets/javascripts/reports/components/issue_body.js b/app/assets/javascripts/reports/components/issue_body.js
index 04e72809e62..a76a6f45c07 100644
--- a/app/assets/javascripts/reports/components/issue_body.js
+++ b/app/assets/javascripts/reports/components/issue_body.js
@@ -1,14 +1,11 @@
import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
export const components = {
- AccessibilityIssueBody: () =>
- import('../accessibility_report/components/accessibility_issue_body.vue'),
CodequalityIssueBody: () => import('../codequality_report/components/codequality_issue_body.vue'),
TestIssueBody: () => import('../grouped_test_report/components/test_issue_body.vue'),
};
export const componentNames = {
- AccessibilityIssueBody: 'AccessibilityIssueBody',
CodequalityIssueBody: 'CodequalityIssueBody',
TestIssueBody: 'TestIssueBody',
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue b/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue
index f3186723a49..0e858fb30e6 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue
@@ -77,6 +77,8 @@ export default {
<div class="gl-display-flex">
<gl-dropdown
v-if="tertiaryButtons.length"
+ v-gl-tooltip
+ :title="__('Options')"
:text="dropdownLabel"
icon="ellipsis_v"
no-caret
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
index 5e89d28ee50..c5ea336bd96 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
@@ -537,130 +537,148 @@ export default {
<div class="mr-widget-body mr-widget-body-ready-merge media mr-widget-body-line-height-1">
<div class="media-body">
<div class="mr-widget-body-controls gl-display-flex gl-align-items-center gl-flex-wrap">
- <gl-button-group v-if="shouldShowMergeControls" class="gl-align-self-start">
- <gl-button
- size="medium"
- category="primary"
- class="accept-merge-request"
- data-testid="merge-button"
- variant="confirm"
- :disabled="isMergeButtonDisabled"
- :loading="isMakingRequest"
- data-qa-selector="merge_button"
- @click="handleMergeButtonClick(isAutoMergeAvailable)"
- >{{ mergeButtonText }}</gl-button
- >
- <gl-dropdown
- v-if="shouldShowMergeImmediatelyDropdown"
- v-gl-tooltip.hover.focus="__('Select merge moment')"
- :disabled="isMergeButtonDisabled"
- variant="confirm"
- data-qa-selector="merge_moment_dropdown"
- toggle-class="btn-icon js-merge-moment"
- >
- <template #button-content>
- <gl-icon name="chevron-down" class="mr-0" />
- <span class="sr-only">{{ __('Select merge moment') }}</span>
- </template>
- <gl-dropdown-item
- icon-name="warning"
- button-class="accept-merge-request js-merge-immediately-button"
- data-qa-selector="merge_immediately_menu_item"
- @click="handleMergeImmediatelyButtonClick"
+ <template v-if="shouldShowMergeControls">
+ <div class="gl-display-flex gl-align-items-center gl-flex-wrap gl-w-full gl-mb-5">
+ <gl-form-checkbox
+ v-if="canRemoveSourceBranch"
+ id="remove-source-branch-input"
+ v-model="removeSourceBranch"
+ :disabled="isRemoveSourceBranchButtonDisabled"
+ class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center gl-mr-5"
>
- {{ __('Merge immediately') }}
- </gl-dropdown-item>
- <merge-immediately-confirmation-dialog
- ref="confirmationDialog"
- :docs-url="mr.mergeImmediatelyDocsPath"
- @mergeImmediately="onMergeImmediatelyConfirmation"
+ {{ __('Delete source branch') }}
+ </gl-form-checkbox>
+
+ <!-- Placeholder for EE extension of this component -->
+ <squash-before-merge
+ v-if="shouldShowSquashBeforeMerge"
+ v-model="squashBeforeMerge"
+ :help-path="mr.squashBeforeMergeHelpPath"
+ :is-disabled="isSquashReadOnly"
+ class="gl-mr-5"
/>
- </gl-dropdown>
- <merge-train-failed-pipeline-confirmation-dialog
- :visible="isPipelineFailedModalVisibleMergeTrain"
- @startMergeTrain="onStartMergeTrainConfirmation"
- @cancel="isPipelineFailedModalVisibleMergeTrain = false"
- />
- <merge-failed-pipeline-confirmation-dialog
- :visible="isPipelineFailedModalVisibleNormalMerge"
- @mergeWithFailedPipeline="onMergeWithFailedPipelineConfirmation"
- @cancel="isPipelineFailedModalVisibleNormalMerge = false"
- />
- </gl-button-group>
- <merge-train-helper-icon v-if="shouldRenderMergeTrainHelperIcon" class="gl-mx-3" />
- <div
- v-if="shouldShowMergeControls"
- class="gl-display-flex gl-align-items-center gl-flex-wrap gl-w-full gl-order-n1 gl-mb-5"
- >
- <gl-form-checkbox
- v-if="canRemoveSourceBranch"
- id="remove-source-branch-input"
- v-model="removeSourceBranch"
- :disabled="isRemoveSourceBranchButtonDisabled"
- class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center gl-mr-5"
- >
- {{ __('Delete source branch') }}
- </gl-form-checkbox>
-
- <!-- Placeholder for EE extension of this component -->
- <squash-before-merge
- v-if="shouldShowSquashBeforeMerge"
- v-model="squashBeforeMerge"
- :help-path="mr.squashBeforeMergeHelpPath"
- :is-disabled="isSquashReadOnly"
- class="gl-mr-5"
- />
-
- <gl-form-checkbox
- v-if="shouldShowSquashEdit || shouldShowMergeEdit"
- v-model="editCommitMessage"
- data-testid="widget_edit_commit_message"
- class="gl-display-flex gl-align-items-center"
- >
- {{ __('Edit commit message') }}
- </gl-form-checkbox>
- </div>
- <div
- v-if="editCommitMessage"
- class="gl-w-full gl-order-n1"
- data-testid="edit_commit_message"
- >
- <ul class="border-top commits-list flex-list gl-list-style-none gl-p-0 gl-pt-4">
- <commit-edit
- v-if="shouldShowSquashEdit"
- :value="squashCommitMessage"
- :label="__('Squash commit message')"
- input-id="squash-message-edit"
- class="gl-m-0! gl-p-0!"
- @input="setSquashCommitMessage"
+
+ <gl-form-checkbox
+ v-if="shouldShowSquashEdit || shouldShowMergeEdit"
+ v-model="editCommitMessage"
+ data-testid="widget_edit_commit_message"
+ class="gl-display-flex gl-align-items-center"
>
- <template #header>
- <commit-message-dropdown :commits="commits" @input="setSquashCommitMessage" />
+ {{ __('Edit commit message') }}
+ </gl-form-checkbox>
+ </div>
+ <div class="gl-w-full gl-text-gray-500 gl-mb-5">
+ <added-commit-message
+ :is-squash-enabled="squashBeforeMerge"
+ :is-fast-forward-enabled="!shouldShowMergeEdit"
+ :commits-count="commitsCount"
+ :target-branch="stateData.targetBranch"
+ />
+ <template v-if="mr.relatedLinks">
+ &middot;
+ <related-links
+ :state="mr.state"
+ :related-links="mr.relatedLinks"
+ :show-assign-to-me="false"
+ :diverged-commits-count="mr.divergedCommitsCount"
+ :target-branch-path="mr.targetBranchPath"
+ class="mr-ready-merge-related-links gl-display-inline"
+ />
+ </template>
+ </div>
+ <div v-if="editCommitMessage" class="gl-w-full" data-testid="edit_commit_message">
+ <ul class="border-top commits-list flex-list gl-list-style-none gl-p-0 gl-pt-4">
+ <commit-edit
+ v-if="shouldShowSquashEdit"
+ :value="squashCommitMessage"
+ :label="__('Squash commit message')"
+ input-id="squash-message-edit"
+ class="gl-m-0! gl-p-0!"
+ @input="setSquashCommitMessage"
+ >
+ <template #header>
+ <commit-message-dropdown :commits="commits" @input="setSquashCommitMessage" />
+ </template>
+ </commit-edit>
+ <commit-edit
+ v-if="shouldShowMergeEdit"
+ :value="commitMessage"
+ :label="__('Merge commit message')"
+ input-id="merge-message-edit"
+ class="gl-m-0! gl-p-0!"
+ @input="setCommitMessage"
+ />
+ <li class="gl-m-0! gl-p-0!">
+ <p class="form-text text-muted">
+ <gl-sprintf :message="commitTemplateHintText">
+ <template #link="{ content }">
+ <gl-link
+ :href="commitTemplateHelpPage"
+ class="inline-link"
+ target="_blank"
+ >
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </li>
+ </ul>
+ </div>
+ <gl-button-group class="gl-align-self-start">
+ <gl-button
+ size="medium"
+ category="primary"
+ class="accept-merge-request"
+ data-testid="merge-button"
+ variant="confirm"
+ :disabled="isMergeButtonDisabled"
+ :loading="isMakingRequest"
+ data-qa-selector="merge_button"
+ @click="handleMergeButtonClick(isAutoMergeAvailable)"
+ >{{ mergeButtonText }}</gl-button
+ >
+ <gl-dropdown
+ v-if="shouldShowMergeImmediatelyDropdown"
+ v-gl-tooltip.hover.focus="__('Select merge moment')"
+ :disabled="isMergeButtonDisabled"
+ variant="confirm"
+ data-qa-selector="merge_moment_dropdown"
+ toggle-class="btn-icon js-merge-moment"
+ >
+ <template #button-content>
+ <gl-icon name="chevron-down" class="mr-0" />
+ <span class="sr-only">{{ __('Select merge moment') }}</span>
</template>
- </commit-edit>
- <commit-edit
- v-if="shouldShowMergeEdit"
- :value="commitMessage"
- :label="__('Merge commit message')"
- input-id="merge-message-edit"
- class="gl-m-0! gl-p-0!"
- @input="setCommitMessage"
+ <gl-dropdown-item
+ icon-name="warning"
+ button-class="accept-merge-request js-merge-immediately-button"
+ data-qa-selector="merge_immediately_menu_item"
+ @click="handleMergeImmediatelyButtonClick"
+ >
+ {{ __('Merge immediately') }}
+ </gl-dropdown-item>
+ <merge-immediately-confirmation-dialog
+ ref="confirmationDialog"
+ :docs-url="mr.mergeImmediatelyDocsPath"
+ @mergeImmediately="onMergeImmediatelyConfirmation"
+ />
+ </gl-dropdown>
+ <merge-train-failed-pipeline-confirmation-dialog
+ :visible="isPipelineFailedModalVisibleMergeTrain"
+ @startMergeTrain="onStartMergeTrainConfirmation"
+ @cancel="isPipelineFailedModalVisibleMergeTrain = false"
/>
- <li class="gl-m-0! gl-p-0!">
- <p class="form-text text-muted">
- <gl-sprintf :message="commitTemplateHintText">
- <template #link="{ content }">
- <gl-link :href="commitTemplateHelpPage" class="inline-link" target="_blank">
- {{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
- </p>
- </li>
- </ul>
- </div>
+ <merge-failed-pipeline-confirmation-dialog
+ :visible="isPipelineFailedModalVisibleNormalMerge"
+ @mergeWithFailedPipeline="onMergeWithFailedPipelineConfirmation"
+ @cancel="isPipelineFailedModalVisibleNormalMerge = false"
+ />
+ </gl-button-group>
+ <merge-train-helper-icon v-if="shouldRenderMergeTrainHelperIcon" class="gl-mx-3" />
+ </template>
<div
- v-if="!shouldShowMergeControls"
+ v-else
class="gl-w-full gl-order-n1 mr-widget-merge-details"
data-qa-selector="merged_status_content"
>
@@ -669,12 +687,10 @@ export default {
</p>
<ul class="gl-pl-4 gl-mb-0 gl-ml-3 gl-text-gray-600">
<li v-if="sourceHasDivergedFromTarget" class="gl-line-height-normal">
- <gl-sprintf
- :message="s__('mrWidget|The source branch is %{link} the target branch')"
- >
+ <gl-sprintf :message="$options.i18n.sourceDivergedFromTargetText">
<template #link>
<gl-link :href="mr.targetBranchPath">{{
- n__('%d commit behind', '%d commits behind', mr.divergedCommitsCount)
+ $options.i18n.divergedCommits(mr.divergedCommitsCount)
}}</gl-link>
</template>
</gl-sprintf>
@@ -703,37 +719,6 @@ export default {
</li>
</ul>
</div>
- <div
- v-else
- :class="{ 'gl-mb-5': shouldShowMergeControls }"
- class="gl-w-full gl-order-n1 gl-text-gray-500"
- >
- <p v-if="sourceHasDivergedFromTarget" class="gl-display-inline gl-m-0">
- <gl-sprintf :message="$options.i18n.sourceDivergedFromTargetText">
- <template #link>
- <gl-link :href="mr.targetBranchPath">{{
- $options.i18n.divergedCommits(mr.divergedCommitsCount)
- }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
- <template v-if="sourceHasDivergedFromTarget"> &middot; </template>
- <added-commit-message
- :is-squash-enabled="squashBeforeMerge"
- :is-fast-forward-enabled="!shouldShowMergeEdit"
- :commits-count="commitsCount"
- :target-branch="stateData.targetBranch"
- />
- <template v-if="mr.relatedLinks">
- &middot;
- <related-links
- :state="mr.state"
- :related-links="mr.relatedLinks"
- :show-assign-to-me="false"
- class="mr-ready-merge-related-links gl-display-inline"
- />
- </template>
- </div>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue
deleted file mode 100644
index 18fdb29ba54..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue
+++ /dev/null
@@ -1,137 +0,0 @@
-<script>
-import { GlSkeletonLoader, GlSprintf } from '@gitlab/ui';
-import axios from '~/lib/utils/axios_utils';
-import Poll from '~/lib/utils/poll';
-import { n__ } from '~/locale';
-import MrWidgetExpanableSection from '../mr_widget_expandable_section.vue';
-import TerraformPlan from './terraform_plan.vue';
-
-export default {
- name: 'MRWidgetTerraformContainer',
- components: {
- GlSkeletonLoader,
- GlSprintf,
- MrWidgetExpanableSection,
- TerraformPlan,
- },
- props: {
- endpoint: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- loading: true,
- plansObject: {},
- poll: null,
- };
- },
- computed: {
- inValidPlanCountText() {
- if (this.numberOfInvalidPlans === 0) {
- return null;
- }
-
- return n__(
- 'Terraform|%{number} Terraform report failed to generate',
- 'Terraform|%{number} Terraform reports failed to generate',
- this.numberOfInvalidPlans,
- );
- },
- numberOfInvalidPlans() {
- return Object.values(this.plansObject).filter((plan) => plan.tf_report_error).length;
- },
- numberOfPlans() {
- return Object.keys(this.plansObject).length;
- },
- numberOfValidPlans() {
- return this.numberOfPlans - this.numberOfInvalidPlans;
- },
- validPlanCountText() {
- if (this.numberOfValidPlans === 0) {
- return null;
- }
-
- return n__(
- 'Terraform|%{number} Terraform report was generated in your pipelines',
- 'Terraform|%{number} Terraform reports were generated in your pipelines',
- this.numberOfValidPlans,
- );
- },
- },
- created() {
- this.fetchPlans();
- },
- beforeDestroy() {
- this.poll.stop();
- },
- methods: {
- fetchPlans() {
- this.loading = true;
-
- this.poll = new Poll({
- resource: {
- fetchPlans: () => axios.get(this.endpoint),
- },
- data: this.endpoint,
- method: 'fetchPlans',
- successCallback: ({ data }) => {
- this.plansObject = data;
-
- if (this.numberOfPlans > 0) {
- this.loading = false;
- this.poll.stop();
- }
- },
- errorCallback: () => {
- this.plansObject = { bad_plan: { tf_report_error: 'api_error' } };
- this.loading = false;
- this.poll.stop();
- },
- });
-
- this.poll.makeRequest();
- },
- },
-};
-</script>
-
-<template>
- <section class="mr-widget-section">
- <div v-if="loading" class="mr-widget-body">
- <gl-skeleton-loader />
- </div>
-
- <mr-widget-expanable-section v-else>
- <template #header>
- <div
- data-testid="terraform-header-text"
- class="gl-flex-grow-1 gl-display-flex gl-flex-direction-column"
- >
- <p v-if="validPlanCountText" class="gl-m-0">
- <gl-sprintf :message="validPlanCountText">
- <template #number>
- <strong>{{ numberOfValidPlans }}</strong>
- </template>
- </gl-sprintf>
- </p>
-
- <p v-if="inValidPlanCountText" class="gl-m-0">
- <gl-sprintf :message="inValidPlanCountText">
- <template #number>
- <strong>{{ numberOfInvalidPlans }}</strong>
- </template>
- </gl-sprintf>
- </p>
- </div>
- </template>
-
- <template #content>
- <div class="mr-widget-body gl-pb-1">
- <terraform-plan v-for="(plan, key) in plansObject" :key="key" :plan="plan" />
- </div>
- </template>
- </mr-widget-expanable-section>
- </section>
-</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue b/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue
deleted file mode 100644
index 1e5f7361966..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue
+++ /dev/null
@@ -1,119 +0,0 @@
-<script>
-import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
-import { s__ } from '~/locale';
-
-export default {
- name: 'TerraformPlan',
- components: {
- GlIcon,
- GlLink,
- GlSprintf,
- },
- props: {
- plan: {
- required: true,
- type: Object,
- },
- },
- i18n: {
- changes: s__(
- 'Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete',
- ),
- generationErrored: s__('Terraform|Generating the report caused an error.'),
- namedReportFailed: s__('Terraform|The job %{name} failed to generate a report.'),
- namedReportGenerated: s__('Terraform|The job %{name} generated a report.'),
- reportFailed: s__('Terraform|A report failed to generate.'),
- reportGenerated: s__('Terraform|A report was generated in your pipelines.'),
- },
- computed: {
- addNum() {
- return Number(this.plan.create);
- },
- changeNum() {
- return Number(this.plan.update);
- },
- deleteNum() {
- return Number(this.plan.delete);
- },
- iconType() {
- return this.validPlanValues ? 'doc-changes' : 'warning';
- },
- reportChangeText() {
- if (this.validPlanValues) {
- return this.$options.i18n.changes;
- }
-
- return this.$options.i18n.generationErrored;
- },
- reportHeaderText() {
- if (this.validPlanValues) {
- return this.plan.job_name
- ? this.$options.i18n.namedReportGenerated
- : this.$options.i18n.reportGenerated;
- }
-
- return this.plan.job_name
- ? this.$options.i18n.namedReportFailed
- : this.$options.i18n.reportFailed;
- },
- validPlanValues() {
- return this.addNum + this.changeNum + this.deleteNum >= 0;
- },
- },
-};
-</script>
-
-<template>
- <div class="gl-display-flex gl-pb-3">
- <span
- class="gl-display-flex gl-align-items-center gl-justify-content-center gl-align-self-start gl-px-2"
- >
- <gl-icon :name="iconType" :size="16" data-testid="change-type-icon" />
- </span>
-
- <div class="gl-display-flex gl-flex-grow-1 gl-flex-direction-column flex-md-row gl-pl-3">
- <div class="gl-flex-grow-1 gl-display-flex gl-flex-direction-column gl-pr-3">
- <p class="gl-mb-3 gl-line-height-normal">
- <gl-sprintf :message="reportHeaderText">
- <template #name>
- <strong>{{ plan.job_name }}</strong>
- </template>
- </gl-sprintf>
- </p>
-
- <p class="gl-mb-3 gl-line-height-normal">
- <gl-sprintf :message="reportChangeText">
- <template #addNum>
- <strong>{{ addNum }}</strong>
- </template>
-
- <template #changeNum>
- <strong>{{ changeNum }}</strong>
- </template>
-
- <template #deleteNum>
- <strong>{{ deleteNum }}</strong>
- </template>
- </gl-sprintf>
- </p>
- </div>
-
- <div>
- <gl-link
- v-if="plan.job_path"
- :href="plan.job_path"
- target="_blank"
- data-testid="terraform-report-link"
- data-track-action="click_terraform_mr_plan_button"
- data-track-label="mr_widget_terraform_mr_plan_button"
- data-track-property="terraform_mr_plan_button"
- class="btn btn-sm"
- rel="noopener"
- >
- {{ __('View full log') }}
- <gl-icon name="external-link" />
- </gl-link>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index 4ff2643057f..2d9549fdada 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -86,9 +86,6 @@ export default {
import('../reports/codequality_report/grouped_codequality_reports_app.vue'),
GroupedTestReportsApp: () =>
import('../reports/grouped_test_report/grouped_test_reports_app.vue'),
- TerraformPlan: () => import('./components/terraform/mr_widget_terraform_container.vue'),
- GroupedAccessibilityReportsApp: () =>
- import('../reports/accessibility_report/grouped_accessibility_reports_app.vue'),
MrWidgetApprovals,
SecurityReportsApp: () => import('~/vue_shared/security_reports/security_reports_app.vue'),
MergeChecksFailed: () => import('./components/states/merge_checks_failed.vue'),
@@ -218,12 +215,6 @@ export default {
hasAlerts() {
return this.hasMergeError || this.showMergePipelineForkWarning;
},
- shouldShowExtension() {
- return (
- window.gon?.features?.refactorMrWidgetsExtensions ||
- window.gon?.features?.refactorMrWidgetsExtensionsUser
- );
- },
shouldShowSecurityExtension() {
return window.gon?.features?.refactorSecurityExtension;
},
@@ -518,12 +509,12 @@ export default {
this.mr.isDismissedSuggestPipeline = true;
},
registerTerraformPlans() {
- if (this.shouldRenderTerraformPlans && this.shouldShowExtension) {
+ if (this.shouldRenderTerraformPlans) {
registerExtension(terraformExtension);
}
},
registerAccessibilityExtension() {
- if (this.shouldShowAccessibilityReport && this.shouldShowExtension) {
+ if (this.shouldShowAccessibilityReport) {
registerExtension(accessibilityExtension);
}
},
@@ -627,16 +618,6 @@ export default {
:pipeline-path="mr.pipeline.path"
/>
- <terraform-plan
- v-if="mr.terraformReportsPath && !shouldShowExtension"
- :endpoint="mr.terraformReportsPath"
- />
-
- <grouped-accessibility-reports-app
- v-if="shouldShowAccessibilityReport && !shouldShowExtension"
- :endpoint="mr.accessibilityReportPath"
- />
-
<div class="mr-widget-section" data-qa-selector="mr_widget_content">
<component :is="componentName" :mr="mr" :service="service" />
<ready-to-merge
diff --git a/app/assets/javascripts/vue_shared/components/url_sync.vue b/app/assets/javascripts/vue_shared/components/url_sync.vue
index 925c6008836..bd5b7b77017 100644
--- a/app/assets/javascripts/vue_shared/components/url_sync.vue
+++ b/app/assets/javascripts/vue_shared/components/url_sync.vue
@@ -1,6 +1,9 @@
<script>
import { historyPushState } from '~/lib/utils/common_utils';
-import { mergeUrlParams } from '~/lib/utils/url_utility';
+import { mergeUrlParams, setUrlParams } from '~/lib/utils/url_utility';
+
+export const URL_SET_PARAMS_STRATEGY = 'set';
+export const URL_MERGE_PARAMS_STRATEGY = 'merge';
/**
* Renderless component to update the query string,
@@ -15,6 +18,12 @@ export default {
required: false,
default: null,
},
+ urlParamsUpdateStrategy: {
+ type: String,
+ required: false,
+ default: URL_MERGE_PARAMS_STRATEGY,
+ validator: (value) => [URL_MERGE_PARAMS_STRATEGY, URL_SET_PARAMS_STRATEGY].includes(value),
+ },
},
watch: {
query: {
@@ -29,7 +38,11 @@ export default {
},
methods: {
updateQuery(newQuery) {
- historyPushState(mergeUrlParams(newQuery, window.location.href, { spreadArrays: true }));
+ const url =
+ this.urlParamsUpdateStrategy === URL_SET_PARAMS_STRATEGY
+ ? setUrlParams(this.query, window.location.href, true)
+ : mergeUrlParams(newQuery, window.location.href, { spreadArrays: true });
+ historyPushState(url);
},
},
render() {
diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss
index 050cc2a9fa8..b2fbce7cb4b 100644
--- a/app/assets/stylesheets/page_bundles/merge_requests.scss
+++ b/app/assets/stylesheets/page_bundles/merge_requests.scss
@@ -720,10 +720,6 @@ $tabs-holder-z-index: 250;
}
@include media-breakpoint-down(xs) {
- p {
- font-size: 13px;
- }
-
.btn-grouped {
float: none;
margin-right: 0;
diff --git a/app/controllers/projects/incidents_controller.rb b/app/controllers/projects/incidents_controller.rb
index 57892a45ff2..089ee860ea6 100644
--- a/app/controllers/projects/incidents_controller.rb
+++ b/app/controllers/projects/incidents_controller.rb
@@ -7,7 +7,6 @@ class Projects::IncidentsController < Projects::ApplicationController
before_action :authorize_read_issue!
before_action :load_incident, only: [:show]
before_action do
- push_frontend_feature_flag(:incident_timeline, @project)
push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?)
push_force_frontend_feature_flag(:work_items_mvc_2, @project&.work_items_mvc_2_feature_flag_enabled?)
push_frontend_feature_flag(:work_items_hierarchy, @project)
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 65c23d52271..5b1117c0224 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -41,7 +41,6 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :authorize_download_code!, only: [:related_branches]
before_action do
- push_frontend_feature_flag(:incident_timeline, project)
push_frontend_feature_flag(:preserve_unchanged_markdown, project)
push_frontend_feature_flag(:content_editor_on_issues, project)
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 3e226131d75..d7319b0726f 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -34,7 +34,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action only: [:show] do
push_frontend_feature_flag(:merge_request_widget_graphql, project)
push_frontend_feature_flag(:core_security_mr_widget_counts, project)
- push_frontend_feature_flag(:refactor_mr_widgets_extensions, project)
push_frontend_feature_flag(:refactor_code_quality_extension, project)
push_frontend_feature_flag(:refactor_mr_widget_test_summary, project)
push_frontend_feature_flag(:issue_assignees_widget, @project)
diff --git a/app/services/bulk_imports/create_pipeline_trackers_service.rb b/app/services/bulk_imports/create_pipeline_trackers_service.rb
index af97aec09b5..ca297ef3774 100644
--- a/app/services/bulk_imports/create_pipeline_trackers_service.rb
+++ b/app/services/bulk_imports/create_pipeline_trackers_service.rb
@@ -53,7 +53,7 @@ module BulkImports
def log_skipped_pipeline(pipeline, minimum_version, maximum_version)
logger.info(
message: 'Pipeline skipped as source instance version not compatible with pipeline',
- entity_id: entity.id,
+ bulk_import_entity_id: entity.id,
pipeline_name: pipeline[:pipeline],
minimum_source_version: minimum_version,
maximum_source_version: maximum_version,
diff --git a/app/services/incident_management/timeline_events/create_service.rb b/app/services/incident_management/timeline_events/create_service.rb
index 40ce9097c88..5422b4ad6d2 100644
--- a/app/services/incident_management/timeline_events/create_service.rb
+++ b/app/services/incident_management/timeline_events/create_service.rb
@@ -109,7 +109,6 @@ module IncidentManagement
def add_system_note(timeline_event)
return if auto_created
- return unless Feature.enabled?(:incident_timeline, project)
SystemNoteService.add_timeline_event(timeline_event)
end
diff --git a/app/services/incident_management/timeline_events/destroy_service.rb b/app/services/incident_management/timeline_events/destroy_service.rb
index 90e95ae8869..e1c6bbbdb85 100644
--- a/app/services/incident_management/timeline_events/destroy_service.rb
+++ b/app/services/incident_management/timeline_events/destroy_service.rb
@@ -30,8 +30,6 @@ module IncidentManagement
attr_reader :project, :timeline_event, :user, :incident
def add_system_note(incident, user)
- return unless Feature.enabled?(:incident_timeline, project)
-
SystemNoteService.delete_timeline_event(incident, user)
end
end
diff --git a/app/services/incident_management/timeline_events/update_service.rb b/app/services/incident_management/timeline_events/update_service.rb
index 5c5de4717bc..012e2f0e260 100644
--- a/app/services/incident_management/timeline_events/update_service.rb
+++ b/app/services/incident_management/timeline_events/update_service.rb
@@ -38,8 +38,6 @@ module IncidentManagement
end
def add_system_note(timeline_event)
- return unless Feature.enabled?(:incident_timeline, incident.project)
-
changes = was_changed(timeline_event)
return if changes == :none
diff --git a/app/views/admin/application_settings/_package_registry.html.haml b/app/views/admin/application_settings/_package_registry.html.haml
index 4bdfa5bfe83..3506038ca68 100644
--- a/app/views/admin/application_settings/_package_registry.html.haml
+++ b/app/views/admin/application_settings/_package_registry.html.haml
@@ -20,12 +20,12 @@
%ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs.mb-3
- @plans.each_with_index do |plan, index|
%li
- = link_to admin_plan_limits_path(anchor: 'js-package-settings'), data: { target: "div#plan#{index}", action: "plan#{index}", toggle: 'tab'}, class: index == 0 ? 'active': '' do
+ = link_to admin_plan_limits_path(anchor: 'js-package-settings'), data: { target: "div#plan-package#{index}", action: "plan#{index}", toggle: 'tab'}, class: index == 0 ? 'active': '' do
= plan.name.capitalize
.tab-content
- @plans.each_with_index do |plan, index|
- .tab-pane{ :id => "plan#{index}", class: index == 0 ? 'active': '' }
- = form_for plan.actual_limits, url: admin_plan_limits_path(anchor: 'js-package-settings'), html: { class: 'fieldset-form' }, method: :post do |f|
+ .tab-pane{ :id => "plan-package#{index}", class: index == 0 ? 'active': '' }
+ = gitlab_ui_form_for plan.actual_limits, url: admin_plan_limits_path(anchor: 'js-package-settings'), html: { class: 'fieldset-form' }, method: :post do |f|
= form_errors(plan)
%fieldset
= f.hidden_field(:plan_id, value: plan.id)
@@ -53,4 +53,4 @@
.form-group
= f.label :generic_packages_max_file_size, _('Generic package file size in bytes'), class: 'label-bold'
= f.number_field :generic_packages_max_file_size, class: 'form-control gl-form-input'
- = f.submit _('Save %{name} size limits').html_safe % { name: plan.name.capitalize }, class: 'btn gl-button btn-confirm'
+ = f.submit _('Save %{name} size limits').html_safe % { name: plan.name.capitalize }, pajamas_button: true
diff --git a/app/views/admin/application_settings/_terms.html.haml b/app/views/admin/application_settings/_terms.html.haml
index a4b6e061c43..8da441d5245 100644
--- a/app/views/admin/application_settings/_terms.html.haml
+++ b/app/views/admin/application_settings/_terms.html.haml
@@ -11,4 +11,4 @@
.form-text.text-muted
= _("Markdown supported.")
= link_to _('What is Markdown?'), help_page_path('user/markdown.md'), target: '_blank', rel: 'noopener noreferrer'
- = f.submit _("Save changes"), class: "gl-button btn btn-confirm"
+ = f.submit _("Save changes"), pajamas_button: true
diff --git a/app/views/admin/deploy_keys/edit.html.haml b/app/views/admin/deploy_keys/edit.html.haml
index 12a1c0c3de2..acdf503727d 100644
--- a/app/views/admin/deploy_keys/edit.html.haml
+++ b/app/views/admin/deploy_keys/edit.html.haml
@@ -3,8 +3,8 @@
%hr
%div
- = form_for [:admin, @deploy_key], html: { class: 'deploy-key-form' } do |f|
+ = gitlab_ui_form_for [:admin, @deploy_key], html: { class: 'deploy-key-form' } do |f|
= render partial: 'shared/deploy_keys/form', locals: { form: f, deploy_key: @deploy_key }
.form-actions
- = f.submit _('Save changes'), class: 'btn gl-button btn-confirm'
+ = f.submit _('Save changes'), pajamas_button: true
= link_to _('Cancel'), admin_deploy_keys_path, class: 'btn gl-button btn-default btn-cancel'
diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml
index 69e9e4260b4..7adba0d023b 100644
--- a/app/views/admin/groups/_form.html.haml
+++ b/app/views/admin/groups/_form.html.haml
@@ -35,10 +35,10 @@
= c.body do
= render 'shared/group_tips'
.gl-mt-5
- = f.submit _('Create group'), class: "gl-button btn btn-confirm"
+ = f.submit _('Create group'), pajamas_button: true
= link_to _('Cancel'), admin_groups_path, class: "gl-button btn btn-default btn-cancel"
- else
.gl-mt-5
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = f.submit _('Save changes'), data: { qa_selector: 'save_changes_button' }, pajamas_button: true
= link_to _('Cancel'), admin_group_path(@group), class: "gl-button btn btn-cancel"
diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml
index 393f627aa99..0476193c2cb 100644
--- a/app/views/projects/hooks/index.html.haml
+++ b/app/views/projects/hooks/index.html.haml
@@ -9,6 +9,6 @@
.col-lg-8.gl-mb-3
= gitlab_ui_form_for @hook, as: :hook, url: polymorphic_path([@project, :hooks]) do |f|
= render partial: 'shared/web_hooks/form', locals: { form: f, hook: @hook }
- = f.submit 'Add webhook', class: 'gl-button btn btn-confirm'
+ = f.submit 'Add webhook', pajamas_button: true
= render 'shared/web_hooks/index', hooks: @hooks, hook_class: @hook.class
diff --git a/app/workers/bulk_imports/entity_worker.rb b/app/workers/bulk_imports/entity_worker.rb
index f6b1c693fe4..5f94b58f4c6 100644
--- a/app/workers/bulk_imports/entity_worker.rb
+++ b/app/workers/bulk_imports/entity_worker.rb
@@ -15,7 +15,7 @@ module BulkImports
if stage_running?(entity_id, current_stage)
logger.info(
structured_payload(
- entity_id: entity_id,
+ bulk_import_entity_id: entity_id,
current_stage: current_stage,
message: 'Stage running'
)
@@ -26,7 +26,7 @@ module BulkImports
logger.info(
structured_payload(
- entity_id: entity_id,
+ bulk_import_entity_id: entity_id,
current_stage: current_stage,
message: 'Stage starting'
)
@@ -42,13 +42,13 @@ module BulkImports
rescue StandardError => e
logger.error(
structured_payload(
- entity_id: entity_id,
+ bulk_import_entity_id: entity_id,
current_stage: current_stage,
message: e.message
)
)
- Gitlab::ErrorTracking.track_exception(e, entity_id: entity_id)
+ Gitlab::ErrorTracking.track_exception(e, bulk_import_entity_id: entity_id)
end
private
diff --git a/app/workers/bulk_imports/pipeline_worker.rb b/app/workers/bulk_imports/pipeline_worker.rb
index 435e1095667..6e2387b3fb5 100644
--- a/app/workers/bulk_imports/pipeline_worker.rb
+++ b/app/workers/bulk_imports/pipeline_worker.rb
@@ -19,7 +19,7 @@ module BulkImports
if pipeline_tracker.present?
logger.info(
structured_payload(
- entity_id: pipeline_tracker.entity.id,
+ bulk_import_entity_id: pipeline_tracker.entity.id,
pipeline_name: pipeline_tracker.pipeline_name
)
)
@@ -28,7 +28,7 @@ module BulkImports
else
logger.error(
structured_payload(
- entity_id: entity_id,
+ bulk_import_entity_id: entity_id,
pipeline_tracker_id: pipeline_tracker_id,
message: 'Unstarted pipeline not found'
)
@@ -65,7 +65,7 @@ module BulkImports
logger.error(
structured_payload(
- entity_id: pipeline_tracker.entity.id,
+ bulk_import_entity_id: pipeline_tracker.entity.id,
pipeline_name: pipeline_tracker.pipeline_name,
message: exception.message
)
@@ -73,7 +73,7 @@ module BulkImports
Gitlab::ErrorTracking.track_exception(
exception,
- entity_id: pipeline_tracker.entity.id,
+ bulk_import_entity_id: pipeline_tracker.entity.id,
pipeline_name: pipeline_tracker.pipeline_name
)
@@ -139,7 +139,7 @@ module BulkImports
def retry_tracker(exception)
logger.error(
structured_payload(
- entity_id: pipeline_tracker.entity.id,
+ bulk_import_entity_id: pipeline_tracker.entity.id,
pipeline_name: pipeline_tracker.pipeline_name,
message: "Retrying error: #{exception.message}"
)
@@ -153,7 +153,7 @@ module BulkImports
def skip_tracker
logger.info(
structured_payload(
- entity_id: pipeline_tracker.entity.id,
+ bulk_import_entity_id: pipeline_tracker.entity.id,
pipeline_name: pipeline_tracker.pipeline_name,
message: 'Skipping pipeline due to failed entity'
)
diff --git a/config/feature_flags/development/incident_timeline.yml b/config/feature_flags/development/incident_timeline.yml
deleted file mode 100644
index 587ef8b55e8..00000000000
--- a/config/feature_flags/development/incident_timeline.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: incident_timeline
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80802
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/353426
-milestone: '14.9'
-type: development
-group: group::respond
-default_enabled: true
diff --git a/config/feature_flags/development/refactor_mr_widgets_extensions.yml b/config/feature_flags/development/refactor_mr_widgets_extensions.yml
deleted file mode 100644
index 3f71e786f99..00000000000
--- a/config/feature_flags/development/refactor_mr_widgets_extensions.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: refactor_mr_widgets_extensions
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70993
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341759
-milestone: '14.4'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/refactor_mr_widgets_extensions_user.yml b/config/feature_flags/development/refactor_mr_widgets_extensions_user.yml
deleted file mode 100644
index aa3c2799100..00000000000
--- a/config/feature_flags/development/refactor_mr_widgets_extensions_user.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: refactor_mr_widgets_extensions_user
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70993
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341759
-milestone: '14.4'
-type: development
-group: group::code review
-default_enabled: false
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index 0294e469bad..1e9f20ded55 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -233,8 +233,6 @@ by the `gitlab:artifacts:migrate` Rake task.
To migrate back to local storage:
-1. Set both `direct_upload` and `background_upload` to `false` in `gitlab.rb`, under the artifacts object storage settings.
-1. [Reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure).
1. Run `gitlab-rake gitlab:artifacts:migrate_to_local`.
1. Disable object_storage for artifacts in `gitlab.rb`:
- Set `gitlab_rails['artifacts_object_store_enabled'] = false`.
diff --git a/doc/administration/lfs/index.md b/doc/administration/lfs/index.md
index bb3f3a48f17..1b01c665ab8 100644
--- a/doc/administration/lfs/index.md
+++ b/doc/administration/lfs/index.md
@@ -220,7 +220,6 @@ end
To migrate back to local storage:
-1. Set both `direct_upload` and `background_upload` to `false` under the LFS object storage settings. Don't forget to restart GitLab.
1. Run `rake gitlab:lfs:migrate_to_local` on your console.
1. Disable `object_storage` for LFS objects in `gitlab.rb`. Remember to restart GitLab afterwards.
diff --git a/doc/administration/raketasks/uploads/migrate.md b/doc/administration/raketasks/uploads/migrate.md
index a44ee9b240e..d4ab1012c2a 100644
--- a/doc/administration/raketasks/uploads/migrate.md
+++ b/doc/administration/raketasks/uploads/migrate.md
@@ -171,15 +171,6 @@ keeping in mind the task name in this case is `gitlab:uploads:migrate_to_local`.
To migrate uploads from object storage to local storage:
-1. Disable both `direct_upload` and `background_upload` under `uploads` settings in `gitlab.rb`:
-
- ```ruby
- gitlab_rails['uploads_object_store_direct_upload'] = false
- gitlab_rails['uploads_object_store_background_upload'] = false
- ```
-
- Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure).
-
1. Run the Rake task:
**Omnibus Installation**
diff --git a/doc/operations/incident_management/incident_timeline_events.md b/doc/operations/incident_management/incident_timeline_events.md
index 750f7919b7c..5f98335d7aa 100644
--- a/doc/operations/incident_management/incident_timeline_events.md
+++ b/doc/operations/incident_management/incident_timeline_events.md
@@ -6,11 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Timeline events
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/344059) in GitLab 15.2 [with a flag](../../administration/feature_flags.md) named `incident_timeline`. Enabled by default.
-
-FLAG:
-On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named `incident_timeline`.
-On GitLab.com, this feature is available.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/344059) in GitLab 15.2 [with a flag](../../administration/feature_flags.md) named `incident_timeline`. Enabled by default.
+> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/353426) in GitLab 15.3.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/353426) in GitLab 15.5. [Feature flag 'incident_timeline'](https://gitlab.com/gitlab-org/gitlab/-/issues/343386) removed.
Incident timelines are an important part of record keeping for incidents.
Timelines can show executives and external viewers what happened during an incident,
diff --git a/lib/tasks/gitlab/seed.rake b/lib/tasks/gitlab/seed.rake
index 36761165af5..7b9c57b1876 100644
--- a/lib/tasks/gitlab/seed.rake
+++ b/lib/tasks/gitlab/seed.rake
@@ -35,5 +35,40 @@ namespace :gitlab do
puts "\n#{issues_created} issues created!"
end
end
+
+ task :epics, [:group_full_path, :backfill_weeks, :average_issues_per_week] => :environment do |t, args|
+ args.with_defaults(backfill_weeks: 5, average_issues_per_week: 2)
+
+ groups =
+ if args.group_full_path
+ group = Group.find_by_full_path(args.group_full_path)
+
+ unless group
+ error_message = "Group '#{args.group_full_path}' does not exist!"
+ potential_groups = Group.search(args.group_full_path)
+
+ if potential_groups.present?
+ error_message += " Did you mean '#{potential_groups.first.full_path}'?"
+ end
+
+ puts error_message.color(:red)
+ exit 1
+ end
+
+ [group]
+ else
+ Group.not_mass_generated.find_each
+ end
+
+ groups.each do |group|
+ puts "\nSeeding epics for the '#{group.full_path}' group"
+ seeder = Quality::Seeders::Epics.new(group: group)
+ epics = seeder.seed(
+ backfill_weeks: args.backfill_weeks.to_i,
+ average_issues_per_week: args.average_issues_per_week.to_i
+ )
+ puts "\n#{epics} epics created!"
+ end
+ end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 54ef5345a5c..7f84d6012d4 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -2030,15 +2030,9 @@ msgstr ""
msgid "AccessTokens|Your static object token authenticates you when repository static objects (such as archives or blobs) are served from an external storage."
msgstr ""
-msgid "AccessibilityReport|Learn more"
-msgstr ""
-
msgid "AccessibilityReport|Message: %{message}"
msgstr ""
-msgid "AccessibilityReport|New"
-msgstr ""
-
msgid "AccessibilityReport|The accessibility scanning found an error of the following type: %{code}"
msgstr ""
@@ -33726,11 +33720,6 @@ msgid_plural "Reports|%{recentlyFailed} out of %{failed} failed tests have faile
msgstr[0] ""
msgstr[1] ""
-msgid "Reports|Accessibility scanning detected %d issue for the source branch only"
-msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issue for the source branch only"
msgid_plural "Reports|Accessibility scanning detected %{strong_start}%{number}%{strong_end} issues for the source branch only"
msgstr[0] ""
@@ -38440,9 +38429,6 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
-msgid "StatusCheck| %{failed} failed, and %{pending} pending"
-msgstr ""
-
msgid "StatusCheck|%{failed} failed"
msgstr ""
@@ -38455,9 +38441,6 @@ msgstr ""
msgid "StatusCheck|Add status check"
msgstr ""
-msgid "StatusCheck|All passed"
-msgstr ""
-
msgid "StatusCheck|An error occurred deleting the %{name} status check."
msgstr ""
@@ -38479,9 +38462,6 @@ msgstr ""
msgid "StatusCheck|Failed to load status checks"
msgstr ""
-msgid "StatusCheck|Failed to load status checks."
-msgstr ""
-
msgid "StatusCheck|Invoke an external API as part of the pipeline process."
msgstr ""
@@ -39618,16 +39598,6 @@ msgstr ""
msgid "Terraform|%{name} successfully removed"
msgstr ""
-msgid "Terraform|%{number} Terraform report failed to generate"
-msgid_plural "Terraform|%{number} Terraform reports failed to generate"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "Terraform|%{number} Terraform report was generated in your pipelines"
-msgid_plural "Terraform|%{number} Terraform reports were generated in your pipelines"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "Terraform|%{strong_start}%{number}%{strong_end} Terraform report failed to generate"
msgid_plural "Terraform|%{strong_start}%{number}%{strong_end} Terraform reports failed to generate"
msgstr[0] ""
@@ -39647,12 +39617,6 @@ msgstr ""
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
-msgid "Terraform|A report failed to generate."
-msgstr ""
-
-msgid "Terraform|A report was generated in your pipelines."
-msgstr ""
-
msgid "Terraform|Actions"
msgstr ""
@@ -39740,12 +39704,6 @@ msgstr ""
msgid "Terraform|Terraform reports"
msgstr ""
-msgid "Terraform|The job %{name} failed to generate a report."
-msgstr ""
-
-msgid "Terraform|The job %{name} generated a report."
-msgstr ""
-
msgid "Terraform|The job %{strong_start}%{name}%{strong_end} failed to generate a report."
msgstr ""
@@ -44229,9 +44187,6 @@ msgstr ""
msgid "View full dashboard"
msgstr ""
-msgid "View full log"
-msgstr ""
-
msgid "View group in admin area"
msgstr ""
diff --git a/scripts/lib/glfm/update_specification.rb b/scripts/lib/glfm/update_specification.rb
index 7a89797123b..51ac48a5842 100644
--- a/scripts/lib/glfm/update_specification.rb
+++ b/scripts/lib/glfm/update_specification.rb
@@ -43,7 +43,7 @@ module Glfm
def update_ghfm_spec_md
output("Downloading #{GHFM_SPEC_TXT_URI}...")
- ghfm_spec_txt_uri_io = URI.open(GHFM_SPEC_TXT_URI)
+ ghfm_spec_txt_uri_io = URI.parse(GHFM_SPEC_TXT_URI).open
# Read IO stream into an array of lines for easy processing later
ghfm_spec_lines = ghfm_spec_txt_uri_io.readlines
diff --git a/spec/features/incidents/incident_timeline_events_spec.rb b/spec/features/incidents/incident_timeline_events_spec.rb
index 6db9f87d6f2..ef0eb27d310 100644
--- a/spec/features/incidents/incident_timeline_events_spec.rb
+++ b/spec/features/incidents/incident_timeline_events_spec.rb
@@ -12,7 +12,6 @@ RSpec.describe 'Incident timeline events', :js do
end
before do
- stub_feature_flags(incident_timeline: true)
sign_in(developer)
visit project_issues_incident_path(project, incident)
diff --git a/spec/features/issues/incident_issue_spec.rb b/spec/features/issues/incident_issue_spec.rb
index 509ff7d4023..d6cde466d1b 100644
--- a/spec/features/issues/incident_issue_spec.rb
+++ b/spec/features/issues/incident_issue_spec.rb
@@ -26,7 +26,6 @@ RSpec.describe 'Incident Detail', :js do
context 'when user displays the incident' do
before do
- stub_feature_flags(incident_timeline: project)
project.add_developer(user)
sign_in(user)
@@ -97,20 +96,5 @@ RSpec.describe 'Incident Detail', :js do
end
end
end
-
- context 'when incident_timeline feature flag is disabled' do
- before do
- stub_feature_flags(incident_timeline: false)
-
- visit project_issues_incident_path(project, incident)
- wait_for_requests
- end
-
- it 'does not show Timeline tab' do
- tabs = find('[data-testid="incident-tabs"]')
-
- expect(tabs).not_to have_content('Timeline')
- end
- end
end
end
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index 5a0af17dc15..77ac6fac22f 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -22,8 +22,6 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
project_only_mwps.add_maintainer(user)
sign_in(user)
- stub_feature_flags(refactor_mr_widgets_extensions: false)
- stub_feature_flags(refactor_mr_widgets_extensions_user: false)
stub_feature_flags(refactor_mr_widget_test_summary: false)
end
diff --git a/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js b/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js
index d92aeabba0f..458c1c3f858 100644
--- a/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js
+++ b/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js
@@ -5,7 +5,6 @@ import { trackIncidentDetailsViewsOptions } from '~/incidents/constants';
import DescriptionComponent from '~/issues/show/components/description.vue';
import HighlightBar from '~/issues/show/components/incidents/highlight_bar.vue';
import IncidentTabs from '~/issues/show/components/incidents/incident_tabs.vue';
-import TimelineTab from '~/issues/show/components/incidents/timeline_events_tab.vue';
import INVALID_URL from '~/lib/utils/invalid_url';
import Tracking from '~/tracking';
import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
@@ -38,7 +37,6 @@ describe('Incident Tabs component', () => {
projectId: '',
issuableId: '',
uploadMetricsFeatureAvailable: true,
- glFeatures: { incidentTimeline: true },
},
data() {
return { alert: mockAlert, ...data };
@@ -67,7 +65,6 @@ describe('Incident Tabs component', () => {
const findAlertDetailsComponent = () => wrapper.findComponent(AlertDetailsTable);
const findDescriptionComponent = () => wrapper.findComponent(DescriptionComponent);
const findHighlightBarComponent = () => wrapper.findComponent(HighlightBar);
- const findTimelineTab = () => wrapper.findComponent(TimelineTab);
describe('empty state', () => {
beforeEach(() => {
@@ -128,20 +125,4 @@ describe('Incident Tabs component', () => {
expect(Tracking.event).toHaveBeenCalledWith(category, action);
});
});
-
- describe('incident timeline tab', () => {
- beforeEach(() => {
- mountComponent();
- });
-
- it('renders the timeline tab when feature flag is enabled', () => {
- expect(findTimelineTab().exists()).toBe(true);
- });
-
- it('does not render timeline tab when feature flag is disabled', () => {
- mountComponent({}, { provide: { glFeatures: { incidentTimeline: false } } });
-
- expect(findTimelineTab().exists()).toBe(false);
- });
- });
});
diff --git a/spec/frontend/reports/accessibility_report/components/accessibility_issue_body_spec.js b/spec/frontend/reports/accessibility_report/components/accessibility_issue_body_spec.js
deleted file mode 100644
index d835ca4c733..00000000000
--- a/spec/frontend/reports/accessibility_report/components/accessibility_issue_body_spec.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import { GlBadge } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import AccessibilityIssueBody from '~/reports/accessibility_report/components/accessibility_issue_body.vue';
-
-const issue = {
- name:
- 'The accessibility scanning found 2 errors of the following type: WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent',
- code: 'WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent',
- message: 'This element has insufficient contrast at this conformance level.',
- status: 'failed',
- className: 'spec.test_spec',
- learnMoreUrl: 'https://www.w3.org/TR/WCAG20-TECHS/H91.html',
-};
-
-describe('CustomMetricsForm', () => {
- let wrapper;
-
- const mountComponent = ({ name, code, message, status, className }, isNew = false) => {
- wrapper = shallowMount(AccessibilityIssueBody, {
- propsData: {
- issue: {
- name,
- code,
- message,
- status,
- className,
- },
- isNew,
- },
- });
- };
-
- const findIsNewBadge = () => wrapper.findComponent(GlBadge);
-
- beforeEach(() => {
- mountComponent(issue);
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('Displays the issue message', () => {
- const description = wrapper.findComponent({ ref: 'accessibility-issue-description' }).text();
-
- expect(description).toContain(`Message: ${issue.message}`);
- });
-
- describe('When an issue code is present', () => {
- it('Creates the correct URL for learning more about the issue code', () => {
- const learnMoreUrl = wrapper
- .findComponent({ ref: 'accessibility-issue-learn-more' })
- .attributes('href');
-
- expect(learnMoreUrl).toBe(issue.learnMoreUrl);
- });
- });
-
- describe('When an issue code is not present', () => {
- beforeEach(() => {
- mountComponent({
- ...issue,
- code: undefined,
- });
- });
-
- it('Creates a URL leading to the overview documentation page', () => {
- const learnMoreUrl = wrapper
- .findComponent({ ref: 'accessibility-issue-learn-more' })
- .attributes('href');
-
- expect(learnMoreUrl).toBe('https://www.w3.org/TR/WCAG20-TECHS/Overview.html');
- });
- });
-
- describe('When an issue code does not contain the TECHS code', () => {
- beforeEach(() => {
- mountComponent({
- ...issue,
- code: 'WCAG2AA.Principle4.Guideline4_1.4_1_2',
- });
- });
-
- it('Creates a URL leading to the overview documentation page', () => {
- const learnMoreUrl = wrapper
- .findComponent({ ref: 'accessibility-issue-learn-more' })
- .attributes('href');
-
- expect(learnMoreUrl).toBe('https://www.w3.org/TR/WCAG20-TECHS/Overview.html');
- });
- });
-
- describe('When issue is new', () => {
- beforeEach(() => {
- mountComponent(issue, true);
- });
-
- it('Renders the new badge', () => {
- expect(findIsNewBadge().exists()).toBe(true);
- });
- });
-
- describe('When issue is not new', () => {
- beforeEach(() => {
- mountComponent(issue, false);
- });
-
- it('Does not render the new badge', () => {
- expect(findIsNewBadge().exists()).toBe(false);
- });
- });
-});
diff --git a/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js b/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js
deleted file mode 100644
index 9d3535291eb..00000000000
--- a/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js
+++ /dev/null
@@ -1,125 +0,0 @@
-import { mount } from '@vue/test-utils';
-import Vue from 'vue';
-import Vuex from 'vuex';
-import AccessibilityIssueBody from '~/reports/accessibility_report/components/accessibility_issue_body.vue';
-import GroupedAccessibilityReportsApp from '~/reports/accessibility_report/grouped_accessibility_reports_app.vue';
-import { getStoreConfig } from '~/reports/accessibility_report/store';
-import { mockReport } from './mock_data';
-
-Vue.use(Vuex);
-
-describe('Grouped accessibility reports app', () => {
- let wrapper;
- let mockStore;
-
- const mountComponent = () => {
- wrapper = mount(GroupedAccessibilityReportsApp, {
- store: mockStore,
- propsData: {
- endpoint: 'endpoint.json',
- },
- });
- };
-
- const findHeader = () => wrapper.find('[data-testid="report-section-code-text"]');
-
- beforeEach(() => {
- mockStore = new Vuex.Store({
- ...getStoreConfig(),
- actions: { fetchReport: () => {}, setEndpoint: () => {} },
- });
-
- mountComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('while loading', () => {
- beforeEach(() => {
- mockStore.state.isLoading = true;
- mountComponent();
- });
-
- it('renders loading state', () => {
- expect(findHeader().text()).toEqual('Accessibility scanning results are being parsed');
- });
- });
-
- describe('with error', () => {
- beforeEach(() => {
- mockStore.state.isLoading = false;
- mockStore.state.hasError = true;
- mountComponent();
- });
-
- it('renders error state', () => {
- expect(findHeader().text()).toEqual('Accessibility scanning failed loading results');
- });
- });
-
- describe('with a report', () => {
- describe('with no issues', () => {
- beforeEach(() => {
- mockStore.state.report = {
- summary: {
- errored: 0,
- },
- };
- });
-
- it('renders no issues header', () => {
- expect(findHeader().text()).toContain(
- 'Accessibility scanning detected no issues for the source branch only',
- );
- });
- });
-
- describe('with one issue', () => {
- beforeEach(() => {
- mockStore.state.report = {
- summary: {
- errored: 1,
- },
- };
- });
-
- it('renders one issue header', () => {
- expect(findHeader().text()).toContain(
- 'Accessibility scanning detected 1 issue for the source branch only',
- );
- });
- });
-
- describe('with multiple issues', () => {
- beforeEach(() => {
- mockStore.state.report = {
- summary: {
- errored: 2,
- },
- };
- });
-
- it('renders multiple issues header', () => {
- expect(findHeader().text()).toContain(
- 'Accessibility scanning detected 2 issues for the source branch only',
- );
- });
- });
-
- describe('with issues to show', () => {
- beforeEach(() => {
- mockStore.state.report = mockReport;
- });
-
- it('renders custom accessibility issue body', () => {
- const issueBody = wrapper.findComponent(AccessibilityIssueBody);
-
- expect(issueBody.props('issue').code).toBe(mockReport.new_errors[0].code);
- expect(issueBody.props('issue').message).toBe(mockReport.new_errors[0].message);
- expect(issueBody.props('isNew')).toBe(true);
- });
- });
- });
-});
diff --git a/spec/frontend/reports/accessibility_report/mock_data.js b/spec/frontend/reports/accessibility_report/mock_data.js
deleted file mode 100644
index 9dace1e7c54..00000000000
--- a/spec/frontend/reports/accessibility_report/mock_data.js
+++ /dev/null
@@ -1,53 +0,0 @@
-export const mockReport = {
- status: 'failed',
- summary: {
- total: 2,
- resolved: 0,
- errored: 2,
- },
- new_errors: [
- {
- code: 'WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail',
- type: 'error',
- typeCode: 1,
- message:
- 'This element has insufficient contrast at this conformance level. Expected a contrast ratio of at least 4.5:1, but text in this element has a contrast ratio of 3.84:1. Recommendation: change text colour to #767676.',
- context: '<a href="/stages-devops-lifecycle/" class="main-nav-link">Product</a>',
- selector: '#main-nav > div:nth-child(2) > ul > li:nth-child(1) > a',
- runner: 'htmlcs',
- runnerExtras: {},
- },
- ],
- new_notes: [],
- new_warnings: [],
- resolved_errors: [
- {
- code: 'WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent',
- type: 'error',
- typeCode: 1,
- message:
- 'Anchor element found with a valid href attribute, but no link content has been supplied.',
- context: '<a href="/" class="navbar-brand animated"><svg height="36" viewBox="0 0 1...</a>',
- selector: '#main-nav > div:nth-child(1) > a',
- runner: 'htmlcs',
- runnerExtras: {},
- },
- ],
- resolved_notes: [],
- resolved_warnings: [],
- existing_errors: [
- {
- code: 'WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent',
- type: 'error',
- typeCode: 1,
- message:
- 'Anchor element found with a valid href attribute, but no link content has been supplied.',
- context: '<a href="/" class="navbar-brand animated"><svg height="36" viewBox="0 0 1...</a>',
- selector: '#main-nav > div:nth-child(1) > a',
- runner: 'htmlcs',
- runnerExtras: {},
- },
- ],
- existing_notes: [],
- existing_warnings: [],
-};
diff --git a/spec/frontend/reports/accessibility_report/store/actions_spec.js b/spec/frontend/reports/accessibility_report/store/actions_spec.js
deleted file mode 100644
index bab6c4905a7..00000000000
--- a/spec/frontend/reports/accessibility_report/store/actions_spec.js
+++ /dev/null
@@ -1,115 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
-import { TEST_HOST } from 'spec/test_constants';
-import axios from '~/lib/utils/axios_utils';
-import createStore from '~/reports/accessibility_report/store';
-import * as actions from '~/reports/accessibility_report/store/actions';
-import * as types from '~/reports/accessibility_report/store/mutation_types';
-import { mockReport } from '../mock_data';
-
-describe('Accessibility Reports actions', () => {
- let localState;
- let localStore;
-
- beforeEach(() => {
- localStore = createStore();
- localState = localStore.state;
- });
-
- describe('setEndpoints', () => {
- it('should commit SET_ENDPOINTS mutation', () => {
- const endpoint = 'endpoint.json';
-
- return testAction(
- actions.setEndpoint,
- endpoint,
- localState,
- [{ type: types.SET_ENDPOINT, payload: endpoint }],
- [],
- );
- });
- });
-
- describe('fetchReport', () => {
- let mock;
-
- beforeEach(() => {
- localState.endpoint = `${TEST_HOST}/endpoint.json`;
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- actions.stopPolling();
- actions.clearEtagPoll();
- });
-
- describe('success', () => {
- it('should commit REQUEST_REPORT mutation and dispatch receiveReportSuccess', () => {
- const data = { report: { summary: {} } };
- mock.onGet(`${TEST_HOST}/endpoint.json`).reply(200, data);
-
- return testAction(
- actions.fetchReport,
- null,
- localState,
- [{ type: types.REQUEST_REPORT }],
- [
- {
- payload: { status: 200, data },
- type: 'receiveReportSuccess',
- },
- ],
- );
- });
- });
-
- describe('error', () => {
- it('should commit REQUEST_REPORT and RECEIVE_REPORT_ERROR mutations', () => {
- mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
-
- return testAction(
- actions.fetchReport,
- null,
- localState,
- [{ type: types.REQUEST_REPORT }],
- [{ type: 'receiveReportError' }],
- );
- });
- });
- });
-
- describe('receiveReportSuccess', () => {
- it('should commit RECEIVE_REPORT_SUCCESS mutation with 200', () => {
- return testAction(
- actions.receiveReportSuccess,
- { status: 200, data: mockReport },
- localState,
- [{ type: types.RECEIVE_REPORT_SUCCESS, payload: mockReport }],
- [{ type: 'stopPolling' }],
- );
- });
-
- it('should not commit RECEIVE_REPORTS_SUCCESS mutation with 204', () => {
- return testAction(
- actions.receiveReportSuccess,
- { status: 204, data: mockReport },
- localState,
- [],
- [],
- );
- });
- });
-
- describe('receiveReportError', () => {
- it('should commit RECEIVE_REPORT_ERROR mutation', () => {
- return testAction(
- actions.receiveReportError,
- null,
- localState,
- [{ type: types.RECEIVE_REPORT_ERROR }],
- [{ type: 'stopPolling' }],
- );
- });
- });
-});
diff --git a/spec/frontend/reports/accessibility_report/store/getters_spec.js b/spec/frontend/reports/accessibility_report/store/getters_spec.js
deleted file mode 100644
index 96344596003..00000000000
--- a/spec/frontend/reports/accessibility_report/store/getters_spec.js
+++ /dev/null
@@ -1,149 +0,0 @@
-import createStore from '~/reports/accessibility_report/store';
-import * as getters from '~/reports/accessibility_report/store/getters';
-import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '~/reports/constants';
-
-describe('Accessibility reports store getters', () => {
- let localState;
- let localStore;
-
- beforeEach(() => {
- localStore = createStore();
- localState = localStore.state;
- });
-
- describe('summaryStatus', () => {
- describe('when summary is loading', () => {
- it('returns loading status', () => {
- localState.isLoading = true;
-
- expect(getters.summaryStatus(localState)).toEqual(LOADING);
- });
- });
-
- describe('when summary has error', () => {
- it('returns error status', () => {
- localState.hasError = true;
-
- expect(getters.summaryStatus(localState)).toEqual(ERROR);
- });
- });
-
- describe('when summary has failed status', () => {
- it('returns loading status', () => {
- localState.status = STATUS_FAILED;
-
- expect(getters.summaryStatus(localState)).toEqual(ERROR);
- });
- });
-
- describe('when summary has successfully loaded', () => {
- it('returns loading status', () => {
- expect(getters.summaryStatus(localState)).toEqual(SUCCESS);
- });
- });
- });
-
- describe('groupedSummaryText', () => {
- describe('when state is loading', () => {
- it('returns the loading summary message', () => {
- localState.isLoading = true;
- const result = 'Accessibility scanning results are being parsed';
-
- expect(getters.groupedSummaryText(localState)).toEqual(result);
- });
- });
-
- describe('when state has error', () => {
- it('returns the error summary message', () => {
- localState.hasError = true;
- const result = 'Accessibility scanning failed loading results';
-
- expect(getters.groupedSummaryText(localState)).toEqual(result);
- });
- });
-
- describe('when state has successfully loaded', () => {
- describe('when report has errors', () => {
- it('returns summary message containing number of errors', () => {
- localState.report = {
- summary: {
- errored: 2,
- },
- };
- const result = 'Accessibility scanning detected 2 issues for the source branch only';
-
- expect(getters.groupedSummaryText(localState)).toEqual(result);
- });
- });
-
- describe('when report has no errors', () => {
- it('returns summary message containing no errors', () => {
- localState.report = {
- summary: {
- errored: 0,
- },
- };
- const result = 'Accessibility scanning detected no issues for the source branch only';
-
- expect(getters.groupedSummaryText(localState)).toEqual(result);
- });
- });
- });
- });
-
- describe('shouldRenderIssuesList', () => {
- describe('when has issues to render', () => {
- it('returns true', () => {
- localState.report = {
- existing_errors: [{ name: 'Issue' }],
- };
-
- expect(getters.shouldRenderIssuesList(localState)).toEqual(true);
- });
- });
-
- describe('when does not have issues to render', () => {
- it('returns false', () => {
- localState.report = {
- status: 'success',
- summary: { errored: 0 },
- };
-
- expect(getters.shouldRenderIssuesList(localState)).toEqual(false);
- });
- });
- });
-
- describe('unresolvedIssues', () => {
- it('returns the array unresolved errors', () => {
- localState.report = {
- existing_errors: [1],
- };
- const result = [1];
-
- expect(getters.unresolvedIssues(localState)).toEqual(result);
- });
- });
-
- describe('resolvedIssues', () => {
- it('returns array of resolved errors', () => {
- localState.report = {
- resolved_errors: [1],
- };
- const result = [1];
-
- expect(getters.resolvedIssues(localState)).toEqual(result);
- });
- });
-
- describe('newIssues', () => {
- it('returns array of new errors', () => {
- localState.report = {
- new_errors: [1],
- };
- const result = [1];
-
- expect(getters.newIssues(localState)).toEqual(result);
- });
- });
-});
diff --git a/spec/frontend/reports/accessibility_report/store/mutations_spec.js b/spec/frontend/reports/accessibility_report/store/mutations_spec.js
deleted file mode 100644
index b336261d804..00000000000
--- a/spec/frontend/reports/accessibility_report/store/mutations_spec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import createStore from '~/reports/accessibility_report/store';
-import mutations from '~/reports/accessibility_report/store/mutations';
-
-describe('Accessibility Reports mutations', () => {
- let localState;
- let localStore;
-
- beforeEach(() => {
- localStore = createStore();
- localState = localStore.state;
- });
-
- describe('SET_ENDPOINT', () => {
- it('sets endpoint to given value', () => {
- const endpoint = 'endpoint.json';
- mutations.SET_ENDPOINT(localState, endpoint);
-
- expect(localState.endpoint).toEqual(endpoint);
- });
- });
-
- describe('REQUEST_REPORT', () => {
- it('sets isLoading to true', () => {
- mutations.REQUEST_REPORT(localState);
-
- expect(localState.isLoading).toEqual(true);
- });
- });
-
- describe('RECEIVE_REPORT_SUCCESS', () => {
- it('sets isLoading to false', () => {
- mutations.RECEIVE_REPORT_SUCCESS(localState, {});
-
- expect(localState.isLoading).toEqual(false);
- });
-
- it('sets hasError to false', () => {
- mutations.RECEIVE_REPORT_SUCCESS(localState, {});
-
- expect(localState.hasError).toEqual(false);
- });
-
- it('sets report to response report', () => {
- const report = { data: 'testing' };
- mutations.RECEIVE_REPORT_SUCCESS(localState, report);
-
- expect(localState.report).toEqual(report);
- });
- });
-
- describe('RECEIVE_REPORT_ERROR', () => {
- it('sets isLoading to false', () => {
- mutations.RECEIVE_REPORT_ERROR(localState);
-
- expect(localState.isLoading).toEqual(false);
- });
-
- it('sets hasError to true', () => {
- mutations.RECEIVE_REPORT_ERROR(localState);
-
- expect(localState.hasError).toEqual(true);
- });
- });
-});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap b/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
index 519475f8953..7d9dbcd68ff 100644
--- a/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
+++ b/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
@@ -79,6 +79,7 @@ exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have
class="dropdown b-dropdown gl-new-dropdown gl-display-block gl-md-display-none! btn-group"
lazy=""
no-caret=""
+ title="Options"
>
<!---->
<button
@@ -255,6 +256,7 @@ exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have c
class="dropdown b-dropdown gl-new-dropdown gl-display-block gl-md-display-none! btn-group"
lazy=""
no-caret=""
+ title="Options"
>
<!---->
<button
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js
index 9844af208d2..48d3f15560b 100644
--- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -795,7 +795,7 @@ describe('ReadyToMerge', () => {
});
it('shows the diverged commits text when the source branch is behind the target', () => {
- createComponent({ mr: { divergedCommitsCount: 9001 } });
+ createComponent({ mr: { divergedCommitsCount: 9001, canMerge: false } });
expect(wrapper.text()).toEqual(
expect.stringContaining('The source branch is 9001 commits behind the target branch'),
diff --git a/spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js b/spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js
deleted file mode 100644
index db10236e5de..00000000000
--- a/spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js
+++ /dev/null
@@ -1,175 +0,0 @@
-import { GlSkeletonLoader, GlSprintf } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import MockAdapter from 'axios-mock-adapter';
-import { nextTick } from 'vue';
-import axios from '~/lib/utils/axios_utils';
-import Poll from '~/lib/utils/poll';
-import MrWidgetExpanableSection from '~/vue_merge_request_widget/components/mr_widget_expandable_section.vue';
-import MrWidgetTerraformContainer from '~/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue';
-import TerraformPlan from '~/vue_merge_request_widget/components/terraform/terraform_plan.vue';
-import { invalidPlanWithName, plans, validPlanWithName } from './mock_data';
-
-describe('MrWidgetTerraformConainer', () => {
- let mock;
- let wrapper;
-
- const propsData = { endpoint: '/path/to/terraform/report.json' };
-
- const findHeader = () => wrapper.find('[data-testid="terraform-header-text"]');
- const findPlans = () =>
- wrapper.findAllComponents(TerraformPlan).wrappers.map((x) => x.props('plan'));
-
- const mockPollingApi = (response, body, header) => {
- mock.onGet(propsData.endpoint).reply(response, body, header);
- };
-
- const mountWrapper = () => {
- wrapper = shallowMount(MrWidgetTerraformContainer, {
- propsData,
- stubs: { MrWidgetExpanableSection, GlSprintf },
- });
- return axios.waitForAll();
- };
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- wrapper.destroy();
- mock.restore();
- });
-
- describe('when data is loading', () => {
- beforeEach(async () => {
- mockPollingApi(200, plans, {});
-
- await mountWrapper();
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ loading: true });
- await nextTick();
- });
-
- it('diplays loading skeleton', () => {
- expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(true);
- expect(wrapper.findComponent(MrWidgetExpanableSection).exists()).toBe(false);
- });
- });
-
- describe('when data has finished loading', () => {
- beforeEach(() => {
- mockPollingApi(200, plans, {});
- return mountWrapper();
- });
-
- it('displays terraform content', () => {
- expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(false);
- expect(wrapper.findComponent(MrWidgetExpanableSection).exists()).toBe(true);
- expect(findPlans()).toEqual(Object.values(plans));
- });
-
- describe('when data includes one invalid plan', () => {
- beforeEach(() => {
- const invalidPlanGroup = { bad_plan: invalidPlanWithName };
- mockPollingApi(200, invalidPlanGroup, {});
- return mountWrapper();
- });
-
- it('displays header text for one invalid plan', () => {
- expect(findHeader().text()).toBe('1 Terraform report failed to generate');
- });
- });
-
- describe('when data includes multiple invalid plans', () => {
- beforeEach(() => {
- const invalidPlanGroup = {
- bad_plan_one: invalidPlanWithName,
- bad_plan_two: invalidPlanWithName,
- };
-
- mockPollingApi(200, invalidPlanGroup, {});
- return mountWrapper();
- });
-
- it('displays header text for multiple invalid plans', () => {
- expect(findHeader().text()).toBe('2 Terraform reports failed to generate');
- });
- });
-
- describe('when data includes one valid plan', () => {
- beforeEach(() => {
- const validPlanGroup = { valid_plan: validPlanWithName };
- mockPollingApi(200, validPlanGroup, {});
- return mountWrapper();
- });
-
- it('displays header text for one valid plans', () => {
- expect(findHeader().text()).toBe('1 Terraform report was generated in your pipelines');
- });
- });
-
- describe('when data includes multiple valid plans', () => {
- beforeEach(() => {
- const validPlanGroup = {
- valid_plan_one: validPlanWithName,
- valid_plan_two: validPlanWithName,
- };
- mockPollingApi(200, validPlanGroup, {});
- return mountWrapper();
- });
-
- it('displays header text for multiple valid plans', () => {
- expect(findHeader().text()).toBe('2 Terraform reports were generated in your pipelines');
- });
- });
- });
-
- describe('polling', () => {
- let pollRequest;
- let pollStop;
-
- beforeEach(() => {
- pollRequest = jest.spyOn(Poll.prototype, 'makeRequest');
- pollStop = jest.spyOn(Poll.prototype, 'stop');
- });
-
- afterEach(() => {
- pollRequest.mockRestore();
- pollStop.mockRestore();
- });
-
- describe('successful poll', () => {
- beforeEach(() => {
- mockPollingApi(200, plans, {});
-
- return mountWrapper();
- });
-
- it('does not make additional requests after poll is successful', () => {
- expect(pollRequest).toHaveBeenCalledTimes(1);
- expect(pollStop).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('polling fails', () => {
- beforeEach(() => {
- mockPollingApi(500, null, {});
- return mountWrapper();
- });
-
- it('stops loading', () => {
- expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(false);
- });
-
- it('generates one broken plan', () => {
- expect(findPlans()).toEqual([{ tf_report_error: 'api_error' }]);
- });
-
- it('does not make additional requests after poll is unsuccessful', () => {
- expect(pollRequest).toHaveBeenCalledTimes(1);
- expect(pollStop).toHaveBeenCalledTimes(1);
- });
- });
- });
-});
diff --git a/spec/frontend/vue_merge_request_widget/components/terraform/terraform_plan_spec.js b/spec/frontend/vue_merge_request_widget/components/terraform/terraform_plan_spec.js
deleted file mode 100644
index 3c9f6c2e165..00000000000
--- a/spec/frontend/vue_merge_request_widget/components/terraform/terraform_plan_spec.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import { GlLink, GlSprintf } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import TerraformPlan from '~/vue_merge_request_widget/components/terraform/terraform_plan.vue';
-import {
- invalidPlanWithName,
- invalidPlanWithoutName,
- validPlanWithName,
- validPlanWithoutName,
-} from './mock_data';
-
-describe('TerraformPlan', () => {
- let wrapper;
-
- const findIcon = () => wrapper.find('[data-testid="change-type-icon"]');
- const findLogButton = () => wrapper.find('[data-testid="terraform-report-link"]');
-
- const mountWrapper = (propsData) => {
- wrapper = shallowMount(TerraformPlan, { stubs: { GlLink, GlSprintf }, propsData });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('valid plan with job_name', () => {
- beforeEach(() => {
- mountWrapper({ plan: validPlanWithName });
- });
-
- it('displays a document icon', () => {
- expect(findIcon().attributes('name')).toBe('doc-changes');
- });
-
- it('diplays the header text with a name', () => {
- expect(wrapper.text()).toContain(`The job ${validPlanWithName.job_name} generated a report.`);
- });
-
- it('diplays the reported changes', () => {
- expect(wrapper.text()).toContain(
- `Reported Resource Changes: ${validPlanWithName.create} to add, ${validPlanWithName.update} to change, ${validPlanWithName.delete} to delete`,
- );
- });
-
- it('renders button when url is found', () => {
- expect(findLogButton().exists()).toBe(true);
- expect(findLogButton().text()).toEqual('View full log');
- });
- });
-
- describe('valid plan without job_name', () => {
- beforeEach(() => {
- mountWrapper({ plan: validPlanWithoutName });
- });
-
- it('diplays the header text without a name', () => {
- expect(wrapper.text()).toContain('A report was generated in your pipelines.');
- });
- });
-
- describe('invalid plan with job_name', () => {
- beforeEach(() => {
- mountWrapper({ plan: invalidPlanWithName });
- });
-
- it('displays a warning icon', () => {
- expect(findIcon().attributes('name')).toBe('warning');
- });
-
- it('diplays the header text with a name', () => {
- expect(wrapper.text()).toContain(
- `The job ${invalidPlanWithName.job_name} failed to generate a report.`,
- );
- });
-
- it('diplays generic error since report values are missing', () => {
- expect(wrapper.text()).toContain('Generating the report caused an error.');
- });
- });
-
- describe('invalid plan with out job_name', () => {
- beforeEach(() => {
- mountWrapper({ plan: invalidPlanWithoutName });
- });
-
- it('diplays the header text without a name', () => {
- expect(wrapper.text()).toContain('A report failed to generate.');
- });
-
- it('does not render button because url is missing', () => {
- expect(findLogButton().exists()).toBe(false);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/url_sync_spec.js b/spec/frontend/vue_shared/components/url_sync_spec.js
index aefe6a5c3e8..acda1a64a75 100644
--- a/spec/frontend/vue_shared/components/url_sync_spec.js
+++ b/spec/frontend/vue_shared/components/url_sync_spec.js
@@ -1,10 +1,11 @@
import { shallowMount } from '@vue/test-utils';
import { historyPushState } from '~/lib/utils/common_utils';
-import { mergeUrlParams } from '~/lib/utils/url_utility';
-import UrlSyncComponent from '~/vue_shared/components/url_sync.vue';
+import { mergeUrlParams, setUrlParams } from '~/lib/utils/url_utility';
+import UrlSyncComponent, { URL_SET_PARAMS_STRATEGY } from '~/vue_shared/components/url_sync.vue';
jest.mock('~/lib/utils/url_utility', () => ({
- mergeUrlParams: jest.fn((query, url) => `urlParams: ${query} ${url}`),
+ mergeUrlParams: jest.fn((query, url) => `urlParams: ${JSON.stringify(query)} ${url}`),
+ setUrlParams: jest.fn((query, url) => `urlParams: ${JSON.stringify(query)} ${url}`),
}));
jest.mock('~/lib/utils/common_utils', () => ({
@@ -17,9 +18,14 @@ describe('url sync component', () => {
const findButton = () => wrapper.find('button');
- const createComponent = ({ query = mockQuery, scopedSlots, slots } = {}) => {
+ const createComponent = ({
+ query = mockQuery,
+ scopedSlots,
+ slots,
+ urlParamsUpdateStrategy,
+ } = {}) => {
wrapper = shallowMount(UrlSyncComponent, {
- propsData: { query },
+ propsData: { query, ...(urlParamsUpdateStrategy && { urlParamsUpdateStrategy }) },
scopedSlots,
slots,
});
@@ -29,21 +35,39 @@ describe('url sync component', () => {
wrapper.destroy();
});
- const expectUrlSync = (query, times, mergeUrlParamsReturnValue) => {
- expect(mergeUrlParams).toHaveBeenCalledTimes(times);
- expect(mergeUrlParams).toHaveBeenCalledWith(query, window.location.href, {
- spreadArrays: true,
- });
+ const expectUrlSyncFactory = (
+ query,
+ times,
+ urlParamsUpdateStrategy,
+ urlOptions,
+ urlReturnValue,
+ ) => {
+ expect(urlParamsUpdateStrategy).toHaveBeenCalledTimes(times);
+ expect(urlParamsUpdateStrategy).toHaveBeenCalledWith(query, window.location.href, urlOptions);
expect(historyPushState).toHaveBeenCalledTimes(times);
- expect(historyPushState).toHaveBeenCalledWith(mergeUrlParamsReturnValue);
+ expect(historyPushState).toHaveBeenCalledWith(urlReturnValue);
+ };
+
+ const expectUrlSyncWithMergeUrlParams = (query, times, mergeUrlParamsReturnValue) => {
+ expectUrlSyncFactory(
+ query,
+ times,
+ mergeUrlParams,
+ { spreadArrays: true },
+ mergeUrlParamsReturnValue,
+ );
+ };
+
+ const expectUrlSyncWithSetUrlParams = (query, times, setUrlParamsReturnValue) => {
+ expectUrlSyncFactory(query, times, setUrlParams, true, setUrlParamsReturnValue);
};
describe('with query as a props', () => {
it('immediately syncs the query to the URL', () => {
createComponent();
- expectUrlSync(mockQuery, 1, mergeUrlParams.mock.results[0].value);
+ expectUrlSyncWithMergeUrlParams(mockQuery, 1, mergeUrlParams.mock.results[0].value);
});
describe('when the query is modified', () => {
@@ -54,11 +78,21 @@ describe('url sync component', () => {
// using setProps to test the watcher
await wrapper.setProps({ query: newQuery });
- expectUrlSync(mockQuery, 2, mergeUrlParams.mock.results[1].value);
+ expectUrlSyncWithMergeUrlParams(mockQuery, 2, mergeUrlParams.mock.results[1].value);
});
});
});
+ describe('with url-params-update-strategy equals to URL_SET_PARAMS_STRATEGY', () => {
+ it('uses setUrlParams to generate URL', () => {
+ createComponent({
+ urlParamsUpdateStrategy: URL_SET_PARAMS_STRATEGY,
+ });
+
+ expectUrlSyncWithSetUrlParams(mockQuery, 1, setUrlParams.mock.results[0].value);
+ });
+ });
+
describe('with scoped slot', () => {
const scopedSlots = {
default: `
@@ -77,7 +111,7 @@ describe('url sync component', () => {
findButton().trigger('click');
- expectUrlSync({ bar: 'baz' }, 1, mergeUrlParams.mock.results[0].value);
+ expectUrlSyncWithMergeUrlParams({ bar: 'baz' }, 1, mergeUrlParams.mock.results[0].value);
});
});
diff --git a/spec/scripts/lib/glfm/update_specification_spec.rb b/spec/scripts/lib/glfm/update_specification_spec.rb
index 1cdc90876de..7daf85b5d25 100644
--- a/spec/scripts/lib/glfm/update_specification_spec.rb
+++ b/spec/scripts/lib/glfm/update_specification_spec.rb
@@ -1,8 +1,12 @@
# frozen_string_literal: true
+
require 'fast_spec_helper'
require_relative '../../../../scripts/lib/glfm/update_specification'
+require_relative '../../../support/helpers/next_instance_of'
RSpec.describe Glfm::UpdateSpecification, '#process' do
+ include NextInstanceOf
+
subject { described_class.new }
let(:ghfm_spec_txt_uri) { described_class::GHFM_SPEC_TXT_URI }
@@ -79,7 +83,9 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
# We mock out the URI and local file IO objects with real StringIO, instead of just mock
# objects. This gives better and more realistic coverage, while still avoiding
# actual network and filesystem I/O during the spec run.
- allow(URI).to receive(:open).with(ghfm_spec_txt_uri) { ghfm_spec_txt_uri_io }
+ allow_next_instance_of(URI::HTTP) do |instance|
+ allow(instance).to receive(:open).and_return(ghfm_spec_txt_uri_io)
+ end
allow(File).to receive(:open).with(ghfm_spec_md_path) { ghfm_spec_txt_local_io }
allow(File).to receive(:open).with(glfm_intro_md_path) { glfm_intro_md_io }
allow(File).to receive(:open).with(glfm_examples_txt_path) { glfm_examples_txt_io }
@@ -92,7 +98,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
describe 'retrieving latest GHFM spec.txt' do
context 'when UPDATE_GHFM_SPEC_MD is not true (default)' do
it 'does not download' do
- expect(URI).not_to receive(:open).with(ghfm_spec_txt_uri)
+ expect(URI).not_to receive(:parse).with(ghfm_spec_txt_uri)
subject.process
diff --git a/spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb b/spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb
index d7b00ba04ab..c07bc761016 100644
--- a/spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb
+++ b/spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb
@@ -75,7 +75,7 @@ RSpec.describe BulkImports::CreatePipelineTrackersService do
expect_next_instance_of(Gitlab::Import::Logger) do |logger|
expect(logger).to receive(:info).with({
message: 'Pipeline skipped as source instance version not compatible with pipeline',
- entity_id: entity.id,
+ bulk_import_entity_id: entity.id,
pipeline_name: 'PipelineClass4',
minimum_source_version: '15.1.0',
maximum_source_version: nil,
@@ -84,7 +84,7 @@ RSpec.describe BulkImports::CreatePipelineTrackersService do
expect(logger).to receive(:info).with({
message: 'Pipeline skipped as source instance version not compatible with pipeline',
- entity_id: entity.id,
+ bulk_import_entity_id: entity.id,
pipeline_name: 'PipelineClass5',
minimum_source_version: '16.0.0',
maximum_source_version: nil,
diff --git a/spec/services/incident_management/timeline_events/create_service_spec.rb b/spec/services/incident_management/timeline_events/create_service_spec.rb
index 0e6864387d6..a7f448c825f 100644
--- a/spec/services/incident_management/timeline_events/create_service_spec.rb
+++ b/spec/services/incident_management/timeline_events/create_service_spec.rb
@@ -84,50 +84,6 @@ RSpec.describe IncidentManagement::TimelineEvents::CreateService do
expect(result.action).to eq(IncidentManagement::TimelineEvents::DEFAULT_ACTION)
end
- end
-
- context 'with non_default action' do
- it_behaves_like 'success response'
-
- it 'matches the action from arguments', :aggregate_failures do
- result = execute.payload[:timeline_event]
-
- expect(result.action).to eq(args[:action])
- end
- end
-
- context 'with editable param' do
- let(:args) do
- {
- note: 'note',
- occurred_at: Time.current,
- action: 'new comment',
- promoted_from_note: comment,
- editable: editable
- }
- end
-
- context 'when editable is true' do
- let(:editable) { true }
-
- it_behaves_like 'success response'
- end
-
- context 'when editable is false' do
- let(:editable) { false }
-
- it_behaves_like 'success response'
- end
- end
-
- it 'successfully creates a database record', :aggregate_failures do
- expect { execute }.to change { ::IncidentManagement::TimelineEvent.count }.by(1)
- end
-
- context 'when incident_timeline feature flag is enabled' do
- before do
- stub_feature_flags(incident_timeline: project)
- end
it 'creates a system note' do
expect { execute }.to change { incident.notes.reload.count }.by(1)
@@ -168,14 +124,42 @@ RSpec.describe IncidentManagement::TimelineEvents::CreateService do
end
end
- context 'when incident_timeline feature flag is disabled' do
- before do
- stub_feature_flags(incident_timeline: false)
+ context 'with non_default action' do
+ it_behaves_like 'success response'
+
+ it 'matches the action from arguments', :aggregate_failures do
+ result = execute.payload[:timeline_event]
+
+ expect(result.action).to eq(args[:action])
end
+ end
- it 'does not create a system note' do
- expect { execute }.not_to change { incident.notes.reload.count }
+ context 'with editable param' do
+ let(:args) do
+ {
+ note: 'note',
+ occurred_at: Time.current,
+ action: 'new comment',
+ promoted_from_note: comment,
+ editable: editable
+ }
+ end
+
+ context 'when editable is true' do
+ let(:editable) { true }
+
+ it_behaves_like 'success response'
end
+
+ context 'when editable is false' do
+ let(:editable) { false }
+
+ it_behaves_like 'success response'
+ end
+ end
+
+ it 'successfully creates a database record', :aggregate_failures do
+ expect { execute }.to change { ::IncidentManagement::TimelineEvent.count }.by(1)
end
end
diff --git a/spec/services/incident_management/timeline_events/destroy_service_spec.rb b/spec/services/incident_management/timeline_events/destroy_service_spec.rb
index 2fffe75b53c..e1b258960ae 100644
--- a/spec/services/incident_management/timeline_events/destroy_service_spec.rb
+++ b/spec/services/incident_management/timeline_events/destroy_service_spec.rb
@@ -51,7 +51,7 @@ RSpec.describe IncidentManagement::TimelineEvents::DestroyService do
it_behaves_like 'error response', 'Timeline text cannot be removed'
end
- context 'success response' do
+ context 'with success response' do
it 'successfully returns the timeline event', :aggregate_failures do
expect(execute).to be_success
@@ -60,27 +60,11 @@ RSpec.describe IncidentManagement::TimelineEvents::DestroyService do
expect(result.id).to eq(timeline_event.id)
end
- it_behaves_like 'an incident management tracked event', :incident_management_timeline_event_deleted
- end
-
- context 'when incident_timeline feature flag is enabled' do
- before do
- stub_feature_flags(incident_timeline: project)
- end
-
it 'creates a system note' do
expect { execute }.to change { incident.notes.reload.count }.by(1)
end
- end
-
- context 'when incident_timeline feature flag is disabled' do
- before do
- stub_feature_flags(incident_timeline: false)
- end
- it 'does not create a system note' do
- expect { execute }.not_to change { incident.notes.reload.count }
- end
+ it_behaves_like 'an incident management tracked event', :incident_management_timeline_event_deleted
end
end
end
diff --git a/spec/services/incident_management/timeline_events/update_service_spec.rb b/spec/services/incident_management/timeline_events/update_service_spec.rb
index 21aa983dbd1..5d8518cf2ef 100644
--- a/spec/services/incident_management/timeline_events/update_service_spec.rb
+++ b/spec/services/incident_management/timeline_events/update_service_spec.rb
@@ -12,10 +12,6 @@ RSpec.describe IncidentManagement::TimelineEvents::UpdateService do
let(:params) { { note: 'Updated note', occurred_at: occurred_at } }
let(:current_user) { user }
- before do
- stub_feature_flags(incident_timeline: project)
- end
-
describe '#execute' do
shared_examples 'successful response' do
it 'responds with success', :aggregate_failures do
@@ -70,16 +66,6 @@ RSpec.describe IncidentManagement::TimelineEvents::UpdateService do
it_behaves_like 'passing the correct was_changed value', :occurred_at_and_note
- context 'when incident_timeline feature flag is disabled' do
- before do
- stub_feature_flags(incident_timeline: false)
- end
-
- it 'does not add a system note' do
- expect { execute }.not_to change { incident.notes }
- end
- end
-
context 'when note is nil' do
let(:params) { { occurred_at: occurred_at } }
diff --git a/spec/support/capybara_slow_finder.rb b/spec/support/capybara_slow_finder.rb
index 029e11e4460..975ddd52c1f 100644
--- a/spec/support/capybara_slow_finder.rb
+++ b/spec/support/capybara_slow_finder.rb
@@ -2,7 +2,9 @@
module Capybara
MESSAGE = <<~MSG
- Timeout reached while running a waiting Capybara finder. Consider using a non-waiting finder.
+ Timeout (%{timeout}s) reached while running a waiting Capybara finder.
+ Consider using a non-waiting finder.
+
See https://www.cloudbees.com/blog/faster-rails-tests
MSG
@@ -19,7 +21,8 @@ module Capybara
raise e unless seconds > 0 && Gitlab::Metrics::System.monotonic_time - start_time > seconds
- raise e, "#{$!}#{MESSAGE}", e.backtrace
+ message = format(MESSAGE, timeout: seconds)
+ raise e, "#{$!}\n\n#{message}", e.backtrace
end
end
diff --git a/spec/support_specs/capybara_slow_finder_spec.rb b/spec/support_specs/capybara_slow_finder_spec.rb
index cba75a7fba2..b0438a7a78b 100644
--- a/spec/support_specs/capybara_slow_finder_spec.rb
+++ b/spec/support_specs/capybara_slow_finder_spec.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
+require 'capybara'
+require 'support/capybara_slow_finder'
RSpec.describe Capybara::Node::Base::SlowFinder do # rubocop:disable RSpec/FilePath
context 'without timeout' do
@@ -38,10 +40,12 @@ RSpec.describe Capybara::Node::Base::SlowFinder do # rubocop:disable RSpec/FileP
end
context 'with timeout' do
+ let(:timeout) { 0.01 }
+
let(:slow_finder) do
Class.new do
def synchronize(seconds = nil, errors: nil)
- sleep 0.1
+ sleep 0.02
raise Capybara::ElementNotFound
end
@@ -50,10 +54,24 @@ RSpec.describe Capybara::Node::Base::SlowFinder do # rubocop:disable RSpec/FileP
end.new
end
- it 'raises a timeout error' do
- expect { slow_finder.synchronize(0.01) }.to raise_error(
+ context 'with default timeout' do
+ it 'raises a timeout error' do
+ expect(Capybara).to receive(:default_max_wait_time).and_return(timeout)
+
+ expect { slow_finder.synchronize }.to raise_error_element_not_found
+ end
+ end
+
+ context 'when passed as paramater' do
+ it 'raises a timeout error' do
+ expect { slow_finder.synchronize(timeout) }.to raise_error_element_not_found
+ end
+ end
+
+ def raise_error_element_not_found
+ raise_error(
Capybara::ElementNotFound,
- /Timeout reached while running a waiting Capybara finder./
+ /\n\nTimeout \(#{timeout}s\) reached while running a waiting Capybara finder./
)
end
end
diff --git a/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb b/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb
index 18a2e29adab..cb41f2e636e 100644
--- a/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb
+++ b/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe 'admin/application_settings/_package_registry' do
it 'does not display the plan name when there is only one plan' do
subject
- expect(page).not_to have_content('Default')
+ expect(page).not_to have_selector('a[data-action="plan0"]')
end
end
diff --git a/spec/workers/bulk_imports/entity_worker_spec.rb b/spec/workers/bulk_imports/entity_worker_spec.rb
index ab85b587975..ba638e1369e 100644
--- a/spec/workers/bulk_imports/entity_worker_spec.rb
+++ b/spec/workers/bulk_imports/entity_worker_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe BulkImports::EntityWorker do
.to receive(:info).twice
.with(
hash_including(
- 'entity_id' => entity.id,
+ 'bulk_import_entity_id' => entity.id,
'current_stage' => nil,
'message' => 'Stage starting'
)
@@ -67,7 +67,7 @@ RSpec.describe BulkImports::EntityWorker do
.to receive(:info).twice
.with(
hash_including(
- 'entity_id' => entity.id,
+ 'bulk_import_entity_id' => entity.id,
'current_stage' => nil
)
)
@@ -76,7 +76,7 @@ RSpec.describe BulkImports::EntityWorker do
.to receive(:error)
.with(
hash_including(
- 'entity_id' => entity.id,
+ 'bulk_import_entity_id' => entity.id,
'current_stage' => nil,
'message' => 'Error!'
)
@@ -85,7 +85,7 @@ RSpec.describe BulkImports::EntityWorker do
expect(Gitlab::ErrorTracking)
.to receive(:track_exception)
- .with(exception, entity_id: entity.id)
+ .with(exception, bulk_import_entity_id: entity.id)
subject
end
@@ -99,7 +99,7 @@ RSpec.describe BulkImports::EntityWorker do
.to receive(:info).twice
.with(
hash_including(
- 'entity_id' => entity.id,
+ 'bulk_import_entity_id' => entity.id,
'current_stage' => 0,
'message' => 'Stage running'
)
@@ -127,7 +127,7 @@ RSpec.describe BulkImports::EntityWorker do
.to receive(:info).twice
.with(
hash_including(
- 'entity_id' => entity.id,
+ 'bulk_import_entity_id' => entity.id,
'current_stage' => 0
)
)
diff --git a/spec/workers/bulk_imports/pipeline_worker_spec.rb b/spec/workers/bulk_imports/pipeline_worker_spec.rb
index cc403f91191..ef1db948893 100644
--- a/spec/workers/bulk_imports/pipeline_worker_spec.rb
+++ b/spec/workers/bulk_imports/pipeline_worker_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe BulkImports::PipelineWorker do
.with(
hash_including(
'pipeline_name' => 'FakePipeline',
- 'entity_id' => entity.id
+ 'bulk_import_entity_id' => entity.id
)
)
end
@@ -83,7 +83,7 @@ RSpec.describe BulkImports::PipelineWorker do
.with(
hash_including(
'pipeline_tracker_id' => pipeline_tracker.id,
- 'entity_id' => entity.id,
+ 'bulk_import_entity_id' => entity.id,
'message' => 'Unstarted pipeline not found'
)
)
@@ -120,7 +120,7 @@ RSpec.describe BulkImports::PipelineWorker do
.with(
hash_including(
'pipeline_name' => 'FakePipeline',
- 'entity_id' => entity.id,
+ 'bulk_import_entity_id' => entity.id,
'message' => 'Error!'
)
)
@@ -130,7 +130,7 @@ RSpec.describe BulkImports::PipelineWorker do
.to receive(:track_exception)
.with(
instance_of(StandardError),
- entity_id: entity.id,
+ bulk_import_entity_id: entity.id,
pipeline_name: pipeline_tracker.pipeline_name
)
@@ -178,7 +178,7 @@ RSpec.describe BulkImports::PipelineWorker do
.with(
hash_including(
'pipeline_name' => 'FakePipeline',
- 'entity_id' => entity.id,
+ 'bulk_import_entity_id' => entity.id,
'message' => 'Skipping pipeline due to failed entity'
)
)
@@ -225,7 +225,7 @@ RSpec.describe BulkImports::PipelineWorker do
.with(
hash_including(
'pipeline_name' => 'FakePipeline',
- 'entity_id' => entity.id
+ 'bulk_import_entity_id' => entity.id
)
)
end
@@ -348,7 +348,7 @@ RSpec.describe BulkImports::PipelineWorker do
.with(
hash_including(
'pipeline_name' => 'NdjsonPipeline',
- 'entity_id' => entity.id,
+ 'bulk_import_entity_id' => entity.id,
'message' => 'Pipeline timeout'
)
)
@@ -375,7 +375,7 @@ RSpec.describe BulkImports::PipelineWorker do
.with(
hash_including(
'pipeline_name' => 'NdjsonPipeline',
- 'entity_id' => entity.id,
+ 'bulk_import_entity_id' => entity.id,
'message' => 'Export from source instance failed: Error!'
)
)