diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue index f3530344181..63c7010983e 100644 --- a/app/assets/javascripts/notes/components/note_header.vue +++ b/app/assets/javascripts/notes/components/note_header.vue @@ -198,7 +198,7 @@ export default { { {} } + attribute :kroki_formats, default: -> { {} } chronic_duration_attr_writer :archive_builds_in_human_readable, :archive_builds_in_seconds diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb index 1f921c71984..c5a234ffa69 100644 --- a/app/models/broadcast_message.rb +++ b/app/models/broadcast_message.rb @@ -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' diff --git a/app/models/concerns/ttl_expirable.rb b/app/models/concerns/ttl_expirable.rb index 1c2147beedd..d09ce4873b1 100644 --- a/app/models/concerns/ttl_expirable.rb +++ b/app/models/concerns/ttl_expirable.rb @@ -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 } diff --git a/app/models/dependency_proxy/group_setting.rb b/app/models/dependency_proxy/group_setting.rb index bcf09b27129..3a7ae66a263 100644 --- a/app/models/dependency_proxy/group_setting.rb +++ b/app/models/dependency_proxy/group_setting.rb @@ -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 diff --git a/app/models/project.rb b/app/models/project.rb index 211e00eb7c6..db30a74112d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -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 diff --git a/app/models/work_items/widgets/hierarchy.rb b/app/models/work_items/widgets/hierarchy.rb index 930aced8ace..d0819076efd 100644 --- a/app/models/work_items/widgets/hierarchy.rb +++ b/app/models/work_items/widgets/hierarchy.rb @@ -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 diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index 832b78bb9c3..3ba753ab60d 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -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. diff --git a/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml b/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml index c2294650494..6b6f0e978ae 100644 --- a/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml +++ b/config/metrics/counts_all/20210216181014_projects_with_expiration_policy_disabled.yml @@ -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 diff --git a/db/docs/audit_events_streaming_event_type_filters.yml b/db/docs/audit_events_streaming_event_type_filters.yml new file mode 100644 index 00000000000..7119c84589e --- /dev/null +++ b/db/docs/audit_events_streaming_event_type_filters.yml @@ -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' diff --git a/db/migrate/20221003151747_create_audit_events_streaming_event_type_filters.rb b/db/migrate/20221003151747_create_audit_events_streaming_event_type_filters.rb new file mode 100644 index 00000000000..c0acbe75d78 --- /dev/null +++ b/db/migrate/20221003151747_create_audit_events_streaming_event_type_filters.rb @@ -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 diff --git a/db/schema_migrations/20221003151747 b/db/schema_migrations/20221003151747 new file mode 100644 index 00000000000..70a8babf308 --- /dev/null +++ b/db/schema_migrations/20221003151747 @@ -0,0 +1 @@ +84b89419404d26f7d2783a3adf1fa7b7d89417d6533b393ae6e0de40a31e299a \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 7f9d177a3ea..9d295fb6cb0 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -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; diff --git a/doc/.vale/gitlab/Admin.yml b/doc/.vale/gitlab/Admin.yml deleted file mode 100644 index 6160eb85c8e..00000000000 --- a/doc/.vale/gitlab/Admin.yml +++ /dev/null @@ -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))' diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 46b23e4394e..8fe1ac5c696 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -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. | `INCIDENT` | Incident issue type. | | `ISSUE` | Issue issue type. | | `REQUIREMENT` | Requirement issue type. | -| `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. | +| `TASK` **{warning-solid}** | **Introduced** in 15.2. This feature is in Alpha. It can be changed or removed at any time. Task issue type. | | `TEST_CASE` | Test Case issue type. | ### `IterationSearchableField` diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md index ac740542ef5..9b17b694194 100644 --- a/doc/development/ee_features.md +++ b/doc/development/ee_features.md @@ -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 diff --git a/doc/development/service_ping/metrics_instrumentation.md b/doc/development/service_ping/metrics_instrumentation.md index 4b00d1fc56d..759e1cf11df 100644 --- a/doc/development/service_ping/metrics_instrumentation.md +++ b/doc/development/service_ping/metrics_instrumentation.md @@ -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 diff --git a/lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml index 1bd527a6ec0..5863da142f0 100644 --- a/lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml @@ -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 diff --git a/lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml index 701e08ba56d..733ba4e4954 100644 --- a/lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml @@ -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 diff --git a/lib/gitlab/ci/templates/Security/DAST-Runner-Validation.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST-Runner-Validation.gitlab-ci.yml index 5b6af37977e..c75ff2e9ff8 100644 --- a/lib/gitlab/ci/templates/Security/DAST-Runner-Validation.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/DAST-Runner-Validation.gitlab-ci.yml @@ -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 diff --git a/lib/gitlab/database/gitlab_schemas.yml b/lib/gitlab/database/gitlab_schemas.yml index db563f109c4..928c28e1fc0 100644 --- a/lib/gitlab/database/gitlab_schemas.yml +++ b/lib/gitlab/database/gitlab_schemas.yml @@ -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 diff --git a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb index 6dec0349a38..f0d5298870c 100644 --- a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb +++ b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb @@ -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 diff --git a/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric.rb b/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_metric.rb similarity index 65% rename from lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric.rb rename to lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_metric.rb index 0c421dc3311..8811dec49d8 100644 --- a/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric.rb +++ b/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_metric.rb @@ -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 diff --git a/spec/controllers/dashboard_controller_spec.rb b/spec/controllers/dashboard_controller_spec.rb index 21810f64cb4..ea12b0c5ad7 100644 --- a/spec/controllers/dashboard_controller_spec.rb +++ b/spec/controllers/dashboard_controller_spec.rb @@ -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 diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index bb5dc4dfc46..3166b502741 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -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 diff --git a/spec/features/issues/confidential_notes_spec.rb b/spec/features/issues/confidential_notes_spec.rb new file mode 100644 index 00000000000..858c054c803 --- /dev/null +++ b/spec/features/issues/confidential_notes_spec.rb @@ -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 diff --git a/spec/features/issues/user_comments_on_issue_spec.rb b/spec/features/issues/user_comments_on_issue_spec.rb index a1e7c007b90..ef00e66af7e 100644 --- a/spec/features/issues/user_comments_on_issue_spec.rb +++ b/spec/features/issues/user_comments_on_issue_spec.rb @@ -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) diff --git a/spec/frontend/notes/components/note_header_spec.js b/spec/frontend/notes/components/note_header_spec.js index b870cda2a24..56c22b09e1b 100644 --- a/spec/frontend/notes/components/note_header_spec.js +++ b/spec/frontend/notes/components/note_header_spec.js @@ -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 = diff --git a/spec/graphql/resolvers/work_item_resolver_spec.rb b/spec/graphql/resolvers/work_item_resolver_spec.rb index c44ed395102..dacc6ac11d8 100644 --- a/spec/graphql/resolvers/work_item_resolver_spec.rb +++ b/spec/graphql/resolvers/work_item_resolver_spec.rb @@ -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 diff --git a/spec/graphql/resolvers/work_items/types_resolver_spec.rb b/spec/graphql/resolvers/work_items/types_resolver_spec.rb index 868f4566ad6..5121a105523 100644 --- a/spec/graphql/resolvers/work_items/types_resolver_spec.rb +++ b/spec/graphql/resolvers/work_items/types_resolver_spec.rb @@ -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 diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb index f2b99fd4d26..2e9a444bd24 100644 --- a/spec/lib/gitlab/url_builder_spec.rb +++ b/spec/lib/gitlab/url_builder_spec.rb @@ -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 diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb index f73155642d6..6532a304b2e 100644 --- a/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb +++ b/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb @@ -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 diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_metric_spec.rb similarity index 79% rename from spec/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric_spec.rb rename to spec/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_metric_spec.rb index 757adee6117..d46de893a8a 100644 --- a/spec/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric_spec.rb +++ b/spec/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_metric_spec.rb @@ -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 diff --git a/spec/models/appearance_spec.rb b/spec/models/appearance_spec.rb index 2817e177d28..9d84279a75e 100644 --- a/spec/models/appearance_spec.rb +++ b/spec/models/appearance_spec.rb @@ -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) diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 77bb6b502b5..a6341b91a5d 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -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' } diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb index b0bfdabe13c..8fdc9852f6e 100644 --- a/spec/models/broadcast_message_spec.rb +++ b/spec/models/broadcast_message_spec.rb @@ -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) diff --git a/spec/models/dependency_proxy/group_setting_spec.rb b/spec/models/dependency_proxy/group_setting_spec.rb index c4c4a877d50..4da1fe42ff2 100644 --- a/spec/models/dependency_proxy/group_setting_spec.rb +++ b/spec/models/dependency_proxy/group_setting_spec.rb @@ -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 diff --git a/spec/models/work_items/widgets/hierarchy_spec.rb b/spec/models/work_items/widgets/hierarchy_spec.rb index cd528772710..c847f2694fe 100644 --- a/spec/models/work_items/widgets/hierarchy_spec.rb +++ b/spec/models/work_items/widgets/hierarchy_spec.rb @@ -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 diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index bf361c00374..1024d4f0b4a 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -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 diff --git a/spec/presenters/issue_presenter_spec.rb b/spec/presenters/issue_presenter_spec.rb index fff6e81a550..df43b0279dd 100644 --- a/spec/presenters/issue_presenter_spec.rb +++ b/spec/presenters/issue_presenter_spec.rb @@ -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 diff --git a/spec/requests/api/graphql/group/work_item_types_spec.rb b/spec/requests/api/graphql/group/work_item_types_spec.rb index d6b0673e4f8..35090e2a89f 100644 --- a/spec/requests/api/graphql/group/work_item_types_spec.rb +++ b/spec/requests/api/graphql/group/work_item_types_spec.rb @@ -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 diff --git a/spec/requests/api/graphql/mutations/issues/create_spec.rb b/spec/requests/api/graphql/mutations/issues/create_spec.rb index 9345735afe4..a489b7424e8 100644 --- a/spec/requests/api/graphql/mutations/issues/create_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/create_spec.rb @@ -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 diff --git a/spec/requests/api/graphql/mutations/work_items/create_from_task_spec.rb b/spec/requests/api/graphql/mutations/work_items/create_from_task_spec.rb index e7f4917ddde..c6a980b5cef 100644 --- a/spec/requests/api/graphql/mutations/work_items/create_from_task_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/create_from_task_spec.rb @@ -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 diff --git a/spec/requests/api/graphql/mutations/work_items/create_spec.rb b/spec/requests/api/graphql/mutations/work_items/create_spec.rb index 2fd4c5e7b35..be3917316c3 100644 --- a/spec/requests/api/graphql/mutations/work_items/create_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/create_spec.rb @@ -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 diff --git a/spec/requests/api/graphql/mutations/work_items/delete_spec.rb b/spec/requests/api/graphql/mutations/work_items/delete_spec.rb index 14c8b757a57..0a84225a7ab 100644 --- a/spec/requests/api/graphql/mutations/work_items/delete_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/delete_spec.rb @@ -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 diff --git a/spec/requests/api/graphql/mutations/work_items/delete_task_spec.rb b/spec/requests/api/graphql/mutations/work_items/delete_task_spec.rb index e576d0ee7ef..c44939c8d54 100644 --- a/spec/requests/api/graphql/mutations/work_items/delete_task_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/delete_task_spec.rb @@ -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 diff --git a/spec/requests/api/graphql/mutations/work_items/update_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_spec.rb index a6d4f518f5b..96736457f26 100644 --- a/spec/requests/api/graphql/mutations/work_items/update_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/update_spec.rb @@ -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 diff --git a/spec/requests/api/graphql/mutations/work_items/update_task_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_task_spec.rb index 32468a46ace..55285be5a5d 100644 --- a/spec/requests/api/graphql/mutations/work_items/update_task_spec.rb +++ b/spec/requests/api/graphql/mutations/work_items/update_task_spec.rb @@ -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 diff --git a/spec/requests/api/graphql/project/work_item_types_spec.rb b/spec/requests/api/graphql/project/work_item_types_spec.rb index 157961c3f66..3d30baab816 100644 --- a/spec/requests/api/graphql/project/work_item_types_spec.rb +++ b/spec/requests/api/graphql/project/work_item_types_spec.rb @@ -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 diff --git a/spec/requests/api/graphql/project/work_items_spec.rb b/spec/requests/api/graphql/project/work_items_spec.rb index 3c41950d578..6d20799c9ec 100644 --- a/spec/requests/api/graphql/project/work_items_spec.rb +++ b/spec/requests/api/graphql/project/work_items_spec.rb @@ -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) diff --git a/spec/requests/api/graphql/work_item_spec.rb b/spec/requests/api/graphql/work_item_spec.rb index 08333824c05..a55de6adfb2 100644 --- a/spec/requests/api/graphql/work_item_spec.rb +++ b/spec/requests/api/graphql/work_item_spec.rb @@ -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 diff --git a/spec/requests/projects/work_items_spec.rb b/spec/requests/projects/work_items_spec.rb index e6365a3824a..4d7acc73d4f 100644 --- a/spec/requests/projects/work_items_spec.rb +++ b/spec/requests/projects/work_items_spec.rb @@ -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 diff --git a/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb b/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb index e02bf66507a..e9a13f7bf63 100644 --- a/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb +++ b/spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb @@ -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 diff --git a/spec/support/shared_examples/features/confidential_notes_shared_examples.rb b/spec/support/shared_examples/features/confidential_notes_shared_examples.rb new file mode 100644 index 00000000000..289da025af6 --- /dev/null +++ b/spec/support/shared_examples/features/confidential_notes_shared_examples.rb @@ -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 diff --git a/spec/support/shared_examples/models/concerns/ttl_expirable_shared_examples.rb b/spec/support/shared_examples/models/concerns/ttl_expirable_shared_examples.rb index 174b8609337..ac34ee32c6d 100644 --- a/spec/support/shared_examples/models/concerns/ttl_expirable_shared_examples.rb +++ b/spec/support/shared_examples/models/concerns/ttl_expirable_shared_examples.rb @@ -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) } diff --git a/workhorse/internal/upload/artifacts_store_test.go b/workhorse/internal/upload/artifacts_store_test.go index edba13d38ae..4ebf4c86180 100644 --- a/workhorse/internal/upload/artifacts_store_test.go +++ b/workhorse/internal/upload/artifacts_store_test.go @@ -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, }, }