Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-05-16 06:14:41 +00:00
parent cc273dad6e
commit c1ce2b78fa
69 changed files with 375 additions and 356 deletions

View File

@ -18,10 +18,6 @@ stages:
- GIT_DEPTH
- GIT_STRATEGY
workflow:
auto_cancel:
on_new_commit: none
variables:
GIT_DEPTH: 20
GIT_STRATEGY: fetch
@ -66,16 +62,11 @@ release-environments-deploy:
variables:
VERSIONS: "${VERSIONS}"
ENVIRONMENT: "${ENVIRONMENT}"
before_script:
# Make sure pipelines run in order
# See https://docs.gitlab.com/ee/ci/resource_groups/index.html#change-the-process-mode
- curl --request PUT --data "process_mode=oldest_first" --header "PRIVATE-TOKEN:${ENVIRONMENT_API_TOKEN}" "https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/resource_groups/release-environment-${CI_COMMIT_REF_SLUG}"
trigger:
project: gitlab-com/gl-infra/release-environments
branch: main
strategy: depend
needs: ["release-environments-deploy-env"]
resource_group: release-environment-${CI_COMMIT_REF_SLUG}
release-environments-qa:
stage: qa
@ -89,7 +80,6 @@ release-environments-qa:
GITLAB_INITIAL_ROOT_PASSWORD: "${RELEASE_ENVIRONMENTS_ROOT_PASSWORD}"
QA_PRAEFECT_REPOSITORY_STORAGE: "default"
SIGNUP_DISABLED: "true"
resource_group: release-environment-${CI_COMMIT_REF_SLUG}
release-environments-notification-failure:
stage: finish

View File

@ -934,6 +934,7 @@ Gitlab/NamespacedClass:
- 'ee/db/**/*.rb'
- 'ee/elastic/**/*.rb'
- 'scripts/**/*'
- 'spec/fixtures/migrations/**/*.rb'
- 'spec/migrations/**/*.rb'
- 'app/experiments/**/*_experiment.rb'
- 'ee/app/experiments/**/*_experiment.rb'

View File

@ -2,19 +2,6 @@
# Cop supports --autocorrect.
Layout/FirstHashElementIndentation:
Exclude:
- 'app/controllers/admin/system_info_controller.rb'
- 'app/controllers/concerns/milestone_actions.rb'
- 'app/controllers/concerns/render_service_results.rb'
- 'app/controllers/concerns/sourcegraph_decorator.rb'
- 'app/controllers/projects/badges_controller.rb'
- 'app/controllers/projects/merge_requests_controller.rb'
- 'app/controllers/repositories/lfs_locks_api_controller.rb'
- 'app/graphql/mutations/notes/create/diff_note.rb'
- 'app/graphql/mutations/notes/create/image_diff_note.rb'
- 'app/graphql/mutations/notes/create/note.rb'
- 'app/graphql/resolvers/ci/runner_projects_resolver.rb'
- 'app/graphql/resolvers/group_packages_resolver.rb'
- 'app/helpers/commits_helper.rb'
- 'app/helpers/projects/project_members_helper.rb'
- 'app/helpers/search_helper.rb'
- 'app/helpers/ssh_keys_helper.rb'

View File

@ -2,7 +2,6 @@
<script>
import { GlAlert, GlButton, GlFormSelect, GlFormGroup, GlIcon, GlLink, GlToken } from '@gitlab/ui';
import { isNumber } from 'lodash';
import Vue from 'vue';
import { s__, __ } from '~/locale';
import {
EMPTY_PARAMETERS,
@ -114,7 +113,8 @@ export default {
},
removeScope(environment) {
if (isNumber(environment.id)) {
Vue.set(environment, 'shouldBeDestroyed', true);
// eslint-disable-next-line no-param-reassign
environment.shouldBeDestroyed = true;
} else {
this.environments = this.environments.filter((e) => e !== environment);
}

View File

@ -1,10 +1,11 @@
import Vue from 'vue';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import * as types from './mutation_types';
const updateFlag = (state, flag) => {
const index = state.featureFlags.findIndex(({ id }) => id === flag.id);
Vue.set(state.featureFlags, index, flag);
const copy = [...state.featureFlags];
copy[index] = flag;
state.featureFlags = copy;
};
const createPaginationInfo = (headers) => {

View File

@ -39,7 +39,6 @@ import { getParameterByName, joinPaths } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import {
OPERATORS_IS,
OPERATORS_IS_NOT,
OPERATORS_IS_NOT_OR,
OPERATORS_AFTER_BEFORE,
TOKEN_TITLE_ASSIGNEE,
@ -309,9 +308,6 @@ export default {
typeTokenOptions() {
return [...defaultTypeTokenOptions, ...this.eeTypeTokenOptions];
},
hasOrFeature() {
return this.glFeatures.orIssuableQueries;
},
hasSearch() {
return Boolean(
this.searchQuery ||
@ -383,7 +379,7 @@ export default {
token: UserToken,
dataType: 'user',
defaultUsers: [],
operators: this.hasOrFeature ? OPERATORS_IS_NOT_OR : OPERATORS_IS_NOT,
operators: OPERATORS_IS_NOT_OR,
fullPath: this.fullPath,
isProject: this.isProject,
recentSuggestionsStorageKey: `${this.fullPath}-issues-recent-tokens-author`,
@ -396,7 +392,7 @@ export default {
icon: 'user',
token: UserToken,
dataType: 'user',
operators: this.hasOrFeature ? OPERATORS_IS_NOT_OR : OPERATORS_IS_NOT,
operators: OPERATORS_IS_NOT_OR,
fullPath: this.fullPath,
isProject: this.isProject,
recentSuggestionsStorageKey: `${this.fullPath}-issues-recent-tokens-assignee`,
@ -418,7 +414,7 @@ export default {
title: TOKEN_TITLE_LABEL,
icon: 'labels',
token: LabelToken,
operators: this.hasOrFeature ? OPERATORS_IS_NOT_OR : OPERATORS_IS_NOT,
operators: OPERATORS_IS_NOT_OR,
fetchLabels: this.fetchLabels,
fetchLatestLabels: this.glFeatures.frontendCaching ? this.fetchLatestLabels : null,
recentSuggestionsStorageKey: `${this.fullPath}-issues-recent-tokens-label`,
@ -956,12 +952,12 @@ export default {
:show-bulk-edit-sidebar="showBulkEditSidebar"
:show-pagination-controls="showPaginationControls"
:default-page-size="pageSize"
show-filtered-search-friendly-text
sync-filter-and-sort
use-keyset-pagination
:show-page-size-change-controls="showPageSizeControls"
:has-next-page="pageInfo.hasNextPage"
:has-previous-page="pageInfo.hasPreviousPage"
:show-filtered-search-friendly-text="hasOrFeature"
:is-grid-view="isGridView"
:active-issuable="activeIssuable"
show-work-item-type-icon

View File

@ -21,10 +21,7 @@ import {
getFilterTokens,
getSortOptions,
} from '~/issues/list/utils';
import {
OPERATORS_IS_NOT,
OPERATORS_IS_NOT_OR,
} from '~/vue_shared/components/filtered_search_bar/constants';
import { OPERATORS_IS_NOT_OR } from '~/vue_shared/components/filtered_search_bar/constants';
import {
CLOSED_MOVED,
CLOSED,
@ -247,9 +244,6 @@ export default {
canShowIssuesList() {
return this.isLoading || this.issuesError.length || this.hasAnyServiceDeskIssue;
},
hasOrFeature() {
return this.glFeatures.orIssuableQueries;
},
hasSearch() {
return Boolean(
this.searchQuery ||
@ -285,7 +279,7 @@ export default {
},
{
...assigneeTokenBase,
operators: this.hasOrFeature ? OPERATORS_IS_NOT_OR : OPERATORS_IS_NOT,
operators: OPERATORS_IS_NOT_OR,
fetchUsers: this.fetchUsers,
recentSuggestionsStorageKey: `${this.fullPath}-issues-recent-tokens-assignee`,
preloadedUsers,
@ -297,7 +291,7 @@ export default {
},
{
...labelTokenBase,
operators: this.hasOrFeature ? OPERATORS_IS_NOT_OR : OPERATORS_IS_NOT,
operators: OPERATORS_IS_NOT_OR,
fetchLabels: this.fetchLabels,
fetchLatestLabels: this.glFeatures.frontendCaching ? this.fetchLatestLabels : null,
recentSuggestionsStorageKey: `${this.fullPath}-issues-recent-tokens-label`,
@ -575,7 +569,6 @@ export default {
:search-tokens="searchTokens"
:issuables-loading="isLoading"
:initial-filter-value="filterTokens"
:show-filtered-search-friendly-text="hasOrFeature"
:show-pagination-controls="showPaginationControls"
:show-page-size-change-controls="showPageSizeControls"
:sort-options="sortOptions"
@ -588,6 +581,7 @@ export default {
:default-page-size="pageSize"
:has-next-page="pageInfo.hasNextPage"
:has-previous-page="pageInfo.hasPreviousPage"
show-filtered-search-friendly-text
sync-filter-and-sort
use-keyset-pagination
@click-tab="handleClickTab"

View File

@ -99,12 +99,12 @@ table {
tr.responsive-table-border-start,
tr.responsive-table-border-end {
display: block;
border: solid $gl-text-color-quaternary;
border: solid $gray-100;
padding-left: 0;
padding-right: 0;
> td {
border-color: $gl-text-color-quaternary;
border-color: $gray-100;
&,
&:last-child {
@ -125,7 +125,7 @@ table {
}
> td:last-child {
border-bottom: 1px solid $gl-text-color-quaternary;
border-bottom: 1px solid $gray-100;
}
}

View File

@ -135,7 +135,6 @@ $gl-font-weight-bold: 600;
$gl-text-color: $gray-900;
$gl-text-color-secondary: $gray-500 !default;
$gl-text-color-tertiary: $gray-400;
$gl-text-color-quaternary: #d6d6d6;
$gl-text-color-inverted: $white;
$gl-text-color-secondary-inverted: rgba($white, 0.85);
$gl-text-color-disabled: $gray-400;

View File

@ -759,7 +759,7 @@ $tabs-holder-z-index: 250;
border: 1px solid var(--border-color, $border-color);
.circle-icon-container {
color: var(--gray-100, $gl-text-color-quaternary);
color: var(--gray-100, $gray-100);
}
}
}

View File

@ -59,11 +59,11 @@ class Admin::SystemInfoController < Admin::ApplicationController
begin
disk = Sys::Filesystem.stat(mount.mount_point)
@disks.push({
bytes_total: disk.bytes_total,
bytes_used: disk.bytes_used,
disk_name: mount.name,
mount_path: disk.path
})
bytes_total: disk.bytes_total,
bytes_used: disk.bytes_used,
disk_name: mount.name,
mount_path: disk.path
})
rescue Sys::Filesystem::Error
end
end

View File

@ -8,9 +8,9 @@ module MilestoneActions
format.html { redirect_to milestone_redirect_path }
format.json do
render json: tabs_json("shared/milestones/_issues_tab", {
issues: @milestone.sorted_issues(current_user), # rubocop:disable Gitlab/ModuleWithInstanceVariables
show_project_name: Gitlab::Utils.to_boolean(params[:show_project_name])
})
issues: @milestone.sorted_issues(current_user), # rubocop:disable Gitlab/ModuleWithInstanceVariables
show_project_name: Gitlab::Utils.to_boolean(params[:show_project_name])
})
end
end
end
@ -20,9 +20,9 @@ module MilestoneActions
format.html { redirect_to milestone_redirect_path }
format.json do
render json: tabs_json("shared/milestones/_merge_requests_tab", {
merge_requests: @milestone.sorted_merge_requests(current_user).preload_milestoneish_associations, # rubocop:disable Gitlab/ModuleWithInstanceVariables
show_project_name: Gitlab::Utils.to_boolean(params[:show_project_name])
})
merge_requests: @milestone.sorted_merge_requests(current_user).preload_milestoneish_associations, # rubocop:disable Gitlab/ModuleWithInstanceVariables
show_project_name: Gitlab::Utils.to_boolean(params[:show_project_name])
})
end
end
end
@ -32,8 +32,8 @@ module MilestoneActions
format.html { redirect_to milestone_redirect_path }
format.json do
render json: tabs_json("shared/milestones/_participants_tab", {
users: @milestone.issue_participants_visible_by_user(current_user) # rubocop:disable Gitlab/ModuleWithInstanceVariables
})
users: @milestone.issue_participants_visible_by_user(current_user) # rubocop:disable Gitlab/ModuleWithInstanceVariables
})
end
end
end
@ -46,10 +46,10 @@ module MilestoneActions
milestone_labels = @milestone.issue_labels_visible_by_user(current_user)
render json: tabs_json("shared/milestones/_labels_tab", {
labels: milestone_labels.map do |label|
label.present(issuable_subject: @milestone.resource_parent)
end
})
labels: milestone_labels.map do |label|
label.present(issuable_subject: @milestone.resource_parent)
end
})
end
end
end

View File

@ -5,25 +5,25 @@ module RenderServiceResults
def success_response(result)
render({
status: result[:http_status],
json: result[:body]
})
status: result[:http_status],
json: result[:body]
})
end
def continue_polling_response
render({
status: :no_content,
json: {
status: _('processing'),
message: _('Not ready yet. Try again later.')
}
})
status: :no_content,
json: {
status: _('processing'),
message: _('Not ready yet. Try again later.')
}
})
end
def error_response(result)
render({
status: result[:http_status] || :bad_request,
json: { status: result[:status], message: result[:message] }
})
status: result[:http_status] || :bad_request,
json: { status: result[:status], message: result[:message] }
})
end
end

View File

@ -22,8 +22,8 @@ module SourcegraphDecorator
return unless sourcegraph_enabled?
gon.push({
sourcegraph: { url: Gitlab::CurrentSettings.sourcegraph_url }
})
sourcegraph: { url: Gitlab::CurrentSettings.sourcegraph_url }
})
end
def sourcegraph_enabled?

View File

@ -36,7 +36,6 @@ class GroupsController < Groups::ApplicationController
before_action :check_export_rate_limit!, only: [:export, :download_export]
before_action only: :issues do
push_frontend_feature_flag(:or_issuable_queries, group)
push_frontend_feature_flag(:frontend_caching, group)
push_force_frontend_feature_flag(:work_items, group.work_items_feature_flag_enabled?)
push_force_frontend_feature_flag(:work_items_beta, group.work_items_beta_feature_flag_enabled?)

View File

@ -13,10 +13,10 @@ class Projects::BadgesController < Projects::ApplicationController
def pipeline
pipeline_status = Gitlab::Ci::Badge::Pipeline::Status
.new(project, params[:ref], opts: {
ignore_skipped: params[:ignore_skipped],
key_text: params[:key_text],
key_width: params[:key_width]
})
ignore_skipped: params[:ignore_skipped],
key_text: params[:key_text],
key_width: params[:key_width]
})
render_badge pipeline_status
end
@ -24,13 +24,13 @@ class Projects::BadgesController < Projects::ApplicationController
def coverage
coverage_report = Gitlab::Ci::Badge::Coverage::Report
.new(project, params[:ref], opts: {
job: params[:job],
key_text: params[:key_text],
key_width: params[:key_width],
min_good: params[:min_good],
min_acceptable: params[:min_acceptable],
min_medium: params[:min_medium]
})
job: params[:job],
key_text: params[:key_text],
key_width: params[:key_width],
min_good: params[:min_good],
min_acceptable: params[:min_acceptable],
min_medium: params[:min_medium]
})
render_badge coverage_report
end
@ -38,11 +38,11 @@ class Projects::BadgesController < Projects::ApplicationController
def release
latest_release = Gitlab::Ci::Badge::Release::LatestRelease
.new(project, current_user, opts: {
key_text: params[:key_text],
key_width: params[:key_width],
value_width: params[:value_width],
order_by: params[:order_by]
})
key_text: params[:key_text],
key_width: params[:key_width],
value_width: params[:value_width],
order_by: params[:order_by]
})
render_badge latest_release
end

View File

@ -57,7 +57,6 @@ class Projects::IssuesController < Projects::ApplicationController
end
before_action only: [:index, :service_desk] do
push_frontend_feature_flag(:or_issuable_queries, project)
push_frontend_feature_flag(:frontend_caching, project&.group)
push_frontend_feature_flag(:group_multi_select_tokens, project)
end

View File

@ -52,9 +52,9 @@ module Repositories
def error_payload(message, custom_attrs = {})
custom_attrs.merge({
message: message,
documentation_url: help_url
})
message: message,
documentation_url: help_url
})
end
def split_by_owner(locks)

View File

@ -373,8 +373,7 @@ class IssuableFinder
def by_author(items)
Issuables::AuthorFilter.new(
params: original_params,
or_filters_enabled: or_filters_enabled?
params: original_params
).filter(items)
end
@ -385,8 +384,7 @@ class IssuableFinder
def assignee_filter
strong_memoize(:assignee_filter) do
Issuables::AssigneeFilter.new(
params: original_params,
or_filters_enabled: or_filters_enabled?
params: original_params
)
end
end
@ -400,8 +398,7 @@ class IssuableFinder
Issuables::LabelFilter.new(
params: original_params,
project: params.project,
group: params.group,
or_filters_enabled: or_filters_enabled?
group: params.group
)
end
end
@ -492,16 +489,6 @@ class IssuableFinder
Issuables::CrmOrganizationFilter.new(params: original_params).filter(items)
end
def or_filters_enabled?
strong_memoize(:or_filters_enabled) do
Feature.enabled?(:or_issuable_queries, feature_flag_scope)
end
end
def feature_flag_scope
params.group || params.project
end
def can_filter_by_crm_contact?
current_user&.can?(:read_crm_contact, root_group)
end

View File

@ -27,7 +27,7 @@ module Issuables
end
def by_assignee_union(issuables)
return issuables unless or_filters_enabled? && has_assignee_param?(or_params)
return issuables unless has_assignee_param?(or_params)
issuables.assigned_to(assignee_ids(or_params))
end

View File

@ -22,7 +22,7 @@ module Issuables
end
def by_author_union(issuables)
return issuables unless or_filters_enabled? && or_params&.fetch(:author_username, false).present?
return issuables unless or_params&.fetch(:author_username, false).present?
issuables.authored(User.by_username(or_params[:author_username]))
.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/419221")

View File

@ -7,9 +7,8 @@ module Issuables
FILTER_NONE = 'none'
FILTER_ANY = 'any'
def initialize(params:, or_filters_enabled: false)
def initialize(params:)
@params = params
@or_filters_enabled = or_filters_enabled
end
def filter
@ -25,9 +24,5 @@ module Issuables
def not_params
params[:not]
end
def or_filters_enabled?
@or_filters_enabled
end
end
end

View File

@ -40,7 +40,7 @@ module Issuables
# rubocop: disable CodeReuse/ActiveRecord
def by_label_union(issuables)
return issuables unless or_filters_enabled? && label_names_from_or_params.present?
return issuables unless label_names_from_or_params.present?
if root_namespace
all_label_ids = find_label_ids(label_names_from_or_params).flatten

View File

@ -31,10 +31,10 @@ module Mutations
def create_note_params(noteable, args)
super(noteable, args).merge({
type: 'DiffNote',
position: position(noteable, args),
merge_request_diff_head_sha: args[:position][:head_sha]
})
type: 'DiffNote',
position: position(noteable, args),
merge_request_diff_head_sha: args[:position][:head_sha]
})
end
def position(noteable, args)

View File

@ -15,9 +15,9 @@ module Mutations
def create_note_params(noteable, args)
super(noteable, args).merge({
type: 'DiffNote',
position: position(noteable, args)
})
type: 'DiffNote',
position: position(noteable, args)
})
end
def position(noteable, args)

View File

@ -31,9 +31,9 @@ module Mutations
end
super(noteable, args).merge({
in_reply_to_discussion_id: discussion_id,
merge_request_diff_head_sha: args[:merge_request_diff_head_sha]
})
in_reply_to_discussion_id: discussion_id,
merge_request_diff_head_sha: args[:merge_request_diff_head_sha]
})
end
def authorize_discussion!(discussion)

View File

@ -13,7 +13,7 @@ module Resolvers
alias_method :list, :object
def resolve(**args)
filters = item_filters(args[:filters], list.board.resource_parent)
filters = item_filters(args[:filters])
mutually_exclusive_milestone_args!(filters)
filter_params = filters.merge(board_id: list.board.id, id: list.id)

View File

@ -20,7 +20,7 @@ module Resolvers
def resolve(id: nil, issue_filters: {})
Gitlab::Graphql::Lazy.with_value(find_list(id: id)) do |list|
context.scoped_set!(:issue_filters, item_filters(issue_filters, list&.board&.resource_parent))
context.scoped_set!(:issue_filters, item_filters(issue_filters))
list if authorized_resource?(list)
end
end

View File

@ -22,7 +22,7 @@ module Resolvers
def resolve_with_lookahead(id: nil, issue_filters: {})
lists = board_lists(id)
context.scoped_set!(:issue_filters, item_filters(issue_filters, board.resource_parent))
context.scoped_set!(:issue_filters, item_filters(issue_filters))
List.preload_preferences_for_user(lists, current_user) if load_preferences?

View File

@ -5,7 +5,7 @@ module BoardItemFilterable
private
def item_filters(args, resource_parent)
def item_filters(args)
filters = args.to_h
set_filter_values(filters)
@ -13,11 +13,6 @@ module BoardItemFilterable
set_filter_values(filters[:not]) if filters[:not]
if filters[:or]
if ::Feature.disabled?(:or_issuable_queries, resource_parent)
raise ::Gitlab::Graphql::Errors::ArgumentError,
"'or' arguments are only allowed when the `or_issuable_queries` feature flag is enabled."
end
rewrite_param_name(filters[:or], :author_usernames, :author_username)
rewrite_param_name(filters[:or], :assignee_usernames, :assignee_username)
rewrite_param_name(filters[:or], :label_names, :label_name)

View File

@ -13,9 +13,9 @@ module Resolvers
default_value: :created_desc
GROUP_SORT_TO_PARAMS_MAP = SORT_TO_PARAMS_MAP.merge({
project_path_desc: { order_by: 'project_path', sort: 'desc' },
project_path_asc: { order_by: 'project_path', sort: 'asc' }
}).freeze
project_path_desc: { order_by: 'project_path', sort: 'desc' },
project_path_asc: { order_by: 'project_path', sort: 'asc' }
}).freeze
def resolve(sort:, **filters)
return unless packages_available?

View File

@ -104,11 +104,6 @@ module Resolvers
end
def ready?(**args)
if args[:or].present? && or_issuable_queries_disabled?
raise ::Gitlab::Graphql::Errors::ArgumentError,
"'or' arguments are only allowed when the `or_issuable_queries` feature flag is enabled."
end
args[:not] = args[:not].to_h if args[:not]
args[:or] = args[:or].to_h if args[:or]
@ -117,14 +112,6 @@ module Resolvers
private
def or_issuable_queries_disabled?
if respond_to?(:resource_parent, true)
::Feature.disabled?(:or_issuable_queries, resource_parent)
else
::Feature.disabled?(:or_issuable_queries)
end
end
def prepare_finder_params(args)
params = super(args)
params[:not] = params[:not].to_h if params[:not]

View File

@ -1,8 +0,0 @@
---
name: or_issuable_queries
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54444
rollout_issue_url:
milestone: '13.10'
type: development
group: group::project management
default_enabled: true

View File

@ -1,5 +1,44 @@
# frozen_string_literal: true
module ActiveRecord
module Tasks
module DatabaseTasks
def migrate_status
# rubocop:disable Database/MultipleDatabases -- From Rails base code which doesn't follow our style guide
# rubocop:disable Rails/Output -- From Rails base code which doesn't follow our style guide
unless ActiveRecord::Base.connection.schema_migration.table_exists?
Kernel.abort "Schema migrations table does not exist yet."
end
puts "\ndatabase: #{ActiveRecord::Base.connection_db_config.database}\n\n"
puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} #{'Type'.ljust(7)} #{'Milestone'.ljust(11)} Name"
puts "-" * 50
status_with_milestones.each do |status, version, type, milestone, name|
puts "#{status.center(8)} #{version.ljust(14)} #{type.ljust(7)} #{milestone.ljust(11)} #{name}"
end
puts
# rubocop:enable Rails/Output
# rubocop:enable Database/MultipleDatabases
end
def status_with_milestones
# rubocop:disable Database/MultipleDatabases -- From Rails base code which doesn't follow our style guide
versions = ActiveRecord::SchemaMigration.all_versions.map(&:to_i)
ActiveRecord::Base.connection.migration_context.migrations.sort_by(&:version).map do |m|
[
(versions.include?(m.version.to_i) ? 'up' : 'down'),
m.version.to_s,
m.version.try(:type).to_s,
m.try(:milestone).to_s,
m.name
]
end
# rubocop:enable Database/MultipleDatabases
end
end
end
end
return unless Gitlab.ee?
ActiveSupport.on_load(:active_record) do

View File

@ -1,26 +1,6 @@
# frozen_string_literal: true
Gitlab::Database::Migrations::LockRetryMixin.patch!
Gitlab::Database::Migrations::MigrationOrderMixin.patch!
Gitlab::Database::Migrations::PgBackendPid.patch!
Gitlab::Database::Migrations::RunnerBackoff::ActiveRecordMixin.patch!
# This patch rolls back to Rails 6.1 behavior:
#
# https://github.com/rails/rails/blob/v6.1.4.3/activerecord/lib/active_record/migration.rb#L1044
#
# It fixes the tests that relies on the fact that the same constants have the same object_id.
# For example to make sure that stub_const works correctly.
#
# It overrides the new behavior that removes the constant first:
#
# https://github.com/rails/rails/blob/v7.0.5/activerecord/lib/active_record/migration.rb#L1054
module ActiveRecord
class MigrationProxy
private
def load_migration
require(File.expand_path(filename))
name.constantize.new(name, version)
end
end
end

View File

@ -16956,7 +16956,7 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="boardepicancestorsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="boardepicancestorsmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
| <a id="boardepicancestorsnot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="boardepicancestorsor"></a>`or` **{warning-solid}** | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | **Introduced** in GitLab 15.9. **Status**: Experiment. List of arguments with inclusive OR. Ignored unless `or_issuable_queries` flag is enabled. |
| <a id="boardepicancestorsor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. |
| <a id="boardepicancestorssearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="boardepicancestorssort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="boardepicancestorsstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. |
@ -16993,7 +16993,7 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="boardepicchildrenmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="boardepicchildrenmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
| <a id="boardepicchildrennot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="boardepicchildrenor"></a>`or` **{warning-solid}** | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | **Introduced** in GitLab 15.9. **Status**: Experiment. List of arguments with inclusive OR. Ignored unless `or_issuable_queries` flag is enabled. |
| <a id="boardepicchildrenor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. |
| <a id="boardepicchildrensearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="boardepicchildrensort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="boardepicchildrenstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. |
@ -20130,7 +20130,7 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="epicancestorsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="epicancestorsmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
| <a id="epicancestorsnot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="epicancestorsor"></a>`or` **{warning-solid}** | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | **Introduced** in GitLab 15.9. **Status**: Experiment. List of arguments with inclusive OR. Ignored unless `or_issuable_queries` flag is enabled. |
| <a id="epicancestorsor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. |
| <a id="epicancestorssearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="epicancestorssort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="epicancestorsstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. |
@ -20167,7 +20167,7 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="epicchildrenmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="epicchildrenmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
| <a id="epicchildrennot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="epicchildrenor"></a>`or` **{warning-solid}** | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | **Introduced** in GitLab 15.9. **Status**: Experiment. List of arguments with inclusive OR. Ignored unless `or_issuable_queries` flag is enabled. |
| <a id="epicchildrenor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. |
| <a id="epicchildrensearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="epicchildrensort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="epicchildrenstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. |
@ -21672,7 +21672,7 @@ Returns [`Epic`](#epic).
| <a id="groupepicmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="groupepicmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
| <a id="groupepicnot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="groupepicor"></a>`or` **{warning-solid}** | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | **Introduced** in GitLab 15.9. **Status**: Experiment. List of arguments with inclusive OR. Ignored unless `or_issuable_queries` flag is enabled. |
| <a id="groupepicor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. |
| <a id="groupepicsearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="groupepicsort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="groupepicstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. |
@ -21721,7 +21721,7 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="groupepicsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Filter epics by milestone title, computed from epic's issues. |
| <a id="groupepicsmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. |
| <a id="groupepicsnot"></a>`not` | [`NegatedEpicFilterInput`](#negatedepicfilterinput) | Negated epic arguments. |
| <a id="groupepicsor"></a>`or` **{warning-solid}** | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | **Introduced** in GitLab 15.9. **Status**: Experiment. List of arguments with inclusive OR. Ignored unless `or_issuable_queries` flag is enabled. |
| <a id="groupepicsor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. |
| <a id="groupepicssearch"></a>`search` | [`String`](#string) | Search query for title or description. |
| <a id="groupepicssort"></a>`sort` | [`EpicSort`](#epicsort) | List epics by sort order. |
| <a id="groupepicsstate"></a>`state` | [`EpicState`](#epicstate) | Filter epics by state. |
@ -37539,7 +37539,7 @@ Filter parameters for projects to be aggregated for DORA metrics.
| <a id="epicfilterslabelname"></a>`labelName` | [`[String]`](#string) | Filter by label name. |
| <a id="epicfiltersmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. Wildcard values "NONE" and "ANY" are supported. |
| <a id="epicfiltersnot"></a>`not` | [`NegatedEpicBoardIssueInput`](#negatedepicboardissueinput) | Negated epic arguments. |
| <a id="epicfiltersor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. Ignored unless `or_issuable_queries` flag is enabled. |
| <a id="epicfiltersor"></a>`or` | [`UnionedEpicFilterInput`](#unionedepicfilterinput) | List of arguments with inclusive OR. |
| <a id="epicfilterssearch"></a>`search` | [`String`](#string) | Search query for epic title or description. |
### `EpicTreeNodeFieldsInputType`

View File

@ -265,15 +265,10 @@ To filter:
### Filter with the OR operator
> - OR filtering for labels and authors was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/382969) in GitLab 15.9 [with a flag](../../../administration/feature_flags.md) named `or_issuable_queries`. Disabled by default.
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/104292) in GitLab 15.9.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/296031) in GitLab 17.0. Feature flag `or_issuable_queries` removed.
FLAG:
On self-managed GitLab, by default this feature is not available.
To make it available, an administrator can [enable the feature flag](../../../administration/feature_flags.md) named `or_issuable_queries`.
On GitLab.com and GitLab Dedicated, this feature is not available.
This feature is not ready for production use.
When this feature is enabled, you can use the OR operator (**is one of: `||`**)
when you [filter the list of epics](#filter-the-list-of-epics) by:
You can use the OR operator (**is one of: `||`**) when you [filter the list of epics](#filter-the-list-of-epics) by:
- Authors
- Labels

View File

@ -510,14 +510,9 @@ It's a limitation of PostgreSQL full text search.
> - OR filtering for author and assignee was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23532) in GitLab 15.6 [with a flag](../../../administration/feature_flags.md) named `or_issuable_queries`. Disabled by default.
> - OR filtering for label was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23532) in GitLab 15.8 [with a flag](../../../administration/feature_flags.md) named `or_issuable_queries`. Disabled by default.
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/104292) in GitLab 15.9.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/296031) in GitLab 17.0. Feature flag `or_issuable_queries` removed.
FLAG:
On self-managed GitLab, by default this feature is available.
To hide the feature, an administrator can [disable the feature flag](../../../administration/feature_flags.md) named `or_issuable_queries`.
On GitLab.com and GitLab Dedicated, this feature is available.
When this feature is enabled, you can use the OR operator (**is one of: `||`**)
when you [filter the list of issues](#filter-the-list-of-issues) by:
You can use the OR operator (**is one of: `||`**) when you [filter the list of issues](#filter-the-list-of-issues) by:
- Assignees
- Author

View File

@ -71,6 +71,11 @@ module Gitlab
end
class V2_2 < V2_1
def self.inherited(subclass)
super
subclass.instance_variable_set(:@_defining_file, caller_locations.first.absolute_path)
end
include Gitlab::Database::Migrations::MilestoneMixin
end

View File

@ -0,0 +1,61 @@
# frozen_string_literal: true
# The patch to load_migration rolls back to Rails 6.1 behavior:
#
# https://github.com/rails/rails/blob/v6.1.4.3/activerecord/lib/active_record/migration.rb#L1044
#
# It fixes the tests that relies on the fact that the same constants have the same object_id.
# For example to make sure that stub_const works correctly.
#
# It overrides the new behavior that removes the constant first:
#
# https://github.com/rails/rails/blob/v7.0.5/activerecord/lib/active_record/migration.rb#L1054
# The following is a reminder for when we upgrade to Rails 7.1. In particular,
# we need to pay special attention to ensure that our ActiveRecord overrides are
# compatible.
if ::ActiveRecord::VERSION::STRING >= "7.1"
raise 'New version of active-record detected, please remove or update this patch'
end
module Gitlab
module Database
module Migrations
module MigrationOrderMixin
module MigrationProxyOverrides
def version
migration.version
end
def milestone
migration.try(:milestone)
end
private
def load_migration
require(File.expand_path(filename))
name.constantize.new(name, self[:version])
end
end
module MigratorOverrides
def current_version
migrations
.sort_by(&:version)
.reverse
.find { |m| migrated.include?(m.version) }
.try(:version) || 0
end
end
def self.patch!
ActiveRecord::MigrationProxy.prepend(MigrationProxyOverrides)
ActiveRecord::Migrator.prepend(MigratorOverrides)
end
end
end
end
end

View File

@ -19,10 +19,23 @@ module Gitlab
end
end
def initialize(name = self.class.name, version = nil, _type = nil)
def type_from_path(path)
dir = File.dirname(path)
return :post if dir.match?(%r{db/(\w+/)?post_migrate})
return :regular if dir.match?(%r{db/(\w+/)?migrate})
raise 'unknown migration path'
end
def initialize(name = self.class.name, version = nil)
raise MilestoneNotSetError, "Milestone is not set for #{name}" if milestone.nil?
super(name, version)
@version = Gitlab::Database::Migrations::Version.new(
version,
milestone,
type_from_path(self.class.instance_variable_get(:@_defining_file))
)
end
def milestone # rubocop:disable Lint/DuplicateMethods

View File

@ -17,7 +17,7 @@ module Gitlab
def initialize(timestamp, milestone, type)
@timestamp = timestamp
@milestone = milestone
@milestone = Gitlab::VersionInfo.parse_from_milestone(milestone)
self.type = type
end
@ -29,6 +29,10 @@ module Gitlab
@type_value = TYPE_VALUES.fetch(value.to_sym) { raise InvalidTypeError }
end
def milestone=(milestone_str)
@milestone = Gitlab::VersionInfo.parse_from_milestone(milestone_str)
end
def regular?
@type_value == TYPE_VALUES[:regular]
end
@ -38,9 +42,12 @@ module Gitlab
end
def <=>(other)
return 0 if other.is_a?(Integer) && @timestamp == other
return 1 unless other.is_a?(self.class)
return milestone <=> other.milestone if milestone != other.milestone
compare_milestones = milestone <=> other.milestone
return compare_milestones if compare_milestones != 0
return @type_value <=> other.type_value if @type_value != other.type_value
@ -55,7 +62,7 @@ module Gitlab
@timestamp.to_i
end
def coerce(_other)
def coerce(_)
[-1, timestamp.to_i]
end
@ -68,7 +75,7 @@ module Gitlab
end
def hash
[timestamp, milestone, @type_value].hash
timestamp.hash
end
end
end

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ActiveRecord::Tasks::DatabaseTasks, feature_category: :database do
let(:db_config) { Gitlab::Database.database_base_models.first }
it 'does not raise an error' do
expect { described_class.migrate_status }.not_to raise_error
end
end

View File

@ -12,10 +12,6 @@ RSpec.describe 'Group issues page', feature_category: :groups_and_projects do
let(:project_with_issues_disabled) { create(:project, :issues_disabled, group: group) }
let(:path) { issues_group_path(group) }
before do
stub_feature_flags(or_issuable_queries: false)
end
context 'with shared examples', :js do
let(:issuable) { create(:issue, project: project, title: "this is my created issuable") }

View File

@ -11,7 +11,6 @@ RSpec.describe 'Groups > User sees users dropdowns in issuables list', :js, feat
let!(:project) { create(:project, group: group) }
before do
stub_feature_flags(or_issuable_queries: false)
group.add_developer(user_in_dropdown)
sign_in(user_in_dropdown)
end

View File

@ -9,10 +9,6 @@ RSpec.describe 'Dropdown assignee', :js, feature_category: :team_planning do
let_it_be(:user) { create(:user) }
let_it_be(:issue) { create(:issue, project: project) }
before do
stub_feature_flags(or_issuable_queries: false)
end
describe 'behavior' do
before do
project.add_maintainer(user)

View File

@ -10,7 +10,6 @@ RSpec.describe 'Dropdown author', :js, feature_category: :team_planning do
let_it_be(:issue) { create(:issue, project: project) }
before do
stub_feature_flags(or_issuable_queries: false)
project.add_maintainer(user)
sign_in(user)

View File

@ -10,7 +10,6 @@ RSpec.describe 'Dropdown base', :js, feature_category: :team_planning do
let_it_be(:issue) { create(:issue, project: project) }
before do
stub_feature_flags(or_issuable_queries: false)
project.add_maintainer(user)
sign_in(user)

View File

@ -11,7 +11,6 @@ RSpec.describe 'Dropdown emoji', :js, feature_category: :team_planning do
let_it_be(:award_emoji_star) { create(:award_emoji, name: 'star', user: user, awardable: issue) }
before do
stub_feature_flags(or_issuable_queries: false)
project.add_maintainer(user)
create_list(:award_emoji, 2, user: user, name: 'thumbsup')
create_list(:award_emoji, 1, user: user, name: 'thumbsdown')

View File

@ -10,7 +10,6 @@ RSpec.describe 'Dropdown hint', :js, feature_category: :team_planning do
let_it_be(:issue) { create(:issue, project: project) }
before do
stub_feature_flags(or_issuable_queries: false)
project.add_maintainer(user)
end
@ -68,11 +67,11 @@ RSpec.describe 'Dropdown hint', :js, feature_category: :team_planning do
expect_visible_suggestions_list
expect_suggestion '='
click_link '= is'
click_link 'is ='
expect_visible_suggestions_list
expect_token_segment 'Author'
expect_token_segment '='
expect_token_segment 'is'
expect_empty_search_term
end
end

View File

@ -11,7 +11,6 @@ RSpec.describe 'Dropdown label', :js, feature_category: :team_planning do
let_it_be(:label) { create(:label, project: project, title: 'bug-label') }
before do
stub_feature_flags(or_issuable_queries: false)
project.add_maintainer(user)
sign_in(user)

View File

@ -12,7 +12,6 @@ RSpec.describe 'Dropdown milestone', :js, feature_category: :team_planning do
let_it_be(:issue) { create(:issue, project: project) }
before do
stub_feature_flags(or_issuable_queries: false)
project.add_maintainer(user)
sign_in(user)

View File

@ -12,7 +12,6 @@ RSpec.describe 'Dropdown release', :js, feature_category: :team_planning do
let_it_be(:issue) { create(:issue, project: project) }
before do
stub_feature_flags(or_issuable_queries: false)
project.add_maintainer(user)
sign_in(user)

View File

@ -19,7 +19,6 @@ RSpec.describe 'Filter issues', :js, feature_category: :team_planning do
end
before do
stub_feature_flags(or_issuable_queries: false)
project.add_maintainer(user)
create(:issue, project: project, author: user2, title: "Bug report 1")

View File

@ -15,7 +15,6 @@ RSpec.describe 'Visual tokens', :js, feature_category: :team_planning do
let_it_be(:issue) { create(:issue, project: project) }
before do
stub_feature_flags(or_issuable_queries: false)
project.add_member(user, :maintainer)
project.add_member(user_rock, :maintainer)
sign_in(user)
@ -91,7 +90,7 @@ RSpec.describe 'Visual tokens', :js, feature_category: :team_planning do
expect_suggestion '='
expect_suggestion '!='
click_on '= is'
click_on 'is ='
expect_suggestion(user.name)
expect_suggestion(user_rock.name)
@ -111,10 +110,10 @@ RSpec.describe 'Visual tokens', :js, feature_category: :team_planning do
it 'does retain hint token when mix of typing and clicks are performed' do
select_tokens 'Label'
click_on '= is'
click_on 'is ='
expect_token_segment 'Label'
expect_token_segment '='
expect_token_segment 'is'
end
describe 'Any/None option' do

View File

@ -17,7 +17,6 @@ RSpec.describe 'Labels Hierarchy', :js, feature_category: :team_planning do
let!(:project_label_1) { create(:label, project: project_1, title: 'Label_4') }
before do
stub_feature_flags(or_issuable_queries: false)
grandparent.add_owner(user)
sign_in(user)
@ -61,7 +60,7 @@ RSpec.describe 'Labels Hierarchy', :js, feature_category: :team_planning do
within_testid('filtered-search-input') do
click_filtered_search_bar
click_on 'Label'
click_on '= is'
click_on 'is ='
click_on label.title
send_keys :enter
end
@ -112,7 +111,7 @@ RSpec.describe 'Labels Hierarchy', :js, feature_category: :team_planning do
within_testid('filtered-search-input') do
click_filtered_search_bar
click_on 'Label'
click_on '= is'
click_on 'is ='
click_on label.title
send_keys :enter
end

View File

@ -55,16 +55,6 @@ RSpec.describe MergeRequestsFinder, feature_category: :code_review_workflow do
it 'returns merge requests created by any of the given users' do
expect(merge_requests).to contain_exactly(merge_request1, merge_request2)
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(or_issuable_queries: false)
end
it 'does not add any filter' do
expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3, merge_request4, merge_request5)
end
end
end
context 'with nonexistent author ID and MR term using CTE for search' do

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class OrderingTestOne < Gitlab::Database::Migration[2.1]
def change
# no op
end
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class OrderingTestTwo < Gitlab::Database::Migration[2.1]
def change
# no op
end
end

View File

@ -40,6 +40,7 @@ describe('Feature flags strategy', () => {
const findStrategyParameters = () => wrapper.findComponent(StrategyParameters);
const findDocsLinks = () => wrapper.findAllComponents(GlLink);
const findToken = () => wrapper.findComponent(GlToken);
const factory = (
opts = {
@ -140,7 +141,7 @@ describe('Feature flags strategy', () => {
});
it('should revert to all-environments scope when last scope is removed', async () => {
const token = wrapper.findComponent(GlToken);
const token = findToken();
token.vm.$emit('close');
await nextTick();
expect(wrapper.findAllComponents(GlToken)).toHaveLength(0);
@ -154,6 +155,34 @@ describe('Feature flags strategy', () => {
});
});
describe('with a single environment scope defined and existing feature flag', () => {
let strategy;
beforeEach(() => {
strategy = {
name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
parameters: { percentage: '50', groupId: 'default' },
scopes: [{ environmentScope: 'production', id: 1 }],
};
const propsData = { strategy, index: 0 };
factory({ propsData, provide });
});
it('should revert single environment scope when last scope is removed', async () => {
findToken().vm.$emit('close');
await nextTick();
expect(wrapper.emitted('change')).toEqual([
[
{
name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
parameters: { percentage: '50', groupId: PERCENT_ROLLOUT_GROUP_ID },
scopes: [{ environmentScope: 'production', id: 1, shouldBeDestroyed: true }],
},
],
]);
});
});
describe('with an all-environments scope defined', () => {
let strategy;
@ -169,7 +198,8 @@ describe('Feature flags strategy', () => {
it('should change the parameters if a different strategy is chosen', async () => {
const select = wrapper.findComponent(GlFormSelect);
select.setValue(ROLLOUT_STRATEGY_ALL_USERS);
select.element.value = ROLLOUT_STRATEGY_ALL_USERS;
select.trigger('change');
await nextTick();
expect(last(wrapper.emitted('change'))).toEqual([
{
@ -185,7 +215,7 @@ describe('Feature flags strategy', () => {
dropdown.vm.$emit('add', 'production');
await nextTick();
expect(wrapper.findAllComponents(GlToken)).toHaveLength(1);
expect(wrapper.findComponent(GlToken).text()).toBe('production');
expect(findToken().text()).toBe('production');
});
it('should display all selected scopes', async () => {
@ -237,7 +267,7 @@ describe('Feature flags strategy', () => {
dropdown.vm.$emit('add', 'production');
await nextTick();
expect(wrapper.findAllComponents(GlToken)).toHaveLength(1);
expect(wrapper.findComponent(GlToken).text()).toBe('production');
expect(findToken().text()).toBe('production');
});
it('should display all selected scopes', async () => {

View File

@ -113,7 +113,9 @@ RSpec.describe Gitlab::Database::Migrations::LockRetryMixin, feature_category: :
let(:migration) do
Class.new(Gitlab::Database::Migration[2.2]) do
milestone 16.10
milestone '16.10'
@_defining_file = 'db/migrate/1_test.rb'
def change
# no-op

View File

@ -12,12 +12,22 @@ RSpec.describe Gitlab::Database::Migrations::MilestoneMixin, feature_category: :
end
let(:migration_mixin) do
Class.new(Gitlab::Database::Migration[2.2])
Class.new(Gitlab::Database::Migration[2.2]) do
@_defining_file = 'db/migrate/00000000000000_example.rb'
end
end
let(:migration_mixin_version) do
Class.new(Gitlab::Database::Migration[2.2]) do
milestone '16.4'
@_defining_file = 'db/migrate/00000000000000_example.rb'
end
end
let(:migration_mixin_version_post) do
Class.new(Gitlab::Database::Migration[2.2]) do
milestone '16.4'
@_defining_file = 'db/post_migrate/00000000000000_example.rb'
end
end
@ -30,7 +40,7 @@ RSpec.describe Gitlab::Database::Migrations::MilestoneMixin, feature_category: :
context 'when the mixin is included' do
context 'when a milestone is not specified' do
it "raises MilestoneNotSetError" do
expect { migration_mixin.new(4, 4, :regular) }.to raise_error(
expect { migration_mixin.new(4, 4) }.to raise_error(
"#{described_class}::MilestoneNotSetError".constantize
)
end
@ -38,7 +48,7 @@ RSpec.describe Gitlab::Database::Migrations::MilestoneMixin, feature_category: :
context 'when a milestone is specified' do
it "does not raise an error" do
expect { migration_mixin_version.new(4, 4, :regular) }.not_to raise_error
expect { migration_mixin_version.new(4, 4) }.not_to raise_error
end
end
@ -47,5 +57,17 @@ RSpec.describe Gitlab::Database::Migrations::MilestoneMixin, feature_category: :
expect { migration_mixin_version.new }.not_to raise_error
end
end
context "when it's a regular migration" do
it 'is a regular migration' do
expect(migration_mixin_version.new(4, 4).version.type).to eq(:regular)
end
end
context "when it's a post-deployment migration" do
it 'is a regular migration' do
expect(migration_mixin_version_post.new(4, 4).version.type).to eq(:post)
end
end
end
end

View File

@ -7,32 +7,35 @@ RSpec.describe Gitlab::Database::Migrations::Version, feature_category: :databas
[
4,
5,
described_class.new(6, Gitlab::VersionInfo.parse_from_milestone('10.3'), :regular),
described_class.new(6, '10.3', :regular),
7,
described_class.new(8, Gitlab::VersionInfo.parse_from_milestone('10.3'), :regular),
described_class.new(9, Gitlab::VersionInfo.parse_from_milestone('10.4'), :regular),
described_class.new(10, Gitlab::VersionInfo.parse_from_milestone('10.3'), :post),
described_class.new(11, Gitlab::VersionInfo.parse_from_milestone('10.3'), :regular)
described_class.new(8, '10.3', :regular),
described_class.new(9, '10.4', :regular),
described_class.new(10, '10.3', :post),
described_class.new(11, '10.3', :regular),
described_class.new(12, '10.15', :regular)
]
end
describe "#<=>" do
it 'sorts by existence of milestone, then by milestone, then by type, then by timestamp when sorted by version' do
expect(test_versions.sort.map(&:to_i)).to eq [4, 5, 7, 6, 8, 11, 10, 9]
expect(test_versions.sort.map(&:to_i)).to eq [4, 5, 7, 6, 8, 11, 10, 9, 12]
end
end
describe 'initialize' do
context 'when the type is :post or :regular' do
it 'does not raise an error' do
expect { described_class.new(4, 4, :regular) }.not_to raise_error
expect { described_class.new(4, 4, :post) }.not_to raise_error
expect { described_class.new(4, '10.3', :regular) }.not_to raise_error
expect { described_class.new(4, '10.3', :post) }.not_to raise_error
end
end
context 'when the type is anything else' do
it 'does not raise an error' do
expect { described_class.new(4, 4, 'foo') }.to raise_error("#{described_class}::InvalidTypeError".constantize)
expect do
described_class.new(4, '10.3', 'foo')
end.to raise_error("#{described_class}::InvalidTypeError".constantize)
end
end
end
@ -41,23 +44,23 @@ RSpec.describe Gitlab::Database::Migrations::Version, feature_category: :databas
where(:version1, :version2, :expected_equality) do
[
[
described_class.new(4, Gitlab::VersionInfo.parse_from_milestone('10.3'), :regular),
described_class.new(4, Gitlab::VersionInfo.parse_from_milestone('10.3'), :regular),
described_class.new(4, '10.3', :regular),
described_class.new(4, '10.3', :regular),
true
],
[
described_class.new(4, Gitlab::VersionInfo.parse_from_milestone('10.3'), :regular),
described_class.new(4, Gitlab::VersionInfo.parse_from_milestone('10.4'), :regular),
described_class.new(4, '10.3', :regular),
described_class.new(4, '10.4', :regular),
false
],
[
described_class.new(4, Gitlab::VersionInfo.parse_from_milestone('10.3'), :regular),
described_class.new(4, Gitlab::VersionInfo.parse_from_milestone('10.3'), :post),
described_class.new(4, '10.3', :regular),
described_class.new(4, '10.3', :post),
false
],
[
described_class.new(4, Gitlab::VersionInfo.parse_from_milestone('10.3'), :regular),
described_class.new(5, Gitlab::VersionInfo.parse_from_milestone('10.3'), :regular),
described_class.new(4, '10.3', :regular),
described_class.new(5, '10.3', :regular),
false
]
]
@ -75,7 +78,7 @@ RSpec.describe Gitlab::Database::Migrations::Version, feature_category: :databas
end
describe 'type' do
subject { described_class.new(4, Gitlab::VersionInfo.parse_from_milestone('10.3'), migration_type) }
subject { described_class.new(4, '10.3', migration_type) }
context 'when the migration is regular' do
let(:migration_type) { :regular }
@ -99,7 +102,7 @@ RSpec.describe Gitlab::Database::Migrations::Version, feature_category: :databas
end
describe 'to_s' do
subject { described_class.new(4, Gitlab::VersionInfo.parse_from_milestone('10.3'), :regular) }
subject { described_class.new(4, '10.3', :regular) }
it 'returns the given timestamp value as a string' do
expect(subject.to_s).to eql('4')
@ -107,7 +110,7 @@ RSpec.describe Gitlab::Database::Migrations::Version, feature_category: :databas
end
describe 'hash' do
subject { described_class.new(4, Gitlab::VersionInfo.parse_from_milestone('10.3'), :regular) }
subject { described_class.new(4, '10.3', :regular) }
let(:expected_hash) { subject.hash }
@ -117,4 +120,14 @@ RSpec.describe Gitlab::Database::Migrations::Version, feature_category: :databas
end
end
end
describe '=' do
subject { described_class.new(4, '10.3', :regular) }
it 'correctly assigns a new milestone object parsed from a string' do
subject.milestone = '14.6'
expect(subject.milestone.major).to be(14)
expect(subject.milestone.minor).to be(6)
end
end
end

View File

@ -122,16 +122,6 @@ RSpec.describe 'get board lists', feature_category: :team_planning do
expect(issue_id).to contain_exactly(issue1.to_gid.to_s, issue2.to_gid.to_s)
end
context 'when feature flag is disabled' do
it 'returns an error' do
stub_feature_flags(or_issuable_queries: false)
subject
expect_graphql_errors_to_include("'or' arguments are only allowed when the `or_issuable_queries` feature flag is enabled.")
end
end
end
end
end

View File

@ -152,23 +152,6 @@ RSpec.describe 'get board lists', feature_category: :team_planning do
expect(lists_data[0]['node']['issuesCount']).to eq 2
end
context 'when feature flag is disabled' do
it 'returns an error' do
stub_feature_flags(or_issuable_queries: false)
post_graphql(
query(
id: global_id_of(label_list),
issueFilters: { or: { assignee_usernames: [user.username, another_user.username] } }
), current_user: user
)
expect_graphql_errors_to_include(
"'or' arguments are only allowed when the `or_issuable_queries` feature flag is enabled."
)
end
end
end
end
end

View File

@ -192,11 +192,7 @@ module FilteredSearchHelpers
# Move mouse away to prevent invoking tooltips on usernames, which blocks the search input
find_button('Search').hover
if token == '='
click_on '= is'
else
click_on token
end
click_on token.to_s, match: :first
wait_for_requests
end
@ -252,35 +248,35 @@ module FilteredSearchHelpers
end
def expect_assignee_token(value)
expect(page).to have_css '.gl-filtered-search-token', text: "Assignee = #{value}"
expect(page).to have_css '.gl-filtered-search-token', text: /Assignee (=|is) #{Regexp.escape(value)}/
end
def expect_unioned_assignee_token(value)
expect(page).to have_css '.gl-filtered-search-token', text: "Assignee is one of #{value}"
expect(page).to have_css '.gl-filtered-search-token', text: /Assignee is one of #{Regexp.escape(value)}/
end
def expect_author_token(value)
expect(page).to have_css '.gl-filtered-search-token', text: "Author = #{value}"
expect(page).to have_css '.gl-filtered-search-token', text: /Author (=|is) #{Regexp.escape(value)}/
end
def expect_label_token(value)
expect(page).to have_css '.gl-filtered-search-token', text: "Label = #{value}"
expect(page).to have_css '.gl-filtered-search-token', text: /Label (=|is) #{Regexp.escape(value)}/
end
def expect_negated_label_token(value)
expect(page).to have_css '.gl-filtered-search-token', text: "Label != #{value}"
expect(page).to have_css '.gl-filtered-search-token', text: /Label (!=|is not one of) #{Regexp.escape(value)}/
end
def expect_milestone_token(value)
expect(page).to have_css '.gl-filtered-search-token', text: "Milestone = %#{value}"
expect(page).to have_css '.gl-filtered-search-token', text: /Milestone (=|is) %#{Regexp.escape(value)}/
end
def expect_negated_milestone_token(value)
expect(page).to have_css '.gl-filtered-search-token', text: "Milestone != %#{value}"
expect(page).to have_css '.gl-filtered-search-token', text: /Milestone (!=|is not) %#{Regexp.escape(value)}/
end
def expect_epic_token(value)
expect(page).to have_css '.gl-filtered-search-token', text: "Epic = #{value}"
expect(page).to have_css '.gl-filtered-search-token', text: /Epic (=|is) #{value}/
end
def expect_search_term(value)

View File

@ -4,6 +4,10 @@ RSpec.shared_examples 'multiple issue boards' do
include ListboxHelpers
context 'authorized user' do
before_all do
create(:callout, feature_name: :board_add_new_column_trigger_popover, user: user)
end
before do
parent.add_maintainer(user)

View File

@ -219,16 +219,6 @@ RSpec.shared_examples 'issues or work items finder' do |factory, execute_context
it 'returns items created by any of the given users' do
expect(items).to contain_exactly(item3, item6)
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(or_issuable_queries: false)
end
it 'does not add any filter' do
expect(items).to contain_exactly(item1, item2, item3, item4, item5, item6)
end
end
end
context 'filtering by NOT author ID' do
@ -502,16 +492,6 @@ RSpec.shared_examples 'issues or work items finder' do |factory, execute_context
it 'returns items that have at least one of the given labels' do
expect(items).to contain_exactly(item2, item3)
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(or_issuable_queries: false)
end
it 'does not add any filter' do
expect(items).to contain_exactly(item1, item2, item3, item4, item5)
end
end
end
end

View File

@ -152,20 +152,6 @@ RSpec.shared_examples 'graphql issue list request spec' do
expect_graphql_errors_to_be_empty
end
end
context 'when feature flag is disabled' do
let(:issue_filter_params) { { or: { assignee_usernames: [current_user.username] } } }
it 'returns an error' do
stub_feature_flags(or_issuable_queries: false)
post_query
expect_graphql_errors_to_include(
"'or' arguments are only allowed when the `or_issuable_queries` feature flag is enabled."
)
end
end
end
context 'when filtering by a blank negated argument' do