Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-10-28 09:10:15 +00:00
parent 5431dbfffc
commit 2578890510
74 changed files with 322 additions and 556 deletions

View File

@ -198,7 +198,7 @@ export default {
<gl-badge
v-if="isInternalNote"
v-gl-tooltip:tooltipcontainer.bottom
data-testid="internalNoteIndicator"
data-testid="internal-note-indicator"
variant="warning"
size="sm"
class="gl-ml-2"

View File

@ -60,7 +60,6 @@ module IssuableCollectionsAction
def finder_options
issue_types = Issue::TYPES_FOR_LIST
issue_types = issue_types.excluding('task') unless Feature.enabled?(:work_items)
super.merge(
non_archived: true,

View File

@ -405,7 +405,6 @@ class Projects::IssuesController < Projects::ApplicationController
options = super
options[:issue_types] = Issue::TYPES_FOR_LIST
options[:issue_types] = options[:issue_types].excluding('task') unless project.work_items_feature_flag_enabled?
if service_desk?
options.reject! { |key| key == 'author_username' || key == 'author_id' }
@ -432,7 +431,6 @@ class Projects::IssuesController < Projects::ApplicationController
def create_vulnerability_issue_feedback(issue); end
def redirect_if_task
return render_404 if issue.task? && !project.work_items_feature_flag_enabled?
return unless issue.task?
if Feature.enabled?(:use_iid_in_work_items_path, project.group)

View File

@ -9,8 +9,4 @@ class Projects::WorkItemsController < Projects::ApplicationController
feature_category :team_planning
urgency :low
def index
render_404 unless project&.work_items_feature_flag_enabled?
end
end

View File

@ -9,7 +9,7 @@ module Mutations
include FindsProject
include Mutations::WorkItems::Widgetable
description "Creates a work item. Available only when feature flag `work_items` is enabled."
description "Creates a work item."
authorize :create_work_item
@ -42,10 +42,6 @@ module Mutations
def resolve(project_path:, **attributes)
project = authorized_find!(project_path)
unless project.work_items_feature_flag_enabled?
return { errors: ['`work_items` feature flag disabled for this project'] }
end
spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
params = global_id_compatibility_params(attributes).merge(author_id: current_user.id)
type = ::WorkItems::Type.find(attributes[:work_item_type_id])

View File

@ -7,8 +7,7 @@ module Mutations
include Mutations::SpamProtection
description "Creates a work item from a task in another work item's description." \
" Available only when feature flag `work_items` is enabled."
description "Creates a work item from a task in another work item's description."
authorize :update_work_item
@ -31,10 +30,6 @@ module Mutations
def resolve(id:, work_item_data:)
work_item = authorized_find!(id: id)
unless work_item.project.work_items_feature_flag_enabled?
return { errors: ['`work_items` feature flag disabled for this project'] }
end
spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
result = ::WorkItems::CreateFromTaskService.new(

View File

@ -4,8 +4,7 @@ module Mutations
module WorkItems
class Delete < BaseMutation
graphql_name 'WorkItemDelete'
description "Deletes a work item." \
" Available only when feature flag `work_items` is enabled."
description "Deletes a work item."
authorize :delete_work_item
@ -20,10 +19,6 @@ module Mutations
def resolve(id:)
work_item = authorized_find!(id: id)
unless work_item.project.work_items_feature_flag_enabled?
return { errors: ['`work_items` feature flag disabled for this project'] }
end
result = ::WorkItems::DeleteService.new(
project: work_item.project,
current_user: current_user

View File

@ -5,8 +5,7 @@ module Mutations
class DeleteTask < BaseMutation
graphql_name 'WorkItemDeleteTask'
description "Deletes a task in a work item's description." \
' Available only when feature flag `work_items` is enabled.'
description "Deletes a task in a work item's description."
authorize :update_work_item
@ -29,10 +28,6 @@ module Mutations
work_item = authorized_find!(id: id)
task_data[:task] = authorized_find_task!(task_data[:id])
unless work_item.project.work_items_feature_flag_enabled?
return { errors: ['`work_items` feature flag disabled for this project'] }
end
result = ::WorkItems::DeleteTaskService.new(
work_item: work_item,
current_user: current_user,

View File

@ -4,8 +4,7 @@ module Mutations
module WorkItems
class Update < BaseMutation
graphql_name 'WorkItemUpdate'
description "Updates a work item by Global ID." \
" Available only when feature flag `work_items` is enabled."
description "Updates a work item by Global ID."
include Mutations::SpamProtection
include Mutations::WorkItems::UpdateArguments
@ -20,10 +19,6 @@ module Mutations
def resolve(id:, **attributes)
work_item = authorized_find!(id: id)
unless work_item.project.work_items_feature_flag_enabled?
return { errors: ['`work_items` feature flag disabled for this project'] }
end
spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
widget_params = extract_widget_params!(work_item.work_item_type, attributes)

View File

@ -4,8 +4,7 @@ module Mutations
module WorkItems
class UpdateTask < BaseMutation
graphql_name 'WorkItemUpdateTask'
description "Updates a work item's task by Global ID." \
" Available only when feature flag `work_items` is enabled."
description "Updates a work item's task by Global ID."
include Mutations::SpamProtection
@ -30,10 +29,6 @@ module Mutations
work_item = authorized_find!(id: id)
task = authorized_find_task!(task_data_hash[:id])
unless work_item.project.work_items_feature_flag_enabled?
return { errors: ['`work_items` feature flag disabled for this project'] }
end
spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
::WorkItems::UpdateService.new(

View File

@ -11,10 +11,7 @@ module Resolvers
argument :id, ::Types::GlobalIDType[::WorkItem], required: true, description: 'Global ID of the work item.'
def resolve(id:)
work_item = authorized_find!(id: id)
return unless work_item.project.work_items_feature_flag_enabled?
work_item
authorized_find!(id: id)
end
private

View File

@ -11,8 +11,6 @@ module Resolvers
' Argument is experimental and can be removed in the future without notice.'
def resolve(taskable: nil)
return unless feature_flag_enabled_for_parent?(object)
# This will require a finder in the future when groups/projects get their work item types
# All groups/projects use the default types for now
base_scope = ::WorkItems::Type.default
@ -20,14 +18,6 @@ module Resolvers
base_scope.order_by_name_asc
end
private
def feature_flag_enabled_for_parent?(parent)
return false unless parent.is_a?(::Project) || parent.is_a?(::Group)
parent.work_items_feature_flag_enabled?
end
end
end
end

View File

@ -26,7 +26,7 @@ module Resolvers
required: false
def resolve_with_lookahead(**args)
return WorkItem.none if resource_parent.nil? || !resource_parent.work_items_feature_flag_enabled?
return WorkItem.none if resource_parent.nil?
finder = ::WorkItems::WorkItemsFinder.new(current_user, prepare_finder_params(args))

View File

@ -231,9 +231,7 @@ module Types
field :work_item_types, Types::WorkItems::TypeType.connection_type,
resolver: Resolvers::WorkItems::TypesResolver,
description: 'Work item types available to the group.' \
' Returns `null` if `work_items` feature flag is disabled.' \
' This flag is disabled by default, because the feature is experimental and is subject to change without notice.'
description: 'Work item types available to the group.'
def label(title:)
BatchLoader::GraphQL.for(title).batch(key: group) do |titles, loader, args|

View File

@ -10,7 +10,7 @@ module Types
end
value 'TASK', value: 'task',
description: 'Task issue type. Available only when feature flag `work_items` is enabled.',
description: 'Task issue type.',
alpha: { milestone: '15.2' }
end
end

View File

@ -513,9 +513,7 @@ module Types
field :work_item_types, Types::WorkItems::TypeType.connection_type,
resolver: Resolvers::WorkItems::TypesResolver,
description: 'Work item types available to the project.' \
' Returns `null` if `work_items` feature flag is disabled.' \
' This flag is disabled by default, because the feature is experimental and is subject to change without notice.'
description: 'Work item types available to the project.'
field :timelog_categories, Types::TimeTracking::TimelogCategoryType.connection_type,
null: true,

View File

@ -92,7 +92,7 @@ module Types
null: true,
resolver: Resolvers::WorkItemResolver,
alpha: { milestone: '15.1' },
description: 'Find a work item. Returns `null` if `work_items` feature flag is disabled.'
description: 'Find a work item.'
field :merge_request, Types::MergeRequestType,
null: true,

View File

@ -96,7 +96,7 @@ module Routing
private
def use_work_items_path?(issue)
issue.issue_type == 'task' && issue.project.work_items_feature_flag_enabled?
issue.issue_type == 'task'
end
end
end

View File

@ -6,6 +6,16 @@ class Appearance < ApplicationRecord
include ObjectStorage::BackgroundMove
include WithUploads
attribute :title, default: ''
attribute :description, default: ''
attribute :new_project_guidelines, default: ''
attribute :profile_image_guidelines, default: ''
attribute :header_message, default: ''
attribute :footer_message, default: ''
attribute :message_background_color, default: '#E75E40'
attribute :message_font_color, default: '#FFFFFF'
attribute :email_header_and_footer_enabled, default: false
cache_markdown_field :description
cache_markdown_field :new_project_guidelines
cache_markdown_field :profile_image_guidelines
@ -20,16 +30,6 @@ class Appearance < ApplicationRecord
validate :single_appearance_row, on: :create
default_value_for :title, ''
default_value_for :description, ''
default_value_for :new_project_guidelines, ''
default_value_for :profile_image_guidelines, ''
default_value_for :header_message, ''
default_value_for :footer_message, ''
default_value_for :message_background_color, '#E75E40'
default_value_for :message_font_color, '#FFFFFF'
default_value_for :email_header_and_footer_enabled, false
mount_uploader :logo, AttachmentUploader
mount_uploader :header_logo, AttachmentUploader
mount_uploader :favicon, FaviconUploader

View File

@ -75,9 +75,9 @@ class ApplicationSetting < ApplicationRecord
cache_markdown_field :shared_runners_text, pipeline: :plain_markdown
cache_markdown_field :after_sign_up_text
default_value_for :id, 1
default_value_for :repository_storages_weighted, {}
default_value_for :kroki_formats, {}
attribute :id, default: 1
attribute :repository_storages_weighted, default: -> { {} }
attribute :kroki_formats, default: -> { {} }
chronic_duration_attr_writer :archive_builds_in_human_readable, :archive_builds_in_seconds

View File

@ -23,8 +23,8 @@ class BroadcastMessage < ApplicationRecord
validates :color, allow_blank: true, color: true
validates :font, allow_blank: true, color: true
default_value_for :color, '#E75E40'
default_value_for :font, '#FFFFFF'
attribute :color, default: '#E75E40'
attribute :font, default: '#FFFFFF'
CACHE_KEY = 'broadcast_message_current_json'
BANNER_CACHE_KEY = 'broadcast_message_current_banner_json'

View File

@ -4,8 +4,8 @@ module TtlExpirable
extend ActiveSupport::Concern
included do
attribute :read_at, default: -> { Time.zone.now }
validates :status, presence: true
default_value_for :read_at, Time.zone.now
enum status: { default: 0, pending_destruction: 1, processing: 2, error: 3 }

View File

@ -3,7 +3,7 @@
class DependencyProxy::GroupSetting < ApplicationRecord
belongs_to :group
validates :group, presence: true
attribute :enabled, default: true
default_value_for :enabled, true
validates :group, presence: true
end

View File

@ -3006,7 +3006,7 @@ class Project < ApplicationRecord
end
def work_items_create_from_markdown_feature_flag_enabled?
work_items_feature_flag_enabled? && (group&.work_items_create_from_markdown_feature_flag_enabled? || Feature.enabled?(:work_items_create_from_markdown))
group&.work_items_create_from_markdown_feature_flag_enabled? || Feature.enabled?(:work_items_create_from_markdown)
end
def enqueue_record_project_target_platforms

View File

@ -4,14 +4,10 @@ module WorkItems
module Widgets
class Hierarchy < Base
def parent
return unless work_item.project.work_items_feature_flag_enabled?
work_item.work_item_parent
end
def children
return WorkItem.none unless work_item.project.work_items_feature_flag_enabled?
work_item.work_item_children
end
end

View File

@ -195,8 +195,6 @@ class ProjectPolicy < BasePolicy
with_scope :subject
condition(:packages_disabled) { !@subject.packages_enabled }
condition(:work_items_enabled, scope: :subject) { project&.work_items_feature_flag_enabled? }
features = %w[
merge_requests
issues
@ -304,7 +302,7 @@ class ProjectPolicy < BasePolicy
rule { can?(:create_issue) }.enable :create_work_item
rule { can?(:create_issue) & work_items_enabled }.enable :create_task
rule { can?(:create_issue) }.enable :create_task
# These abilities are not allowed to admins that are not members of the project,
# that's why they are defined separately.

View File

@ -10,7 +10,9 @@ value_type: number
status: active
time_frame: all
data_source: database
instrumentation_class: DistinctCountProjectsWithExpirationPolicyDisabledMetric
instrumentation_class: DistinctCountProjectsWithExpirationPolicyMetric
options:
enabled: false
distribution:
- ee
- ce

View File

@ -0,0 +1,9 @@
---
table_name: audit_events_streaming_event_type_filters
classes:
- AuditEvents::Streaming::EventTypeFilter
feature_categories:
- audit_events
description: Represents a event type filter for audit event streaming
introduced_by_url:
milestone: '15.6'

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class CreateAuditEventsStreamingEventTypeFilters < Gitlab::Database::Migration[2.0]
UNIQ_INDEX_NAME = 'unique_streaming_event_type_filters_destination_id'
def change
create_table :audit_events_streaming_event_type_filters do |t|
t.timestamps_with_timezone null: false
t.references :external_audit_event_destination,
null: false,
index: false,
foreign_key: { to_table: 'audit_events_external_audit_event_destinations', on_delete: :cascade }
t.text :audit_event_type, null: false, limit: 255
t.index [:external_audit_event_destination_id, :audit_event_type], unique: true, name: UNIQ_INDEX_NAME
end
end
end

View File

@ -0,0 +1 @@
84b89419404d26f7d2783a3adf1fa7b7d89417d6533b393ae6e0de40a31e299a

View File

@ -11858,6 +11858,24 @@ CREATE SEQUENCE audit_events_id_seq
ALTER SEQUENCE audit_events_id_seq OWNED BY audit_events.id;
CREATE TABLE audit_events_streaming_event_type_filters (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
external_audit_event_destination_id bigint NOT NULL,
audit_event_type text NOT NULL,
CONSTRAINT check_d20c8e5a51 CHECK ((char_length(audit_event_type) <= 255))
);
CREATE SEQUENCE audit_events_streaming_event_type_filters_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE audit_events_streaming_event_type_filters_id_seq OWNED BY audit_events_streaming_event_type_filters.id;
CREATE TABLE audit_events_streaming_headers (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@ -23397,6 +23415,8 @@ ALTER TABLE ONLY audit_events ALTER COLUMN id SET DEFAULT nextval('audit_events_
ALTER TABLE ONLY audit_events_external_audit_event_destinations ALTER COLUMN id SET DEFAULT nextval('audit_events_external_audit_event_destinations_id_seq'::regclass);
ALTER TABLE ONLY audit_events_streaming_event_type_filters ALTER COLUMN id SET DEFAULT nextval('audit_events_streaming_event_type_filters_id_seq'::regclass);
ALTER TABLE ONLY audit_events_streaming_headers ALTER COLUMN id SET DEFAULT nextval('audit_events_streaming_headers_id_seq'::regclass);
ALTER TABLE ONLY authentication_events ALTER COLUMN id SET DEFAULT nextval('authentication_events_id_seq'::regclass);
@ -25066,6 +25086,9 @@ ALTER TABLE ONLY audit_events_external_audit_event_destinations
ALTER TABLE ONLY audit_events
ADD CONSTRAINT audit_events_pkey PRIMARY KEY (id, created_at);
ALTER TABLE ONLY audit_events_streaming_event_type_filters
ADD CONSTRAINT audit_events_streaming_event_type_filters_pkey PRIMARY KEY (id);
ALTER TABLE ONLY audit_events_streaming_headers
ADD CONSTRAINT audit_events_streaming_headers_pkey PRIMARY KEY (id);
@ -31162,6 +31185,8 @@ CREATE UNIQUE INDEX unique_merge_request_metrics_by_merge_request_id ON merge_re
CREATE UNIQUE INDEX unique_projects_on_name_namespace_id ON projects USING btree (name, namespace_id);
CREATE UNIQUE INDEX unique_streaming_event_type_filters_destination_id ON audit_events_streaming_event_type_filters USING btree (external_audit_event_destination_id, audit_event_type);
CREATE UNIQUE INDEX unique_vuln_merge_request_link_vuln_id_and_mr_id ON vulnerability_merge_request_links USING btree (vulnerability_id, merge_request_id);
CREATE INDEX user_follow_users_followee_id_idx ON user_follow_users USING btree (followee_id);
@ -34949,6 +34974,9 @@ ALTER TABLE ONLY dast_site_tokens
ALTER TABLE ONLY group_deploy_keys_groups
ADD CONSTRAINT fk_rails_e87145115d FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY audit_events_streaming_event_type_filters
ADD CONSTRAINT fk_rails_e8bd011129 FOREIGN KEY (external_audit_event_destination_id) REFERENCES audit_events_external_audit_event_destinations(id) ON DELETE CASCADE;
ALTER TABLE ONLY description_versions
ADD CONSTRAINT fk_rails_e8f4caf9c7 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;

View File

@ -1,13 +0,0 @@
---
# Suggestion: gitlab.Admin
#
# Checks for "admin" and recommends using the full word instead. "Admin Area" is OK.
#
# For a list of all options, see https://vale.sh/docs/topics/styles/
extends: substitution
message: 'Verify this use of the word "admin". Can it be updated to "administration", "administrator", "administer", or "Admin Area"?'
link: https://docs.gitlab.com/ee/development/documentation/styleguide/index.html
level: suggestion
ignorecase: false
swap:
'[Aa]dmin ?\w*': '(?:Admin( Area| Mode)?|[Aa]dminist(ration|rator|rators|er|rative|ering|ered))'

View File

@ -595,7 +595,7 @@ Returns [`Vulnerability`](#vulnerability).
### `Query.workItem`
Find a work item. Returns `null` if `work_items` feature flag is disabled.
Find a work item.
WARNING:
**Introduced** in 15.1.
@ -5777,7 +5777,7 @@ Input type: `VulnerabilityRevertToDetectedInput`
### `Mutation.workItemCreate`
Creates a work item. Available only when feature flag `work_items` is enabled.
Creates a work item.
WARNING:
**Introduced** in 15.1.
@ -5808,7 +5808,7 @@ Input type: `WorkItemCreateInput`
### `Mutation.workItemCreateFromTask`
Creates a work item from a task in another work item's description. Available only when feature flag `work_items` is enabled.
Creates a work item from a task in another work item's description.
WARNING:
**Introduced** in 15.1.
@ -5835,7 +5835,7 @@ Input type: `WorkItemCreateFromTaskInput`
### `Mutation.workItemDelete`
Deletes a work item. Available only when feature flag `work_items` is enabled.
Deletes a work item.
WARNING:
**Introduced** in 15.1.
@ -5860,7 +5860,7 @@ Input type: `WorkItemDeleteInput`
### `Mutation.workItemDeleteTask`
Deletes a task in a work item's description. Available only when feature flag `work_items` is enabled.
Deletes a task in a work item's description.
WARNING:
**Introduced** in 15.1.
@ -5887,7 +5887,7 @@ Input type: `WorkItemDeleteTaskInput`
### `Mutation.workItemUpdate`
Updates a work item by Global ID. Available only when feature flag `work_items` is enabled.
Updates a work item by Global ID.
WARNING:
**Introduced** in 15.1.
@ -5924,7 +5924,7 @@ Input type: `WorkItemUpdateInput`
### `Mutation.workItemUpdateTask`
Updates a work item's task by Global ID. Available only when feature flag `work_items` is enabled.
Updates a work item's task by Global ID.
WARNING:
**Introduced** in 15.1.
@ -13585,7 +13585,7 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
##### `Group.workItemTypes`
Work item types available to the group. Returns `null` if `work_items` feature flag is disabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice.
Work item types available to the group.
Returns [`WorkItemTypeConnection`](#workitemtypeconnection).
@ -17521,7 +17521,7 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
##### `Project.workItemTypes`
Work item types available to the project. Returns `null` if `work_items` feature flag is disabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice.
Work item types available to the project.
Returns [`WorkItemTypeConnection`](#workitemtypeconnection).
@ -21052,7 +21052,7 @@ Issue type.
| <a id="issuetypeincident"></a>`INCIDENT` | Incident issue type. |
| <a id="issuetypeissue"></a>`ISSUE` | Issue issue type. |
| <a id="issuetyperequirement"></a>`REQUIREMENT` | Requirement issue type. |
| <a id="issuetypetask"></a>`TASK` **{warning-solid}** | **Introduced** in 15.2. This feature is in Alpha. It can be changed or removed at any time. Task issue type. Available only when feature flag `work_items` is enabled. |
| <a id="issuetypetask"></a>`TASK` **{warning-solid}** | **Introduced** in 15.2. This feature is in Alpha. It can be changed or removed at any time. Task issue type. |
| <a id="issuetypetest_case"></a>`TEST_CASE` | Test Case issue type. |
### `IterationSearchableField`

View File

@ -120,24 +120,25 @@ To do so:
### Simulate a SaaS instance
If you're developing locally and need your instance to act like the SaaS version of the product,
you can simulate SaaS by exporting an environment variable:
If you're developing locally and need your instance to simulate the SaaS (GitLab.com)
version of the product:
```shell
export GITLAB_SIMULATE_SAAS=1
```
1. Export this environment variable:
There are many ways to pass an environment variable to your local GitLab instance.
For example, you can create a `env.runit` file in the root of your GDK with the above snippet.
```shell
export GITLAB_SIMULATE_SAAS=1
```
#### Enable plans per namespace
There are many ways to pass an environment variable to your local GitLab instance.
For example, you can create an `env.runit` file in the root of your GDK with the above snippet.
To enable plans per namespace turn on the `Allow use of licensed EE features` option from the settings page.
This will make licensed EE features available to projects only if the project namespace's plan includes the feature
or if the project is public. To enable it:
1. Enable **Allow use of licensed EE features** to make licensed EE features available to projects
only if the project namespace's plan includes the feature.
1. If you are developing locally, follow the steps in [Simulate a SaaS instance](#simulate-a-saas-instance) to make the option available.
1. Visit Admin > Settings > General > "Account and limit" and enable "Allow use of licensed EE features".
1. Visit **Admin > Settings > General**.
1. Expand **Account and limit**.
1. Select the **Allow use of licensed EE features** checkbox.
1. Click **Save changes**.
### Run CI pipelines in a FOSS context

View File

@ -41,7 +41,7 @@ We have built a domain-specific language (DSL) to define the metrics instrumenta
You can use database metrics to track data kept in the database, for example, a count of issues that exist on a given instance.
- `operation`: Operations for the given `relation`, one of `count`, `distinct_count`, `sum`, and `average`.
- `relation`: `ActiveRecord::Relation` for the objects we want to perform the `operation`.
- `relation`: Assigns lambda that returns the `ActiveRecord::Relation` for the objects we want to perform the `operation`. The assigned lambda can accept up to one parameter. The parameter is hashed and stored under the `options` key in the metric definition.
- `start`: Specifies the start value of the batch counting, by default is `relation.minimum(:id)`.
- `finish`: Specifies the end value of the batch counting, by default is `relation.maximum(:id)`.
- `cache_start_and_finish_as`: Specifies the cache key for `start` and `finish` values and sets up caching them. Use this call when `start` and `finish` are expensive queries that should be reused between different metric calculations.
@ -55,10 +55,10 @@ module Gitlab
module Usage
module Metrics
module Instrumentations
class CountBoardsMetric < DatabaseMetric
class CountIssuesMetric < DatabaseMetric
operation :count
relation { Board }
relation ->(options) { Issue.where(confidential: options[:confidential]) }
end
end
end

View File

@ -2,6 +2,9 @@
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml
# NOTE: This template is intended for internal GitLab use only and likely will not work properly
# in any other project. Do not include it in your pipeline configuration.
# For information on how to set up and use DAST, visit https://docs.gitlab.com/ee/user/application_security/dast/
stages:
- build

View File

@ -2,6 +2,9 @@
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml
# NOTE: This template is intended for internal GitLab use only and likely will not work properly
# in any other project. Do not include it in your pipeline configuration.
# For information on how to set up and use DAST, visit https://docs.gitlab.com/ee/user/application_security/dast/
stages:
- build

View File

@ -2,6 +2,9 @@
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/DAST-Runner-Validation.gitlab-ci.yml
# NOTE: This template is intended for internal GitLab use only and likely will not work properly
# in any other project. Do not include it in your pipeline configuration.
# For information on how to set up and use DAST, visit https://docs.gitlab.com/ee/user/application_security/dast/
stages:
- build

View File

@ -40,6 +40,7 @@ atlassian_identities: :gitlab_main
audit_events_external_audit_event_destinations: :gitlab_main
audit_events: :gitlab_main
audit_events_streaming_headers: :gitlab_main
audit_events_streaming_event_type_filters: :gitlab_main
authentication_events: :gitlab_main
award_emoji: :gitlab_main
aws_roles: :gitlab_main

View File

@ -34,10 +34,10 @@ module Gitlab
@metric_finish = block
end
def relation(&block)
return @metric_relation&.call unless block
def relation(relation_proc = nil, &block)
return unless relation_proc || block
@metric_relation = block
@metric_relation = (relation_proc || block)
end
def metric_options(&block)
@ -106,7 +106,11 @@ module Gitlab
end
def relation
self.class.metric_relation.call.where(time_constraints)
if self.class.metric_relation.arity == 1
self.class.metric_relation.call(options)
else
self.class.metric_relation.call
end.where(time_constraints)
end
def time_constraints

View File

@ -4,7 +4,7 @@ module Gitlab
module Usage
module Metrics
module Instrumentations
class DistinctCountProjectsWithExpirationPolicyDisabledMetric < DatabaseMetric
class DistinctCountProjectsWithExpirationPolicyMetric < DatabaseMetric
operation :distinct_count, column: :project_id
start { Project.minimum(:id) }
@ -12,7 +12,7 @@ module Gitlab
cache_start_and_finish_as :project_id
relation { ::ContainerExpirationPolicy.where(enabled: false) }
relation ->(options) { ::ContainerExpirationPolicy.where(enabled: options[:enabled]) }
end
end
end

View File

@ -41,20 +41,6 @@ RSpec.describe DashboardController do
expect(assigns[:issues].map(&:id)).to include(task.id)
end
context 'when work_items is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'does not include tasks in issue list' do
task = create(:work_item, :task, project: project, author: user)
get :issues, params: { author_id: user.id }
expect(assigns[:issues].map(&:id)).not_to include(task.id)
end
end
end
describe 'GET merge requests' do

View File

@ -168,94 +168,56 @@ RSpec.describe Projects::IssuesController do
let_it_be(:task) { create(:issue, :task, project: project) }
context 'when work_items feature flag is enabled' do
shared_examples 'redirects to show work item page' do
context 'when use_iid_in_work_items_path feature flag is disabled' do
before do
stub_feature_flags(use_iid_in_work_items_path: false)
end
it 'redirects to work item page' do
make_request
expect(response).to redirect_to(project_work_items_path(project, task.id, query))
end
shared_examples 'redirects to show work item page' do
context 'when use_iid_in_work_items_path feature flag is disabled' do
before do
stub_feature_flags(use_iid_in_work_items_path: false)
end
it 'redirects to work item page using iid' do
it 'redirects to work item page' do
make_request
expect(response).to redirect_to(project_work_items_path(project, task.iid, query.merge(iid_path: true)))
expect(response).to redirect_to(project_work_items_path(project, task.id, query))
end
end
context 'show action' do
let(:query) { { query: 'any' } }
it 'redirects to work item page using iid' do
make_request
it_behaves_like 'redirects to show work item page' do
subject(:make_request) do
get :show, params: { namespace_id: project.namespace, project_id: project, id: task.iid, **query }
end
end
expect(response).to redirect_to(project_work_items_path(project, task.iid, query.merge(iid_path: true)))
end
end
context 'edit action' do
let(:query) { { query: 'any' } }
context 'show action' do
let(:query) { { query: 'any' } }
it_behaves_like 'redirects to show work item page' do
subject(:make_request) do
get :edit, params: { namespace_id: project.namespace, project_id: project, id: task.iid, **query }
end
end
end
context 'update action' do
it_behaves_like 'redirects to show work item page' do
subject(:make_request) do
put :update, params: {
namespace_id: project.namespace,
project_id: project,
id: task.iid,
issue: { title: 'New title' }
}
end
it_behaves_like 'redirects to show work item page' do
subject(:make_request) do
get :show, params: { namespace_id: project.namespace, project_id: project, id: task.iid, **query }
end
end
end
context 'when work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
context 'edit action' do
let(:query) { { query: 'any' } }
shared_examples 'renders 404' do
it 'renders 404 for show action' do
expect(response).to have_gitlab_http_status(:not_found)
it_behaves_like 'redirects to show work item page' do
subject(:make_request) do
get :edit, params: { namespace_id: project.namespace, project_id: project, id: task.iid, **query }
end
end
end
context 'show action' do
before do
get :show, params: { namespace_id: project.namespace, project_id: project, id: task.iid }
context 'update action' do
it_behaves_like 'redirects to show work item page' do
subject(:make_request) do
put :update, params: {
namespace_id: project.namespace,
project_id: project,
id: task.iid,
issue: { title: 'New title' }
}
end
it_behaves_like 'renders 404'
end
context 'edit action' do
before do
get :edit, params: { namespace_id: project.namespace, project_id: project, id: task.iid }
end
it_behaves_like 'renders 404'
end
context 'update action' do
before do
put :update, params: { namespace_id: project.namespace, project_id: project, id: task.iid, issue: { title: 'New title' } }
end
it_behaves_like 'renders 404'
end
end
end
@ -1728,19 +1690,6 @@ RSpec.describe Projects::IssuesController do
expect(response).to redirect_to(project_issues_path(project))
expect(controller).to set_flash[:notice].to match(/\AYour CSV export has started/i)
end
context 'when work_items is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'does not include tasks in CSV export' do
expect(IssuableExportCsvWorker).to receive(:perform_async)
.with(:issue, viewer.id, project.id, hash_including('issue_types' => Issue::TYPES_FOR_LIST.excluding('task')))
request_csv
end
end
end
context 'when not logged in' do

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
require "spec_helper"
RSpec.describe "Confidential notes on issues", :js do
it_behaves_like 'confidential notes on issuables' do
let_it_be(:issuable_parent) { create(:project) }
let_it_be(:issuable) { create(:issue, project: issuable_parent) }
let_it_be(:user) { create(:user) }
let(:issuable_path) { project_issue_path(issuable_parent, issuable) }
end
end

View File

@ -5,9 +5,9 @@ require "spec_helper"
RSpec.describe "User comments on issue", :js do
include Spec::Support::Helpers::Features::NotesHelpers
let(:project) { create(:project_empty_repo, :public) }
let(:issue) { create(:issue, project: project) }
let(:user) { create(:user) }
let_it_be(:project) { create(:project, :public) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:user) { create(:user) }
before do
project.add_guest(user)

View File

@ -18,7 +18,7 @@ describe('NoteHeader component', () => {
const findActionText = () => wrapper.findComponent({ ref: 'actionText' });
const findTimestampLink = () => wrapper.findComponent({ ref: 'noteTimestampLink' });
const findTimestamp = () => wrapper.findComponent({ ref: 'noteTimestamp' });
const findInternalNoteIndicator = () => wrapper.findByTestId('internalNoteIndicator');
const findInternalNoteIndicator = () => wrapper.findByTestId('internal-note-indicator');
const findSpinner = () => wrapper.findComponent({ ref: 'spinner' });
const statusHtml =

View File

@ -27,14 +27,6 @@ RSpec.describe Resolvers::WorkItemResolver do
end
end
end
context 'when the work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it { is_expected.to be_nil }
end
end
private

View File

@ -29,16 +29,6 @@ RSpec.describe Resolvers::WorkItems::TypesResolver do
expect(result.to_a).to contain_exactly(WorkItems::Type.default_by_type(:task))
end
end
context 'when work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'returns nil' do
expect(result).to be_nil
end
end
end
describe '#resolve' do
@ -53,15 +43,5 @@ RSpec.describe Resolvers::WorkItems::TypesResolver do
it_behaves_like 'a work item type resolver'
end
context 'when parent is not a group or project' do
let(:object) { 'not a project/group' }
it 'returns nil because of feature flag check' do
result = resolve(described_class, obj: object, args: {})
expect(result).to be_nil
end
end
end
end

View File

@ -72,18 +72,6 @@ RSpec.describe Gitlab::UrlBuilder do
end
end
context 'when work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'returns an issue path for an issue of type task' do
task = create(:issue, :task)
expect(subject.build(task, only_path: true)).to eq("/#{task.project.full_path}/-/issues/#{task.iid}")
end
end
context 'when passing a compare' do
# NOTE: The Compare requires an actual repository, which isn't available
# with the `build_stubbed` strategy used by the table tests above

View File

@ -7,8 +7,8 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
described_class.tap do |metric_class|
metric_class.relation { Issue }
metric_class.operation :count
metric_class.start { metric_class.relation.minimum(:id) }
metric_class.finish { metric_class.relation.maximum(:id) }
metric_class.start { Issue.minimum(:id) }
metric_class.finish { Issue.maximum(:id) }
end.new(time_frame: 'all')
end
@ -41,8 +41,8 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
described_class.tap do |metric_class|
metric_class.relation { Issue }
metric_class.operation :count
metric_class.start { metric_class.relation.minimum(:id) }
metric_class.finish { metric_class.relation.maximum(:id) }
metric_class.start { Issue.minimum(:id) }
metric_class.finish { Issue.maximum(:id) }
metric_class.metric_options { { batch_size: 12345 } }
end.new(time_frame: 'all')
end
@ -103,8 +103,8 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
described_class.tap do |metric_class|
metric_class.relation { Issue }
metric_class.operation :count
metric_class.start { metric_class.relation.minimum(:id) }
metric_class.finish { metric_class.relation.maximum(:id) }
metric_class.start { Issue.minimum(:id) }
metric_class.finish { Issue.maximum(:id) }
metric_class.cache_start_and_finish_as :special_issue_count
end.new(time_frame: 'all')
end
@ -126,8 +126,8 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
described_class.tap do |metric_class|
metric_class.relation { Issue }
metric_class.operation(:estimate_batch_distinct_count)
metric_class.start { metric_class.relation.minimum(:id) }
metric_class.finish { metric_class.relation.maximum(:id) }
metric_class.start { Issue.minimum(:id) }
metric_class.finish { Issue.maximum(:id) }
end.new(time_frame: 'all')
end
@ -144,8 +144,8 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
metric_class.operation(:estimate_batch_distinct_count) do |result|
result.foo
end
metric_class.start { metric_class.relation.minimum(:id) }
metric_class.finish { metric_class.relation.maximum(:id) }
metric_class.start { Issue.minimum(:id) }
metric_class.finish { Issue.maximum(:id) }
end.new(time_frame: 'all')
end
@ -192,6 +192,22 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
expect(subject.value).to eq(1)
end
end
context 'with additional parameters passed via options' do
subject do
described_class.tap do |metric_class|
metric_class.relation ->(options) { Issue.where(confidential: options[:confidential]) }
metric_class.operation :count
end.new(time_frame: '28d', options: { confidential: true })
end
it 'calculates a correct result' do
create(:issue, last_edited_at: 5.days.ago, confidential: true)
create(:issue, last_edited_at: 5.days.ago, confidential: false)
expect(subject.value).to eq(1)
end
end
end
context 'with unimplemented operation method used' do

View File

@ -2,18 +2,18 @@
require 'spec_helper'
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DistinctCountProjectsWithExpirationPolicyDisabledMetric do
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DistinctCountProjectsWithExpirationPolicyMetric do
before_all do
create(:container_expiration_policy, enabled: false)
create(:container_expiration_policy, enabled: false, created_at: 29.days.ago)
create(:container_expiration_policy, enabled: true)
end
it_behaves_like 'a correct instrumented metric value', { time_frame: '28d' } do
it_behaves_like 'a correct instrumented metric value', { time_frame: '28d', options: { enabled: false } } do
let(:expected_value) { 1 }
end
it_behaves_like 'a correct instrumented metric value', { time_frame: 'all' } do
it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', options: { enabled: false } } do
let(:expected_value) { 2 }
end
end

View File

@ -10,6 +10,20 @@ RSpec.describe Appearance do
it { is_expected.to have_many(:uploads) }
describe 'default values' do
subject(:appearance) { described_class.new }
it { expect(appearance.title).to eq('') }
it { expect(appearance.description).to eq('') }
it { expect(appearance.new_project_guidelines).to eq('') }
it { expect(appearance.profile_image_guidelines).to eq('') }
it { expect(appearance.header_message).to eq('') }
it { expect(appearance.footer_message).to eq('') }
it { expect(appearance.message_background_color).to eq('#E75E40') }
it { expect(appearance.message_font_color).to eq('#FFFFFF') }
it { expect(appearance.email_header_and_footer_enabled).to eq(false) }
end
describe '#single_appearance_row' do
it 'adds an error when more than 1 row exists' do
create(:appearance)

View File

@ -17,6 +17,14 @@ RSpec.describe ApplicationSetting do
it { expect(setting.uuid).to be_present }
it { expect(setting).to have_db_column(:auto_devops_enabled) }
describe 'default values' do
subject(:setting) { described_class.new }
it { expect(setting.id).to eq(1) }
it { expect(setting.repository_storages_weighted).to eq({}) }
it { expect(setting.kroki_formats).to eq({}) }
end
describe 'validations' do
let(:http) { 'http://example.com' }
let(:https) { 'https://example.com' }

View File

@ -27,6 +27,13 @@ RSpec.describe BroadcastMessage do
it { is_expected.to validate_inclusion_of(:target_access_levels).in_array(described_class::ALLOWED_TARGET_ACCESS_LEVELS) }
end
describe 'default values' do
subject(:message) { described_class.new }
it { expect(message.color).to eq('#E75E40') }
it { expect(message.font).to eq('#FFFFFF') }
end
shared_examples 'time constrainted' do |broadcast_type|
it 'returns message if time match' do
message = create(:broadcast_message, broadcast_type: broadcast_type)

View File

@ -7,6 +7,11 @@ RSpec.describe DependencyProxy::GroupSetting, type: :model do
it { is_expected.to belong_to(:group) }
end
describe 'default values' do
it { is_expected.to be_enabled }
it { expect(described_class.new(enabled: false)).not_to be_enabled }
end
describe 'validations' do
it { is_expected.to validate_presence_of(:group) }
end

View File

@ -26,22 +26,6 @@ RSpec.describe WorkItems::Widgets::Hierarchy do
subject { described_class.new(parent_link.work_item).parent }
it { is_expected.to eq(parent_link.work_item_parent) }
context 'when work_items flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it { is_expected.to be_nil }
end
context 'when work_items flag is enabled for the parent group' do
before do
stub_feature_flags(work_items: group)
end
it { is_expected.to eq(parent_link.work_item_parent) }
end
end
describe '#children' do
@ -51,21 +35,5 @@ RSpec.describe WorkItems::Widgets::Hierarchy do
subject { described_class.new(work_item_parent).children }
it { is_expected.to contain_exactly(parent_link1.work_item, parent_link2.work_item) }
context 'when work_items flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it { is_expected.to be_empty }
end
context 'when work_items flag is enabled for the parent group' do
before do
stub_feature_flags(work_items: group)
end
it { is_expected.to contain_exactly(parent_link1.work_item, parent_link2.work_item) }
end
end
end

View File

@ -629,17 +629,7 @@ RSpec.describe ProjectPolicy do
context 'when user is member of the project' do
let(:current_user) { developer }
context 'when work_items feature flag is enabled' do
it { expect_allowed(:create_task) }
end
context 'when work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it { expect_disallowed(:create_task) }
end
it { expect_allowed(:create_task) }
end
end

View File

@ -26,32 +26,20 @@ RSpec.describe IssuePresenter do
context 'when issue type is task' do
let(:presented_issue) { task }
context 'when work_items feature flag is enabled' do
context 'when use_iid_in_work_items_path feature flag is disabled' do
before do
stub_feature_flags(use_iid_in_work_items_path: false)
end
it 'returns a work item url for the task' do
expect(presenter.web_url).to eq(project_work_items_url(project, work_items_path: presented_issue.id))
end
context 'when use_iid_in_work_items_path feature flag is disabled' do
before do
stub_feature_flags(use_iid_in_work_items_path: false)
end
it 'returns a work item url using iid for the task' do
expect(presenter.web_url).to eq(
project_work_items_url(project, work_items_path: presented_issue.iid, iid_path: true)
)
it 'returns a work item url for the task' do
expect(presenter.web_url).to eq(project_work_items_url(project, work_items_path: presented_issue.id))
end
end
context 'when work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'returns an issue url for the task' do
expect(presenter.web_url).to eq("http://localhost/#{group.name}/#{project.name}/-/issues/#{presented_issue.iid}")
end
it 'returns a work item url using iid for the task' do
expect(presenter.web_url).to eq(
project_work_items_url(project, work_items_path: presented_issue.iid, iid_path: true)
)
end
end
end
@ -78,32 +66,20 @@ RSpec.describe IssuePresenter do
context 'when issue type is task' do
let(:presented_issue) { task }
context 'when work_items feature flag is enabled' do
context 'when use_iid_in_work_items_path feature flag is disabled' do
before do
stub_feature_flags(use_iid_in_work_items_path: false)
end
it 'returns a work item path for the task' do
expect(presenter.issue_path).to eq(project_work_items_path(project, work_items_path: presented_issue.id))
end
context 'when use_iid_in_work_items_path feature flag is disabled' do
before do
stub_feature_flags(use_iid_in_work_items_path: false)
end
it 'returns a work item path using iid for the task' do
expect(presenter.issue_path).to eq(
project_work_items_path(project, work_items_path: presented_issue.iid, iid_path: true)
)
it 'returns a work item path for the task' do
expect(presenter.issue_path).to eq(project_work_items_path(project, work_items_path: presented_issue.id))
end
end
context 'when work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'returns an issue path for the task' do
expect(presenter.issue_path).to eq("/#{group.name}/#{project.name}/-/issues/#{presented_issue.iid}")
end
it 'returns a work item path using iid for the task' do
expect(presenter.issue_path).to eq(
project_work_items_path(project, work_items_path: presented_issue.iid, iid_path: true)
)
end
end
end

View File

@ -57,15 +57,4 @@ RSpec.describe 'getting a list of work item types for a group' do
expect(graphql_data).to eq('group' => nil)
end
end
context 'when the work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
post_graphql(query, current_user: current_user)
end
it 'returns null' do
expect(graphql_data.dig('group', 'workItemTypes')).to be_nil
end
end
end

View File

@ -58,34 +58,15 @@ RSpec.describe 'Create an issue' do
input['type'] = 'TASK'
end
context 'when work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'creates an issue with TASK type' do
expect do
post_graphql_mutation(mutation, current_user: current_user)
end.to change(Issue, :count).by(1)
it 'creates an issue with the default ISSUE type' do
expect do
post_graphql_mutation(mutation, current_user: current_user)
end.to change(Issue, :count).by(1)
created_issue = Issue.last
created_issue = Issue.last
expect(created_issue.work_item_type.base_type).to eq('issue')
expect(created_issue.issue_type).to eq('issue')
end
end
context 'when work_items feature flag is enabled' do
it 'creates an issue with TASK type' do
expect do
post_graphql_mutation(mutation, current_user: current_user)
end.to change(Issue, :count).by(1)
created_issue = Issue.last
expect(created_issue.work_item_type.base_type).to eq('task')
expect(created_issue.issue_type).to eq('task')
end
expect(created_issue.work_item_type.base_type).to eq('task')
expect(created_issue.issue_type).to eq('task')
end
end

View File

@ -71,19 +71,5 @@ RSpec.describe "Create a work item from a task in a work item's description" do
it_behaves_like 'has spam protection' do
let(:mutation_class) { ::Mutations::WorkItems::CreateFromTask }
end
context 'when the work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'does nothing and returns and error' do
expect do
post_graphql_mutation(mutation, current_user: current_user)
end.to not_change(WorkItem, :count)
expect(mutation_response['errors']).to contain_exactly('`work_items` feature flag disabled for this project')
end
end
end
end

View File

@ -215,19 +215,5 @@ RSpec.describe 'Create a work item' do
end
end
end
context 'when the work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'does not create the work item and returns an error' do
expect do
post_graphql_mutation(mutation, current_user: current_user)
end.to not_change(WorkItem, :count)
expect(mutation_response['errors']).to contain_exactly('`work_items` feature flag disabled for this project')
end
end
end
end

View File

@ -31,19 +31,5 @@ RSpec.describe 'Delete a work item' do
expect(response).to have_gitlab_http_status(:success)
expect(mutation_response['project']).to include('id' => work_item.project.to_global_id.to_s)
end
context 'when the work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'does not delete the work item' do
expect do
post_graphql_mutation(mutation, current_user: current_user)
end.to not_change(WorkItem, :count)
expect(mutation_response['errors']).to contain_exactly('`work_items` feature flag disabled for this project')
end
end
end
end

View File

@ -75,19 +75,5 @@ RSpec.describe "Delete a task in a work item's description" do
expect(mutation_response['errors']).to contain_exactly('Stale work item. Check lock version')
end
end
context 'when the work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'does nothing and returns and error' do
expect do
post_graphql_mutation(mutation, current_user: current_user)
end.to not_change(WorkItem, :count)
expect(mutation_response['errors']).to contain_exactly('`work_items` feature flag disabled for this project')
end
end
end
end

View File

@ -644,20 +644,5 @@ RSpec.describe 'Update a work item' do
it_behaves_like 'a mutation that returns top-level errors',
errors: ["Following widget keys are not supported by some_test_case_name type: [:hierarchy_widget]"]
end
context 'when the work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'does not update the work item and returns and error' do
expect do
post_graphql_mutation(mutation, current_user: current_user)
work_item.reload
end.to not_change(work_item, :title)
expect(mutation_response['errors']).to contain_exactly('`work_items` feature flag disabled for this project')
end
end
end
end

View File

@ -74,22 +74,6 @@ RSpec.describe 'Update a work item task' do
it_behaves_like 'has spam protection' do
let(:mutation_class) { ::Mutations::WorkItems::UpdateTask }
end
context 'when the work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'does not update the task item and returns and error' do
expect do
post_graphql_mutation(mutation, current_user: current_user)
work_item.reload
task.reload
end.to not_change(task, :title)
expect(mutation_response['errors']).to contain_exactly('`work_items` feature flag disabled for this project')
end
end
end
context 'when user does not have permissions to update a work item' do

View File

@ -57,15 +57,4 @@ RSpec.describe 'getting a list of work item types for a project' do
expect(graphql_data).to eq('project' => nil)
end
end
context 'when the work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
post_graphql(query, current_user: current_user)
end
it 'returns null' do
expect(graphql_data.dig('project', 'workItemTypes')).to be_nil
end
end
end

View File

@ -130,18 +130,6 @@ RSpec.describe 'getting a work item list for a project' do
end
end
context 'when work_items flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'returns an empty list' do
post_graphql(query)
expect(items_data).to eq([])
end
end
it 'returns only items visible to user' do
post_graphql(query, current_user: current_user)

View File

@ -357,16 +357,4 @@ RSpec.describe 'Query.work_item(id)' do
)
end
end
context 'when the work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'returns nil' do
post_graphql(query)
expect(work_item_data).to be_nil
end
end
end

View File

@ -15,24 +15,10 @@ RSpec.describe 'Work Items' do
sign_in(developer)
end
context 'when the work_items feature flag is enabled' do
it 'renders index' do
get project_work_items_url(work_item.project, work_items_path: work_item.id)
it 'renders index' do
get project_work_items_url(work_item.project, work_items_path: work_item.id)
expect(response).to have_gitlab_http_status(:ok)
end
end
context 'when the work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'returns 404' do
get project_work_items_url(work_item.project, work_items_path: work_item.id)
expect(response).to have_gitlab_http_status(:not_found)
end
expect(response).to have_gitlab_http_status(:ok)
end
end
end

View File

@ -10,8 +10,8 @@ RSpec.shared_examples 'a correct instrumented metric value' do |params|
end
before do
if described_class.respond_to?(:relation) && described_class.relation.respond_to?(:connection)
allow(described_class.relation.connection).to receive(:transaction_open?).and_return(false)
if metric.respond_to?(:relation, true) && metric.send(:relation).respond_to?(:connection)
allow(metric.send(:relation).connection).to receive(:transaction_open?).and_return(false)
end
end

View File

@ -0,0 +1,34 @@
# frozen_string_literal: true
require "spec_helper"
RSpec.shared_examples 'confidential notes on issuables' do
include Spec::Support::Helpers::Features::NotesHelpers
context 'when user does not have permissions' do
it 'does not show confidential note checkbox' do
issuable_parent.add_guest(user)
sign_in(user)
visit(issuable_path)
page.within('.new-note') do
expect(page).not_to have_selector('[data-testid="internal-note-checkbox"]')
end
end
end
context 'when user has permissions' do
it 'creates confidential note' do
issuable_parent.add_reporter(user)
sign_in(user)
visit(issuable_path)
find('[data-testid="internal-note-checkbox"]').click
add_note('Confidential note')
page.within('.note-header') do
expect(page).to have_selector('[data-testid="internal-note-indicator"]')
end
end
end
end

View File

@ -7,6 +7,11 @@ RSpec.shared_examples 'ttl_expirable' do
it_behaves_like 'having unique enum values'
describe 'default values', :freeze_time do
it { expect(described_class.new.read_at).to be_like_time(Time.zone.now) }
it { expect(described_class.new(read_at: 1.day.ago).read_at).to be_like_time(1.day.ago) }
end
describe 'validations' do
it { is_expected.to validate_presence_of(:status) }
end
@ -38,7 +43,7 @@ RSpec.shared_examples 'ttl_expirable' do
end
end
describe '#read', :freeze_time do
describe '#read!', :freeze_time do
let_it_be(:old_read_at) { 1.day.ago }
let_it_be(:item1) { create(class_symbol, read_at: old_read_at) }

View File

@ -226,7 +226,7 @@ func TestUploadHandlerSendingToExternalStorageAndSupportRequestTimeout(t *testin
RemoteObject: api.RemoteObject{
StoreURL: storeServer.URL + "/url/put",
ID: "store-id",
Timeout: 0.001,
Timeout: 0.1,
},
}