summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-06-07 09:09:00 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-06-07 09:09:00 +0000
commitbdd03bc52aee1c3f37e25ae9b1fc8a27885b7428 (patch)
treee409a6e1f76d9dc69c5413a06e9b4c4b3f74fef7
parentbed53d96d214fd96ea688d3e86e53457ce50043e (diff)
downloadgitlab-ce-bdd03bc52aee1c3f37e25ae9b1fc8a27885b7428.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml4
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock32
-rw-r--r--app/assets/javascripts/design_management/pages/index.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/label_item.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue3
-rw-r--r--app/assets/stylesheets/page_bundles/issues_show.scss5
-rw-r--r--app/controllers/ide_controller.rb5
-rw-r--r--db/migrate/20220607011733_add_phone_verification_code_enabled_to_application_settings.rb16
-rw-r--r--db/schema_migrations/202206070117331
-rw-r--r--db/structure.sql3
-rw-r--r--doc/api/members.md2
-rw-r--r--doc/user/analytics/value_stream_analytics.md2
-rw-r--r--doc/user/group/value_stream_analytics/index.md2
-rw-r--r--lib/tasks/contracts.rake (renamed from qa/tasks/contracts.rake)10
-rw-r--r--qa/Gemfile2
-rw-r--r--qa/Gemfile.lock35
-rw-r--r--qa/contracts/provider/environments/base.rb24
-rw-r--r--qa/contracts/provider/environments/local.rb12
-rw-r--r--qa/contracts/provider/spec_helper.rb22
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb78
-rw-r--r--spec/contracts/.gitignore (renamed from qa/contracts/.gitignore)0
-rw-r--r--spec/contracts/consumer/.node-version (renamed from qa/contracts/consumer/.node-version)0
-rw-r--r--spec/contracts/consumer/endpoints/merge_requests.js (renamed from qa/contracts/consumer/endpoints/merge_request.js)6
-rw-r--r--spec/contracts/consumer/fixtures/diffs.fixture.js (renamed from qa/contracts/consumer/fixtures/diffs.fixture.js)2
-rw-r--r--spec/contracts/consumer/fixtures/discussions.fixture.js (renamed from qa/contracts/consumer/fixtures/discussions.fixture.js)2
-rw-r--r--spec/contracts/consumer/fixtures/metadata.fixture.js (renamed from qa/contracts/consumer/fixtures/metadata.fixture.js)2
-rw-r--r--spec/contracts/consumer/package.json (renamed from qa/contracts/consumer/package.json)2
-rw-r--r--spec/contracts/consumer/specs/diffs.spec.js (renamed from qa/contracts/consumer/specs/diffs.spec.js)5
-rw-r--r--spec/contracts/consumer/specs/discussions.spec.js (renamed from qa/contracts/consumer/specs/discussions.spec.js)5
-rw-r--r--spec/contracts/consumer/specs/metadata.spec.js (renamed from qa/contracts/consumer/specs/metadata.spec.js)5
-rw-r--r--spec/contracts/contracts/merge_request_page-merge_request_diffs_endpoint.json (renamed from qa/contracts/contracts/merge_request_page-merge_request_diffs_endpoint.json)5
-rw-r--r--spec/contracts/contracts/merge_request_page-merge_request_discussions_endpoint.json (renamed from qa/contracts/contracts/merge_request_page-merge_request_discussions_endpoint.json)5
-rw-r--r--spec/contracts/contracts/merge_request_page-merge_request_metadata_endpoint.json (renamed from qa/contracts/contracts/merge_request_page-merge_request_metadata_endpoint.json)5
-rw-r--r--spec/contracts/provider/environments/test.rb15
-rw-r--r--spec/contracts/provider/helpers/users_helper.rb7
-rw-r--r--spec/contracts/provider/spec_helper.rb39
-rw-r--r--spec/contracts/provider/specs/diffs_helper.rb (renamed from qa/contracts/provider/spec/diffs_helper.rb)5
-rw-r--r--spec/contracts/provider/specs/discussions_helper.rb (renamed from qa/contracts/provider/spec/discussions_helper.rb)5
-rw-r--r--spec/contracts/provider/specs/metadata_helper.rb (renamed from qa/contracts/provider/spec/metadata_helper.rb)5
-rw-r--r--spec/contracts/provider/states/diffs_state.rb18
-rw-r--r--spec/contracts/provider/states/discussions_state.rb17
-rw-r--r--spec/contracts/provider/states/metadata_state.rb18
-rw-r--r--spec/frontend/design_management/pages/index_spec.js20
-rw-r--r--spec/requests/ide_controller_spec.rb25
52 files changed, 323 insertions, 185 deletions
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index 792e0ccc346..6a2c27a1c22 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -238,7 +238,7 @@
services:
- name: postgres:13
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- - name: redis:5.0-alpine
+ - name: redis:6.2-alpine
variables:
POSTGRES_HOST_AUTH_METHOD: trust
PG_VERSION: "13"
@@ -269,7 +269,7 @@
services:
- name: postgres:13
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- - name: redis:5.0-alpine
+ - name: redis:6.2-alpine
- name: elasticsearch:7.17.0
command: ["elasticsearch", "-E", "discovery.type=single-node", "-E", "xpack.security.enabled=false"]
variables:
diff --git a/Gemfile b/Gemfile
index bb8585d525f..bfbb52c1d17 100644
--- a/Gemfile
+++ b/Gemfile
@@ -402,6 +402,8 @@ group :development, :test do
gem 'test_file_finder', '~> 0.1.3'
gem 'sigdump', '~> 0.2.4', require: 'sigdump/setup'
+
+ gem 'pact', '~> 1.12'
end
group :development, :test, :danger do
diff --git a/Gemfile.lock b/Gemfile.lock
index d7d9a013f82..a0561ae2697 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -394,6 +394,8 @@ GEM
rake
ffi-yajl (2.3.4)
libyajl2 (~> 1.2)
+ filelock (1.1.1)
+ find_a_port (1.0.1)
flipper (0.21.0)
flipper-active_record (0.21.0)
activerecord (>= 5.0, < 7)
@@ -914,6 +916,29 @@ GEM
rubypants (~> 0.2)
orm_adapter (0.5.0)
os (1.1.1)
+ pact (1.59.0)
+ pact-mock_service (~> 3.0, >= 3.3.1)
+ pact-support (~> 1.15)
+ rack-test (>= 0.6.3, < 2.0.0)
+ rspec (~> 3.0)
+ term-ansicolor (~> 1.0)
+ thor (>= 0.20, < 2.0)
+ webrick (~> 1.3)
+ pact-mock_service (3.6.2)
+ filelock (~> 1.1)
+ find_a_port (~> 1.0.1)
+ json
+ pact-support (~> 1.12, >= 1.12.0)
+ rack (~> 2.0)
+ rspec (>= 2.14)
+ term-ansicolor (~> 1.0)
+ thor (>= 0.19, < 2.0)
+ webrick (~> 1.3)
+ pact-support (1.15.1)
+ awesome_print (~> 1.1)
+ randexp (~> 0.1.7)
+ rspec (>= 2.14)
+ term-ansicolor (~> 1.0)
parallel (1.20.1)
parser (3.1.2.0)
ast (~> 2.4.1)
@@ -1015,6 +1040,7 @@ GEM
thor (~> 1.0)
rainbow (3.0.0)
rake (13.0.6)
+ randexp (0.1.7)
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
@@ -1278,11 +1304,14 @@ GEM
activesupport (>= 3)
attr_required (>= 0.0.5)
httpclient (>= 2.4)
+ sync (0.5.0)
sys-filesystem (1.4.3)
ffi (~> 1.1)
sysexits (1.2.0)
tanuki_emoji (0.6.0)
temple (0.8.2)
+ term-ansicolor (1.7.1)
+ tins (~> 1.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
terser (1.0.2)
@@ -1301,6 +1330,8 @@ GEM
timecop (0.9.1)
timeliness (0.3.10)
timfel-krb5-auth (0.8.3)
+ tins (1.31.0)
+ sync
toml-rb (2.0.1)
citrus (~> 3.0, > 3.0)
tomlrb (1.3.0)
@@ -1595,6 +1626,7 @@ DEPENDENCIES
omniauth-twitter (~> 1.4)
omniauth_crowd (~> 2.4.0)
org-ruby (~> 0.9.12)
+ pact (~> 1.12)
parallel (~> 1.19)
parslet (~> 1.8)
peek (~> 1.1)
diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue
index 915eb2aaee8..6dbf7585283 100644
--- a/app/assets/javascripts/design_management/pages/index.vue
+++ b/app/assets/javascripts/design_management/pages/index.vue
@@ -1,5 +1,6 @@
<script>
import { GlLoadingIcon, GlButton, GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
+import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
import VueDraggable from 'vuedraggable';
import permissionsQuery from 'shared_queries/design_management/design_permissions.query.graphql';
import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql';
@@ -97,6 +98,9 @@ export default {
isSaving() {
return this.filesToBeSaved.length > 0;
},
+ isMobile() {
+ return GlBreakpointInstance.getBreakpointSize() === 'xs';
+ },
canCreateDesign() {
return this.permissions.createDesign;
},
@@ -429,7 +433,7 @@ export default {
<vue-draggable
v-else
:value="designs"
- :disabled="!isLatestVersion || isReorderingInProgress"
+ :disabled="!isLatestVersion || isReorderingInProgress || isMobile"
v-bind="$options.dragOptions"
tag="ol"
draggable=".js-design-tile"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue
index 60111210f5d..9388ef4ba45 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue
@@ -2,6 +2,9 @@
import { GlButton, GlIcon } from '@gitlab/ui';
import { mapActions, mapGetters } from 'vuex';
+// @deprecated This component should only be used when there is no GraphQL API.
+// In most cases you should use
+// `app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget` instead.
export default {
components: {
GlButton,
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue
index 399db978b60..1064cbc26e3 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue
@@ -4,6 +4,9 @@ import { mapGetters, mapState } from 'vuex';
import DropdownContentsCreateView from './dropdown_contents_create_view.vue';
import DropdownContentsLabelsView from './dropdown_contents_labels_view.vue';
+// @deprecated This component should only be used when there is no GraphQL API.
+// In most cases you should use
+// `app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue` instead.
export default {
components: {
DropdownContentsLabelsView,
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue
index 40c1808dfea..3ff3755de46 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue
@@ -2,6 +2,9 @@
import { GlTooltipDirective, GlButton, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
+// @deprecated This component should only be used when there is no GraphQL API.
+// In most cases you should use
+// `app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue` instead.
export default {
components: {
GlButton,
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue
index 70627ec06ca..e235bfde394 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue
@@ -13,6 +13,9 @@ import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/
import LabelItem from './label_item.vue';
+// @deprecated This component should only be used when there is no GraphQL API.
+// In most cases you should use
+// `app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue` instead.
export default {
components: {
GlIntersectionObserver,
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue
index 18ebfe1dc9c..e4325492334 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue
@@ -2,6 +2,9 @@
import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
+// @deprecated This component should only be used when there is no GraphQL API.
+// In most cases you should use
+// `app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue` instead.
export default {
components: {
GlButton,
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue
index 35ac9ef8565..e59d150dd43 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue
@@ -5,6 +5,9 @@ import { mapState } from 'vuex';
import { isScopedLabel } from '~/lib/utils/common_utils';
+// @deprecated This component should only be used when there is no GraphQL API.
+// In most cases you should use
+// `app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue` instead.
export default {
components: {
GlLabel,
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue
index 8a26c4a6618..5966c78aa51 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue
@@ -2,6 +2,9 @@
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
+// @deprecated This component should only be used when there is no GraphQL API.
+// In most cases you should use
+// `app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget` instead.
export default {
directives: {
GlTooltip: GlTooltipDirective,
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/label_item.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/label_item.vue
index 1f52f4c064f..154e3013acd 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/label_item.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/label_item.vue
@@ -2,6 +2,9 @@
import { GlLink, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
+// @deprecated This component should only be used when there is no GraphQL API.
+// In most cases you should use
+// `app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/label_item.vue` instead.
export default {
functional: true,
props: {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
index b514e4a27af..b61996cdcdb 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
@@ -15,6 +15,9 @@ import labelsSelectModule from './store';
Vue.use(Vuex);
+// @deprecated This component should only be used when there is no GraphQL API.
+// In most cases you should use
+// `app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue` instead.
export default {
store: new Vuex.Store(labelsSelectModule()),
components: {
diff --git a/app/assets/stylesheets/page_bundles/issues_show.scss b/app/assets/stylesheets/page_bundles/issues_show.scss
index 4bfe8a3d620..c664e0a734e 100644
--- a/app/assets/stylesheets/page_bundles/issues_show.scss
+++ b/app/assets/stylesheets/page_bundles/issues_show.scss
@@ -24,8 +24,9 @@
/* The inside bullet aligns itself to the bottom, which we see when text to the right of
* a multi-line list item wraps. We fix this by aligning it to the top, and excluding
- * other elements adversely affected by this. Targeting ::marker doesn't seem to work. */
- > *:not(code):not(gl-emoji):not(input):not(.gl-label):not(.js-add-task) {
+ * other elements. Targeting ::marker doesn't seem to work, instead we exclude custom elements
+ * or anything with a class */
+ > *:not(gl-emoji, code, [class]) {
vertical-align: top;
}
diff --git a/app/controllers/ide_controller.rb b/app/controllers/ide_controller.rb
index 2bcbf88039b..9fcb8385312 100644
--- a/app/controllers/ide_controller.rb
+++ b/app/controllers/ide_controller.rb
@@ -22,6 +22,11 @@ class IdeController < ApplicationController
def index
Gitlab::UsageDataCounters::WebIdeCounter.increment_views_count
+
+ if project && Feature.enabled?(:route_hll_to_snowplow_phase2, project&.namespace)
+ Gitlab::Tracking.event(self.class.to_s, 'web_ide_views',
+ namespace: project&.namespace, user: current_user)
+ end
end
private
diff --git a/db/migrate/20220607011733_add_phone_verification_code_enabled_to_application_settings.rb b/db/migrate/20220607011733_add_phone_verification_code_enabled_to_application_settings.rb
new file mode 100644
index 00000000000..321e55a2abf
--- /dev/null
+++ b/db/migrate/20220607011733_add_phone_verification_code_enabled_to_application_settings.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddPhoneVerificationCodeEnabledToApplicationSettings < Gitlab::Database::Migration[2.0]
+ def up
+ add_column :application_settings,
+ :phone_verification_code_enabled,
+ :boolean,
+ null: false,
+ default: false,
+ comment: 'JiHu-specific column'
+ end
+
+ def down
+ remove_column :application_settings, :phone_verification_code_enabled
+ end
+end
diff --git a/db/schema_migrations/20220607011733 b/db/schema_migrations/20220607011733
new file mode 100644
index 00000000000..7581765679c
--- /dev/null
+++ b/db/schema_migrations/20220607011733
@@ -0,0 +1 @@
+2d4dd4b889b5fc9c3f329669734f086997ebb514ed62afe6ca4220fc525797c9 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 9eff36609e7..1c1b57a6648 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -11320,6 +11320,7 @@ CREATE TABLE application_settings (
globally_allowed_ips text DEFAULT ''::text NOT NULL,
container_registry_pre_import_tags_rate numeric(6,2) DEFAULT 0.5 NOT NULL,
license_usage_data_exported boolean DEFAULT false NOT NULL,
+ phone_verification_code_enabled boolean DEFAULT false NOT NULL,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)),
CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)),
@@ -11380,6 +11381,8 @@ COMMENT ON COLUMN application_settings.encrypted_dingtalk_app_secret IS 'JiHu-sp
COMMENT ON COLUMN application_settings.encrypted_dingtalk_app_secret_iv IS 'JiHu-specific column';
+COMMENT ON COLUMN application_settings.phone_verification_code_enabled IS 'JiHu-specific column';
+
CREATE SEQUENCE application_settings_id_seq
START WITH 1
INCREMENT BY 1
diff --git a/doc/api/members.md b/doc/api/members.md
index 1db9714bfd1..5002e1003e3 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -6,6 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Group and project members API **(FREE)**
+> `created_by` field [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/28789) in GitLab 14.10.
+
## Valid access levels
The access levels are defined in the `Gitlab::Access` module. Currently, these levels are recognized:
diff --git a/doc/user/analytics/value_stream_analytics.md b/doc/user/analytics/value_stream_analytics.md
index afefbee7ca0..c0f97369740 100644
--- a/doc/user/analytics/value_stream_analytics.md
+++ b/doc/user/analytics/value_stream_analytics.md
@@ -44,7 +44,7 @@ To view value stream analytics for your project:
- In the **To** field, select an end date.
1. Optional. Sort results by ascending or descending:
- To sort by most recent or oldest workflow item, select the **Last event** header.
- - To sort by most or least amount of time spent in each stage, select the **Time** header.
+ - To sort by most or least amount of time spent in each stage, select the **Duration** header.
The table shows a list of related workflow items for the selected stage. Based on the stage you choose, this can be:
diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md
index c2b729ebcc2..72d42a8081f 100644
--- a/doc/user/group/value_stream_analytics/index.md
+++ b/doc/user/group/value_stream_analytics/index.md
@@ -51,7 +51,7 @@ To view value stream analytics for your group:
during the date range.
1. Optional. Sort results by ascending or descending:
- To sort by most recent or oldest workflow item, select the **Last event** header.
- - To sort by most or least amount of time spent in each stage, select the **Time** header.
+ - To sort by most or least amount of time spent in each stage, select the **Duration** header.
A badge next to the workflow items table header shows the number of workflow items that
completed during the selected stage.
diff --git a/qa/tasks/contracts.rake b/lib/tasks/contracts.rake
index 682ec0e2e21..75c350f5be5 100644
--- a/qa/tasks/contracts.rake
+++ b/lib/tasks/contracts.rake
@@ -1,8 +1,10 @@
# frozen_string_literal: true
+return if Rails.env.production?
+
require 'pact/tasks/verification_task'
-contracts = File.expand_path('../contracts', __dir__)
+contracts = File.expand_path('../../spec/contracts', __dir__)
provider = File.expand_path('provider', contracts)
# rubocop:disable Rails/RakeEnvironment
@@ -11,21 +13,21 @@ namespace :contracts do
Pact::VerificationTask.new(:metadata) do |pact|
pact.uri(
"#{contracts}/contracts/merge_request_page-merge_request_metadata_endpoint.json",
- pact_helper: "#{provider}/spec/metadata_helper.rb"
+ pact_helper: "#{provider}/specs/metadata_helper.rb"
)
end
Pact::VerificationTask.new(:discussions) do |pact|
pact.uri(
"#{contracts}/contracts/merge_request_page-merge_request_discussions_endpoint.json",
- pact_helper: "#{provider}/spec/discussions_helper.rb"
+ pact_helper: "#{provider}/specs/discussions_helper.rb"
)
end
Pact::VerificationTask.new(:diffs) do |pact|
pact.uri(
"#{contracts}/contracts/merge_request_page-merge_request_diffs_endpoint.json",
- pact_helper: "#{provider}/spec/diffs_helper.rb"
+ pact_helper: "#{provider}/specs/diffs_helper.rb"
)
end
diff --git a/qa/Gemfile b/qa/Gemfile
index 28fd1c9394d..d8d00400563 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -35,8 +35,6 @@ gem 'confiner', '~> 0.3'
gem 'chemlab', '~> 0.9'
gem 'chemlab-library-www-gitlab-com', '~> 0.1'
-gem "pact", "~> 1.12"
-
gem 'deprecation_toolkit', '~> 1.5.1', require: false
group :development do
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index ca23c4ac39d..3b89c3ece56 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -28,7 +28,6 @@ GEM
require_all (>= 2, < 4)
uuid (>= 2.3, < 3)
ast (2.4.2)
- awesome_print (1.9.2)
binding_ninja (0.2.3)
builder (3.2.4)
byebug (9.1.0)
@@ -92,8 +91,6 @@ GEM
ffi-compiler (1.0.1)
ffi (>= 1.0.0)
rake
- filelock (1.1.1)
- find_a_port (1.0.1)
fog-core (2.1.0)
builder
excon (~> 0.58)
@@ -177,7 +174,6 @@ GEM
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
influxdb-client (1.17.0)
- json (2.6.1)
jwt (2.3.0)
knapsack (4.0.0)
rake
@@ -210,29 +206,6 @@ GEM
sawyer (~> 0.8.0, >= 0.5.3)
oj (3.13.11)
os (1.1.4)
- pact (1.59.0)
- pact-mock_service (~> 3.0, >= 3.3.1)
- pact-support (~> 1.15)
- rack-test (>= 0.6.3, < 2.0.0)
- rspec (~> 3.0)
- term-ansicolor (~> 1.0)
- thor (>= 0.20, < 2.0)
- webrick (~> 1.3)
- pact-mock_service (3.6.2)
- filelock (~> 1.1)
- find_a_port (~> 1.0.1)
- json
- pact-support (~> 1.12, >= 1.12.0)
- rack (~> 2.0)
- rspec (>= 2.14)
- term-ansicolor (~> 1.0)
- thor (>= 0.19, < 2.0)
- webrick (~> 1.3)
- pact-support (1.15.1)
- awesome_print (~> 1.1)
- randexp (~> 0.1.7)
- rspec (>= 2.14)
- term-ansicolor (~> 1.0)
parallel (1.19.2)
parallel_tests (2.29.0)
parallel
@@ -256,7 +229,6 @@ GEM
rack (>= 1.0, < 3)
rainbow (3.0.0)
rake (13.0.6)
- randexp (0.1.7)
regexp_parser (2.1.1)
representable (3.1.1)
declarative (< 0.1.0)
@@ -311,18 +283,12 @@ GEM
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
slack-notifier (2.4.0)
- sync (0.5.0)
systemu (2.6.5)
table_print (1.5.7)
- term-ansicolor (1.7.1)
- tins (~> 1.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
- thor (1.2.1)
thread_safe (0.3.6)
timecop (0.9.1)
- tins (1.31.0)
- sync
trailblazer-option (0.1.2)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
@@ -372,7 +338,6 @@ DEPENDENCIES
influxdb-client (~> 1.17)
knapsack (~> 4.0)
octokit (~> 4.21)
- pact (~> 1.12)
parallel (~> 1.19)
parallel_tests (~> 2.29)
pry-byebug (~> 3.5.1)
diff --git a/qa/contracts/provider/environments/base.rb b/qa/contracts/provider/environments/base.rb
deleted file mode 100644
index 695ee6b867d..00000000000
--- a/qa/contracts/provider/environments/base.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-module Provider
- module Environments
- class Base
- attr_writer :base_url, :merge_request
-
- def call(env)
- @payload
- end
-
- def http(endpoint)
- Faraday.default_adapter = :net_http
- response = Faraday.get(@base_url + endpoint)
- @payload = [response.status, response.headers, [response.body]]
- self
- end
-
- def merge_request(endpoint)
- http(@merge_request + endpoint) if endpoint.include? '.json'
- end
- end
- end
-end
diff --git a/qa/contracts/provider/environments/local.rb b/qa/contracts/provider/environments/local.rb
deleted file mode 100644
index 0d472bc25e9..00000000000
--- a/qa/contracts/provider/environments/local.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-module Provider
- module Environments
- class Local < Base
- def initialize
- @base_url = ENV['CONTRACT_HOST']
- @merge_request = ENV['CONTRACT_MR']
- end
- end
- end
-end
diff --git a/qa/contracts/provider/spec_helper.rb b/qa/contracts/provider/spec_helper.rb
deleted file mode 100644
index 1869c039910..00000000000
--- a/qa/contracts/provider/spec_helper.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module SpecHelper
- unless ENV['CONTRACT_HOST']
- raise(ArgumentError, 'Contract tests require CONTRACT_HOST environment variable to be set!')
- end
-
- require_relative '../../../config/bundler_setup'
- Bundler.require(:default)
-
- root = File.expand_path('../', __dir__)
-
- loader = Zeitwerk::Loader.new
- loader.push_dir(root)
-
- loader.ignore("#{root}/consumer")
- loader.ignore("#{root}/contracts")
-
- loader.collapse("#{root}/provider/spec")
-
- loader.setup
-end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb
index 85270791f0f..9c55a6cf9a3 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb
@@ -4,6 +4,8 @@ module QA
RSpec.describe 'Create', :runner do
describe 'Merge requests' do
shared_examples 'merge when pipeline succeeds' do |repeat: 1|
+ let(:runner_name) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
+
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'merge-when-pipeline-succeeds'
@@ -14,24 +16,12 @@ module QA
let!(:runner) do
Resource::Runner.fabricate! do |runner|
runner.project = project
- runner.name = "runner-for-#{project.name}"
- runner.tags = ["runner-for-#{project.name}"]
+ runner.name = runner_name
+ runner.tags = [runner_name]
end
end
- before do
- Flow::Login.sign_in
- end
-
- after do
- runner&.remove_via_api!
- project&.remove_via_api!
- end
-
- it 'merges after pipeline succeeds' do
- transient_test = repeat > 1
-
- # Push a new pipeline config file
+ let!(:ci_file) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
@@ -39,60 +29,48 @@ module QA
[
{
file_path: '.gitlab-ci.yml',
- content: <<~EOF
+ content: <<~YAML
test:
- tags: ["runner-for-#{project.name}"]
- script: sleep 30
+ tags: ["#{runner_name}"]
+ script: sleep 5
only:
- merge_requests
- EOF
+ YAML
}
]
)
end
+ end
- repeat.times do |i|
- QA::Runtime::Logger.info("Transient bug test - Trial #{i}") if transient_test
+ before do
+ Flow::Login.sign_in
+ end
- branch_name = "mr-test-#{SecureRandom.hex(6)}-#{i}"
+ after do
+ runner&.remove_via_api!
+ end
- # Create a branch that will be merged into the default branch
- Resource::Repository::ProjectPush.fabricate! do |project_push|
- project_push.project = project
- project_push.new_branch = true
- project_push.branch_name = branch_name
- project_push.file_name = "#{branch_name}.txt"
- end
+ it 'merges after pipeline succeeds' do
+ transient_test = repeat > 1
+
+ repeat.times do |i|
+ QA::Runtime::Logger.info("Transient bug test - Trial #{i + 1}") if transient_test
- # Create a merge request to merge the branch we just created
+ # Create a merge request to trigger pipeline
merge_request = Resource::MergeRequest.fabricate_via_api! do |merge_request|
merge_request.project = project
- merge_request.source_branch = branch_name
- merge_request.no_preparation = true
+ merge_request.description = Faker::Lorem.sentence
+ merge_request.target_new_branch = false
+ merge_request.source_branch = "mr-test-#{SecureRandom.hex(6)}-#{i + 1}"
+ merge_request.file_name = Faker::Lorem.word
+ merge_request.file_content = Faker::Lorem.sentence
end
# Load the page so that the browser is as prepared as possible to display the pipeline in progress when we
# start it.
merge_request.visit!
- # Push a new file to trigger a new pipeline
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add new file'
- commit.branch = branch_name
- commit.add_files(
- [
- {
- file_path: "#{branch_name}-file.md",
- content: "file content"
- }
- ]
- )
- end
-
Page::MergeRequest::Show.perform do |mr|
- mr.refresh
-
# Part of the challenge with this test is that the MR widget has many components that could be displayed
# and many errors states that those components could encounter. Most of the time few of those
# possible components will be relevant, so it would be inefficient for this test to check for each of
@@ -102,8 +80,6 @@ module QA
mr.wait_until_ready_to_merge(transient_test: transient_test)
mr.retry_until(reload: true, message: 'Wait until ready to click MWPS') do
- merge_request.reload!
-
# Click the MWPS button if we can
break mr.merge_when_pipeline_succeeds! if mr.has_element?(:merge_button, text: 'Merge when pipeline succeeds')
diff --git a/qa/contracts/.gitignore b/spec/contracts/.gitignore
index cb89d4102d3..cb89d4102d3 100644
--- a/qa/contracts/.gitignore
+++ b/spec/contracts/.gitignore
diff --git a/qa/contracts/consumer/.node-version b/spec/contracts/consumer/.node-version
index 18711d290ea..18711d290ea 100644
--- a/qa/contracts/consumer/.node-version
+++ b/spec/contracts/consumer/.node-version
diff --git a/qa/contracts/consumer/endpoints/merge_request.js b/spec/contracts/consumer/endpoints/merge_requests.js
index 74fd4e75bec..04e66c57dc9 100644
--- a/qa/contracts/consumer/endpoints/merge_request.js
+++ b/spec/contracts/consumer/endpoints/merge_requests.js
@@ -9,7 +9,7 @@ exports.getMetadata = (endpoint) => {
.request({
method: 'GET',
baseURL: url,
- url: '/diffs_metadata.json',
+ url: '/gitlab-org/gitlab-qa/-/merge_requests/1/diffs_metadata.json',
headers: { Accept: '*/*' },
})
.then((response) => response.data);
@@ -22,7 +22,7 @@ exports.getDiscussions = (endpoint) => {
.request({
method: 'GET',
baseURL: url,
- url: '/discussions.json',
+ url: '/gitlab-org/gitlab-qa/-/merge_requests/1/discussions.json',
headers: { Accept: '*/*' },
})
.then((response) => response.data);
@@ -35,7 +35,7 @@ exports.getDiffs = (endpoint) => {
.request({
method: 'GET',
baseURL: url,
- url: '/diffs_batch.json?page=0',
+ url: '/gitlab-org/gitlab-qa/-/merge_requests/1/diffs_batch.json?page=0',
headers: { Accept: '*/*' },
})
.then((response) => response.data);
diff --git a/qa/contracts/consumer/fixtures/diffs.fixture.js b/spec/contracts/consumer/fixtures/diffs.fixture.js
index 286d71f421c..7dbe825b093 100644
--- a/qa/contracts/consumer/fixtures/diffs.fixture.js
+++ b/spec/contracts/consumer/fixtures/diffs.fixture.js
@@ -77,7 +77,7 @@ const Diffs = {
uponReceiving: 'a request for diff lines',
withRequest: {
method: 'GET',
- path: '/diffs_batch.json',
+ path: '/gitlab-org/gitlab-qa/-/merge_requests/1/diffs_batch.json',
headers: {
Accept: '*/*',
},
diff --git a/qa/contracts/consumer/fixtures/discussions.fixture.js b/spec/contracts/consumer/fixtures/discussions.fixture.js
index cfc6112561b..c28b9bdd505 100644
--- a/qa/contracts/consumer/fixtures/discussions.fixture.js
+++ b/spec/contracts/consumer/fixtures/discussions.fixture.js
@@ -74,7 +74,7 @@ const Discussions = {
uponReceiving: 'a request for discussions',
withRequest: {
method: 'GET',
- path: '/discussions.json',
+ path: '/gitlab-org/gitlab-qa/-/merge_requests/1/discussions.json',
headers: {
Accept: '*/*',
},
diff --git a/qa/contracts/consumer/fixtures/metadata.fixture.js b/spec/contracts/consumer/fixtures/metadata.fixture.js
index 05a4831c447..3fca6cf9181 100644
--- a/qa/contracts/consumer/fixtures/metadata.fixture.js
+++ b/spec/contracts/consumer/fixtures/metadata.fixture.js
@@ -85,7 +85,7 @@ const Metadata = {
uponReceiving: 'a request for Metadata',
withRequest: {
method: 'GET',
- path: '/diffs_metadata.json',
+ path: '/gitlab-org/gitlab-qa/-/merge_requests/1/diffs_metadata.json',
headers: {
Accept: '*/*',
},
diff --git a/qa/contracts/consumer/package.json b/spec/contracts/consumer/package.json
index b4a3f59e89e..6a427ff8a7b 100644
--- a/qa/contracts/consumer/package.json
+++ b/spec/contracts/consumer/package.json
@@ -12,6 +12,6 @@
"prettier": "^2.5.1"
},
"scripts": {
- "test": "jest specs/ --runInBand"
+ "test": "jest --runInBand"
}
}
diff --git a/qa/contracts/consumer/specs/diffs.spec.js b/spec/contracts/consumer/specs/diffs.spec.js
index 5be2ed7ac00..b812461cb69 100644
--- a/qa/contracts/consumer/specs/diffs.spec.js
+++ b/spec/contracts/consumer/specs/diffs.spec.js
@@ -3,7 +3,7 @@
const { pactWith } = require('jest-pact');
const { Diffs } = require('../fixtures/diffs.fixture');
-const { getDiffs } = require('../endpoints/merge_request');
+const { getDiffs } = require('../endpoints/merge_requests');
pactWith(
{
@@ -17,10 +17,11 @@ pactWith(
describe('Diffs Endpoint', () => {
beforeEach(() => {
const interaction = {
+ state: 'a merge request with diffs exists',
...Diffs.request,
willRespondWith: Diffs.success,
};
- return provider.addInteraction(interaction);
+ provider.addInteraction(interaction);
});
it('return a successful body', () => {
diff --git a/qa/contracts/consumer/specs/discussions.spec.js b/spec/contracts/consumer/specs/discussions.spec.js
index 28ee3186a9f..304c240f7d3 100644
--- a/qa/contracts/consumer/specs/discussions.spec.js
+++ b/spec/contracts/consumer/specs/discussions.spec.js
@@ -3,7 +3,7 @@
const { pactWith } = require('jest-pact');
const { Discussions } = require('../fixtures/discussions.fixture');
-const { getDiscussions } = require('../endpoints/merge_request');
+const { getDiscussions } = require('../endpoints/merge_requests');
pactWith(
{
@@ -17,10 +17,11 @@ pactWith(
describe('Discussions Endpoint', () => {
beforeEach(() => {
const interaction = {
+ state: 'a merge request with discussions exists',
...Discussions.request,
willRespondWith: Discussions.success,
};
- return provider.addInteraction(interaction);
+ provider.addInteraction(interaction);
});
it('return a successful body', () => {
diff --git a/qa/contracts/consumer/specs/metadata.spec.js b/spec/contracts/consumer/specs/metadata.spec.js
index 31fc398f228..c49d4c354b1 100644
--- a/qa/contracts/consumer/specs/metadata.spec.js
+++ b/spec/contracts/consumer/specs/metadata.spec.js
@@ -3,7 +3,7 @@
const { pactWith } = require('jest-pact');
const { Metadata } = require('../fixtures/metadata.fixture');
-const { getMetadata } = require('../endpoints/merge_request');
+const { getMetadata } = require('../endpoints/merge_requests');
pactWith(
{
@@ -17,10 +17,11 @@ pactWith(
describe('Metadata Endpoint', () => {
beforeEach(() => {
const interaction = {
+ state: 'a merge request exists',
...Metadata.request,
willRespondWith: Metadata.success,
};
- return provider.addInteraction(interaction);
+ provider.addInteraction(interaction);
});
it('return a successful body', () => {
diff --git a/qa/contracts/contracts/merge_request_page-merge_request_diffs_endpoint.json b/spec/contracts/contracts/merge_request_page-merge_request_diffs_endpoint.json
index 8df54c25326..2f097d8eb24 100644
--- a/qa/contracts/contracts/merge_request_page-merge_request_diffs_endpoint.json
+++ b/spec/contracts/contracts/merge_request_page-merge_request_diffs_endpoint.json
@@ -8,9 +8,10 @@
"interactions": [
{
"description": "a request for diff lines",
+ "providerState": "a merge request with diffs exists",
"request": {
"method": "GET",
- "path": "/diffs_batch.json",
+ "path": "/gitlab-org/gitlab-qa/-/merge_requests/1/diffs_batch.json",
"query": "page=0",
"headers": {
"Accept": "*/*"
@@ -225,4 +226,4 @@
"version": "2.0.0"
}
}
-} \ No newline at end of file
+}
diff --git a/qa/contracts/contracts/merge_request_page-merge_request_discussions_endpoint.json b/spec/contracts/contracts/merge_request_page-merge_request_discussions_endpoint.json
index 14839053e57..819d95276b3 100644
--- a/qa/contracts/contracts/merge_request_page-merge_request_discussions_endpoint.json
+++ b/spec/contracts/contracts/merge_request_page-merge_request_discussions_endpoint.json
@@ -8,9 +8,10 @@
"interactions": [
{
"description": "a request for discussions",
+ "providerState": "a merge request with discussions exists",
"request": {
"method": "GET",
- "path": "/discussions.json",
+ "path": "/gitlab-org/gitlab-qa/-/merge_requests/1/discussions.json",
"headers": {
"Accept": "*/*"
}
@@ -232,4 +233,4 @@
"version": "2.0.0"
}
}
-} \ No newline at end of file
+}
diff --git a/qa/contracts/contracts/merge_request_page-merge_request_metadata_endpoint.json b/spec/contracts/contracts/merge_request_page-merge_request_metadata_endpoint.json
index 4b6cab0fc94..eb22b7d2e3c 100644
--- a/qa/contracts/contracts/merge_request_page-merge_request_metadata_endpoint.json
+++ b/spec/contracts/contracts/merge_request_page-merge_request_metadata_endpoint.json
@@ -8,9 +8,10 @@
"interactions": [
{
"description": "a request for Metadata",
+ "providerState": "a merge request exists",
"request": {
"method": "GET",
- "path": "/diffs_metadata.json",
+ "path": "/gitlab-org/gitlab-qa/-/merge_requests/1/diffs_metadata.json",
"headers": {
"Accept": "*/*"
}
@@ -219,4 +220,4 @@
"version": "2.0.0"
}
}
-} \ No newline at end of file
+}
diff --git a/spec/contracts/provider/environments/test.rb b/spec/contracts/provider/environments/test.rb
new file mode 100644
index 00000000000..6efb19508d8
--- /dev/null
+++ b/spec/contracts/provider/environments/test.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Provider
+ module Environments
+ class Test
+ def self.app
+ Rack::Builder.app do
+ map "/" do
+ run Gitlab::Application
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/contracts/provider/helpers/users_helper.rb b/spec/contracts/provider/helpers/users_helper.rb
new file mode 100644
index 00000000000..1982bd9cfd2
--- /dev/null
+++ b/spec/contracts/provider/helpers/users_helper.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module Provider
+ module UsersHelper
+ CONTRACT_USER_NAME = "Contract Test User"
+ end
+end
diff --git a/spec/contracts/provider/spec_helper.rb b/spec/contracts/provider/spec_helper.rb
new file mode 100644
index 00000000000..6009d6524e1
--- /dev/null
+++ b/spec/contracts/provider/spec_helper.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'zeitwerk'
+require_relative 'helpers/users_helper'
+
+RSpec.configure do |config|
+ config.include Devise::Test::IntegrationHelpers
+ config.include FactoryBot::Syntax::Methods
+
+ config.before do
+ user = create(:user, name: Provider::UsersHelper::CONTRACT_USER_NAME).tap do |user|
+ user.current_sign_in_at = Time.current
+ end
+
+ sign_in user
+ end
+end
+
+Pact.configure do |config|
+ config.include FactoryBot::Syntax::Methods
+end
+
+module SpecHelper
+ require_relative '../../../config/bundler_setup'
+ Bundler.require(:default)
+
+ root = File.expand_path('../', __dir__)
+
+ loader = Zeitwerk::Loader.new
+ loader.push_dir(root)
+
+ loader.ignore("#{root}/consumer")
+ loader.ignore("#{root}/contracts")
+
+ loader.collapse("#{root}/provider/spec")
+
+ loader.setup
+end
diff --git a/qa/contracts/provider/spec/diffs_helper.rb b/spec/contracts/provider/specs/diffs_helper.rb
index 95dbc4254e6..24bdd00dbae 100644
--- a/qa/contracts/provider/spec/diffs_helper.rb
+++ b/spec/contracts/provider/specs/diffs_helper.rb
@@ -1,13 +1,12 @@
# frozen_string_literal: true
require_relative '../spec_helper'
+require_relative '../states/diffs_state'
module Provider
module DiffsHelper
- local = Environments::Local.new
-
Pact.service_provider "Merge Request Diffs Endpoint" do
- app { local.merge_request('/diffs_batch.json?page=0') }
+ app { Environments::Test.app }
honours_pact_with 'Merge Request Page' do
pact_uri '../contracts/merge_request_page-merge_request_diffs_endpoint.json'
diff --git a/qa/contracts/provider/spec/discussions_helper.rb b/spec/contracts/provider/specs/discussions_helper.rb
index 642dde79e1d..135ccf48276 100644
--- a/qa/contracts/provider/spec/discussions_helper.rb
+++ b/spec/contracts/provider/specs/discussions_helper.rb
@@ -1,13 +1,12 @@
# frozen_string_literal: true
require_relative '../spec_helper'
+require_relative '../states/discussions_state'
module Provider
module DiscussionsHelper
- local = Environments::Local.new
-
Pact.service_provider "Merge Request Discussions Endpoint" do
- app { local.merge_request('/discussions.json') }
+ app { Environments::Test.app }
honours_pact_with 'Merge Request Page' do
pact_uri '../contracts/merge_request_page-merge_request_discussions_endpoint.json'
diff --git a/qa/contracts/provider/spec/metadata_helper.rb b/spec/contracts/provider/specs/metadata_helper.rb
index a3eb4978641..e73b993a31a 100644
--- a/qa/contracts/provider/spec/metadata_helper.rb
+++ b/spec/contracts/provider/specs/metadata_helper.rb
@@ -1,13 +1,12 @@
# frozen_string_literal: true
require_relative '../spec_helper'
+require_relative '../states/metadata_state'
module Provider
module MetadataHelper
- local = Environments::Local.new
-
Pact.service_provider "Merge Request Metadata Endpoint" do
- app { local.merge_request('/diffs_metadata.json') }
+ app { Environments::Test.app }
honours_pact_with 'Merge Request Page' do
pact_uri '../contracts/merge_request_page-merge_request_metadata_endpoint.json'
diff --git a/spec/contracts/provider/states/diffs_state.rb b/spec/contracts/provider/states/diffs_state.rb
new file mode 100644
index 00000000000..d959cde5f5e
--- /dev/null
+++ b/spec/contracts/provider/states/diffs_state.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+Pact.provider_states_for "Merge Request Page" do
+ provider_state "a merge request with diffs exists" do
+ set_up do
+ user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
+ namespace = create(:namespace, name: 'gitlab-org')
+ project = create(:project, :custom_repo, name: 'gitlab-qa', namespace: namespace, files: {})
+
+ project.add_maintainer(user)
+
+ merge_request = create(:merge_request_with_multiple_diffs, source_project: project)
+ merge_request_diff = create(:merge_request_diff, merge_request: merge_request)
+
+ create(:merge_request_diff_file, :new_file, merge_request_diff: merge_request_diff)
+ end
+ end
+end
diff --git a/spec/contracts/provider/states/discussions_state.rb b/spec/contracts/provider/states/discussions_state.rb
new file mode 100644
index 00000000000..ddbcf80f2c8
--- /dev/null
+++ b/spec/contracts/provider/states/discussions_state.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+Pact.provider_states_for "Merge Request Page" do
+ provider_state "a merge request with discussions exists" do
+ set_up do
+ user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
+ namespace = create(:namespace, name: 'gitlab-org')
+ project = create(:project, name: 'gitlab-qa', namespace: namespace)
+
+ project.add_maintainer(user)
+
+ merge_request = create(:merge_request_with_diffs, source_project: project, author: user)
+
+ create(:discussion_note_on_merge_request, noteable: merge_request, project: project, author: user)
+ end
+ end
+end
diff --git a/spec/contracts/provider/states/metadata_state.rb b/spec/contracts/provider/states/metadata_state.rb
new file mode 100644
index 00000000000..59b290ce2fe
--- /dev/null
+++ b/spec/contracts/provider/states/metadata_state.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+Pact.provider_states_for "Merge Request Page" do
+ provider_state "a merge request exists" do
+ set_up do
+ user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
+ namespace = create(:namespace, name: 'gitlab-org')
+ project = create(:project, :custom_repo, name: 'gitlab-qa', namespace: namespace, files: {})
+
+ project.add_maintainer(user)
+
+ merge_request = create(:merge_request, source_project: project)
+ merge_request_diff = create(:merge_request_diff, merge_request: merge_request)
+
+ create(:merge_request_diff_file, :new_file, merge_request_diff: merge_request_diff)
+ end
+ end
+end
diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js
index 87531e8b645..087655d10f7 100644
--- a/spec/frontend/design_management/pages/index_spec.js
+++ b/spec/frontend/design_management/pages/index_spec.js
@@ -4,6 +4,7 @@ import Vue, { nextTick } from 'vue';
import VueApollo, { ApolloMutation } from 'vue-apollo';
import VueRouter from 'vue-router';
+import { GlBreakpointInstance as breakpointInstance } from '@gitlab/ui/dist/utils';
import VueDraggable from 'vuedraggable';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -762,6 +763,25 @@ describe('Design management index page', () => {
expect(findDesigns().at(0).props('id')).toBe('2');
});
+ it.each`
+ breakpoint | reorderDisabled
+ ${'xs'} | ${true}
+ ${'sm'} | ${false}
+ ${'md'} | ${false}
+ ${'lg'} | ${false}
+ ${'xl'} | ${false}
+ `(
+ 'sets draggable disabled value to $reorderDisabled when breakpoint is $breakpoint',
+ async ({ breakpoint, reorderDisabled }) => {
+ jest.spyOn(breakpointInstance, 'getBreakpointSize').mockReturnValue(breakpoint);
+
+ createComponentWithApollo({});
+ await waitForPromises();
+
+ expect(draggableAttributes().disabled).toBe(reorderDisabled);
+ },
+ );
+
it('prevents reordering when reorderDesigns mutation is in progress', async () => {
createComponentWithApollo({});
await moveDesigns(wrapper);
diff --git a/spec/requests/ide_controller_spec.rb b/spec/requests/ide_controller_spec.rb
index 4bf1e43ba40..151fa89b819 100644
--- a/spec/requests/ide_controller_spec.rb
+++ b/spec/requests/ide_controller_spec.rb
@@ -208,6 +208,31 @@ RSpec.describe IdeController do
it_behaves_like 'user access rights check'
end
+
+ describe 'Snowplow view event', :snowplow do
+ it 'is tracked' do
+ subject
+
+ expect_snowplow_event(
+ category: described_class.to_s,
+ action: 'web_ide_views',
+ namespace: project.namespace,
+ user: user
+ )
+ end
+
+ context 'when route_hll_to_snowplow_phase2 FF is disabled' do
+ before do
+ stub_feature_flags(route_hll_to_snowplow_phase2: false)
+ end
+
+ it 'does not track Snowplow event' do
+ subject
+
+ expect_no_snowplow_event
+ end
+ end
+ end
end
end
end