Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
bed53d96d2
commit
bdd03bc52a
|
@ -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:
|
||||
|
|
2
Gemfile
2
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
|
||||
|
|
32
Gemfile.lock
32
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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
2d4dd4b889b5fc9c3f329669734f086997ebb514ed62afe6ca4220fc525797c9
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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,8 +16,29 @@ 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
|
||||
|
||||
let!(:ci_file) do
|
||||
Resource::Repository::Commit.fabricate_via_api! do |commit|
|
||||
commit.project = project
|
||||
commit.commit_message = 'Add .gitlab-ci.yml'
|
||||
commit.add_files(
|
||||
[
|
||||
{
|
||||
file_path: '.gitlab-ci.yml',
|
||||
content: <<~YAML
|
||||
test:
|
||||
tags: ["#{runner_name}"]
|
||||
script: sleep 5
|
||||
only:
|
||||
- merge_requests
|
||||
YAML
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -25,74 +48,29 @@ module QA
|
|||
|
||||
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
|
||||
Resource::Repository::Commit.fabricate_via_api! do |commit|
|
||||
commit.project = project
|
||||
commit.commit_message = 'Add .gitlab-ci.yml'
|
||||
commit.add_files(
|
||||
[
|
||||
{
|
||||
file_path: '.gitlab-ci.yml',
|
||||
content: <<~EOF
|
||||
test:
|
||||
tags: ["runner-for-#{project.name}"]
|
||||
script: sleep 30
|
||||
only:
|
||||
- merge_requests
|
||||
EOF
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
repeat.times do |i|
|
||||
QA::Runtime::Logger.info("Transient bug test - Trial #{i}") if transient_test
|
||||
QA::Runtime::Logger.info("Transient bug test - Trial #{i + 1}") if transient_test
|
||||
|
||||
branch_name = "mr-test-#{SecureRandom.hex(6)}-#{i}"
|
||||
|
||||
# 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
|
||||
|
||||
# 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')
|
||||
|
||||
|
|
|
@ -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);
|
|
@ -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: '*/*',
|
||||
},
|
|
@ -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: '*/*',
|
||||
},
|
|
@ -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: '*/*',
|
||||
},
|
|
@ -12,6 +12,6 @@
|
|||
"prettier": "^2.5.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest specs/ --runInBand"
|
||||
"test": "jest --runInBand"
|
||||
}
|
||||
}
|
|
@ -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', () => {
|
|
@ -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', () => {
|
|
@ -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', () => {
|
|
@ -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": "*/*"
|
|
@ -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": "*/*"
|
||||
}
|
|
@ -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": "*/*"
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Provider
|
||||
module UsersHelper
|
||||
CONTRACT_USER_NAME = "Contract Test User"
|
||||
end
|
||||
end
|
|
@ -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
|
|
@ -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'
|
|
@ -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'
|
|
@ -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'
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue