Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-11-16 03:12:06 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-11-16 03:12:06 +0300
commitd22bc415db079dfffb443cf2e0e428542a8b14db (patch)
treeefade75bdb2b49c872ae493340c76e9b2095d344
parenta7d47330045c163760517a49f5fd35854e089c6e (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/controllers/projects/issue_links_controller.rb2
-rw-r--r--app/models/pages_deployment.rb22
-rw-r--r--app/policies/issue_policy.rb5
-rw-r--r--app/policies/project_policy.rb1
-rw-r--r--app/serializers/linked_project_issue_entity.rb30
-rw-r--r--app/services/admin/set_feature_flag_service.rb1
-rw-r--r--app/services/issue_links/create_service.rb30
-rw-r--r--app/services/issue_links/destroy_service.rb4
-rw-r--r--app/services/projects/update_pages_service.rb3
-rw-r--r--db/migrate/20231115091119_add_upload_finished_to_pages_deployments.rb14
-rw-r--r--db/post_migrate/20231115151449_update_pages_deployments_upload_ready_default_value.rb13
-rw-r--r--db/schema_migrations/202311150911191
-rw-r--r--db/schema_migrations/202311151514491
-rw-r--r--db/structure.sql1
-rw-r--r--doc/administration/analytics/index.md2
-rw-r--r--doc/administration/audit_event_streaming/graphql_api.md12
-rw-r--r--doc/administration/docs_self_host.md2
-rw-r--r--doc/administration/license.md2
-rw-r--r--doc/administration/moderate_users.md4
-rw-r--r--doc/administration/pages/index.md8
-rw-r--r--doc/administration/raketasks/github_import.md2
-rw-r--r--doc/administration/secure_files.md2
-rw-r--r--doc/administration/settings/deprecated_api_rate_limits.md2
-rw-r--r--doc/administration/settings/files_api_rate_limits.md2
-rw-r--r--doc/administration/settings/project_integration_management.md6
-rw-r--r--doc/administration/settings/sign_up_restrictions.md4
-rw-r--r--doc/administration/settings/slack_app.md4
-rw-r--r--doc/administration/terraform_state.md2
-rw-r--r--doc/api/discussions.md2
-rw-r--r--doc/api/job_artifacts.md2
-rw-r--r--doc/api/pages.md2
-rw-r--r--doc/api/pages_domains.md2
-rw-r--r--doc/api/projects.md2
-rw-r--r--doc/api/users.md2
-rw-r--r--doc/ci/chatops/index.md2
-rw-r--r--doc/ci/environments/deployment_approvals.md2
-rw-r--r--doc/ci/jobs/ci_job_token.md8
-rw-r--r--doc/ci/pipelines/cicd_minutes.md14
-rw-r--r--doc/ci/review_apps/index.md2
-rw-r--r--doc/ci/runners/runners_scope.md22
-rw-r--r--doc/ci/test_cases/index.md4
-rw-r--r--doc/ci/testing/code_quality.md2
-rw-r--r--doc/ci/triggers/index.md2
-rw-r--r--doc/ci/variables/index.md12
-rw-r--r--doc/development/documentation/topic_types/task.md2
-rw-r--r--doc/development/secure_coding_guidelines.md31
-rw-r--r--doc/integration/advanced_search/elasticsearch.md2
-rw-r--r--doc/integration/jira/jira_server_configuration.md2
-rw-r--r--doc/operations/incident_management/escalation_policies.md2
-rw-r--r--doc/operations/incident_management/oncall_schedules.md2
-rw-r--r--doc/operations/incident_management/status_page.md2
-rw-r--r--doc/security/user_file_uploads.md2
-rw-r--r--doc/security/webhooks.md8
-rw-r--r--doc/subscriptions/gitlab_com/index.md4
-rw-r--r--doc/topics/autodevops/cicd_variables.md2
-rw-r--r--doc/user/analytics/analytics_dashboards.md2
-rw-r--r--doc/user/analytics/code_review_analytics.md2
-rw-r--r--doc/user/analytics/merge_request_analytics.md2
-rw-r--r--doc/user/analytics/productivity_analytics.md2
-rw-r--r--doc/user/analytics/value_streams_dashboard.md6
-rw-r--r--doc/user/application_security/vulnerabilities/index.md4
-rw-r--r--doc/user/clusters/agent/user_access.md2
-rw-r--r--doc/user/clusters/agent/work_with_agent.md2
-rw-r--r--doc/user/custom_roles.md8
-rw-r--r--doc/user/discussions/index.md2
-rw-r--r--doc/user/free_user_limit.md2
-rw-r--r--doc/user/group/compliance_frameworks.md2
-rw-r--r--doc/user/group/custom_project_templates.md2
-rw-r--r--doc/user/group/devops_adoption/index.md2
-rw-r--r--doc/user/group/import/index.md2
-rw-r--r--doc/user/group/index.md2
-rw-r--r--doc/user/group/manage.md14
-rw-r--r--doc/user/group/subgroups/index.md4
-rw-r--r--doc/user/group/value_stream_analytics/index.md2
-rw-r--r--doc/user/okrs.md6
-rw-r--r--doc/user/packages/nuget_repository/index.md4
-rw-r--r--doc/user/packages/package_registry/index.md2
-rw-r--r--doc/user/packages/workflows/build_packages.md2
-rw-r--r--doc/user/permissions.md2
-rw-r--r--doc/user/product_analytics/index.md2
-rw-r--r--doc/user/profile/account/create_accounts.md4
-rw-r--r--doc/user/profile/personal_access_tokens.md8
-rw-r--r--doc/user/profile/service_accounts.md4
-rw-r--r--doc/user/project/import/bitbucket_server.md2
-rw-r--r--doc/user/project/import/github.md2
-rw-r--r--doc/user/project/integrations/index.md8
-rw-r--r--doc/user/project/integrations/mattermost_slash_commands.md2
-rw-r--r--doc/user/project/issues/managing_issues.md2
-rw-r--r--doc/user/project/issues/related_issues.md2
-rw-r--r--doc/user/project/members/index.md6
-rw-r--r--doc/user/project/merge_requests/approvals/settings.md2
-rw-r--r--doc/user/project/merge_requests/commit_templates.md2
-rw-r--r--doc/user/project/merge_requests/dependencies.md4
-rw-r--r--doc/user/project/merge_requests/merge_when_pipeline_succeeds.md2
-rw-r--r--doc/user/project/protected_branches.md4
-rw-r--r--doc/user/project/protected_tags.md2
-rw-r--r--doc/user/project/repository/mirror/index.md2
-rw-r--r--doc/user/project/repository/push_rules.md2
-rw-r--r--doc/user/project/requirements/index.md10
-rw-r--r--doc/user/project/service_desk/configure.md2
-rw-r--r--doc/user/project/settings/index.md8
-rw-r--r--doc/user/project/working_with_projects.md8
-rw-r--r--doc/user/public_access.md2
-rw-r--r--doc/user/tasks.md6
-rw-r--r--doc/user/workspace/configuration.md2
-rw-r--r--lib/feature.rb60
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/features/issues/related_issues_spec.rb41
-rw-r--r--spec/lib/feature_spec.rb70
-rw-r--r--spec/models/pages_deployment_spec.rb10
-rw-r--r--spec/policies/issue_policy_spec.rb57
-rw-r--r--spec/requests/api/issue_links_spec.rb10
-rw-r--r--spec/requests/projects/issue_links_controller_spec.rb42
-rw-r--r--spec/services/issue_links/create_service_spec.rb1
-rw-r--r--spec/services/issue_links/list_service_spec.rb13
-rw-r--r--spec/services/issues/create_service_spec.rb5
-rw-r--r--spec/support/helpers/stub_feature_flags.rb2
-rw-r--r--spec/support/shared_contexts/policies/project_policy_shared_context.rb2
-rw-r--r--spec/support/shared_examples/policies/project_policy_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/services/issuable_links/create_links_shared_examples.rb10
-rw-r--r--spec/uploaders/pages/deployment_uploader_spec.rb39
121 files changed, 499 insertions, 371 deletions
diff --git a/app/controllers/projects/issue_links_controller.rb b/app/controllers/projects/issue_links_controller.rb
index 4a5f9309aed..956557457fa 100644
--- a/app/controllers/projects/issue_links_controller.rb
+++ b/app/controllers/projects/issue_links_controller.rb
@@ -13,7 +13,7 @@ module Projects
private
def authorize_admin_issue_link!
- render_403 unless can?(current_user, :admin_issue_link, issue)
+ render_403 unless can?(current_user, :admin_issue_link, @project)
end
def authorize_issue_link_association!
diff --git a/app/models/pages_deployment.rb b/app/models/pages_deployment.rb
index 2aa36a94171..0d87a8f6cf6 100644
--- a/app/models/pages_deployment.rb
+++ b/app/models/pages_deployment.rb
@@ -5,6 +5,9 @@ class PagesDeployment < ApplicationRecord
include EachBatch
include FileStoreMounter
include Gitlab::Utils::StrongMemoize
+ include SafelyChangeColumnDefault
+
+ columns_changing_default :upload_ready
attribute :file_store, :integer, default: -> { ::Pages::DeploymentUploader.default_store }
@@ -18,7 +21,12 @@ class PagesDeployment < ApplicationRecord
scope :with_files_stored_remotely, -> { where(file_store: ::ObjectStorage::Store::REMOTE) }
scope :project_id_in, ->(ids) { where(project_id: ids) }
scope :with_path_prefix, ->(prefix) { where("COALESCE(path_prefix, '') = ?", prefix.to_s) }
- scope :active, -> { where(deleted_at: nil).order(created_at: :desc) }
+
+ # We have to mark the PagesDeployment upload as ready to ensure we only
+ # serve PagesDeployment which files are already uploaded.
+ scope :upload_ready, -> { where(upload_ready: true) }
+
+ scope :active, -> { upload_ready.where(deleted_at: nil).order(created_at: :desc) }
scope :deactivated, -> { where('deleted_at < ?', Time.now.utc) }
validates :file, presence: true
@@ -64,6 +72,18 @@ class PagesDeployment < ApplicationRecord
return unless previous_changes.key?(:file)
store_file_now!
+ mark_upload_as_finished!
+ end
+
+ # We have to mark the PagesDeployment upload as ready to ensure we only
+ # serve PagesDeployment which files are already uploaded.
+ #
+ # This is required because we're uploading the file outside of the db transaction
+ # (https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114774)
+ def mark_upload_as_finished!
+ return unless file && file.exists?
+
+ update_column(:upload_ready, true)
end
end
diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb
index dfb33fb386a..683c53d8d78 100644
--- a/app/policies/issue_policy.rb
+++ b/app/policies/issue_policy.rb
@@ -80,7 +80,6 @@ class IssuePolicy < IssuablePolicy
rule { ~anonymous & can?(:read_issue) }.policy do
enable :create_todo
enable :update_subscription
- enable :create_issue_link
end
rule { can?(:admin_issue) }.policy do
@@ -104,10 +103,6 @@ class IssuePolicy < IssuablePolicy
enable :admin_issue_relation
end
- rule { can?(:guest_access) & can?(:read_issue) & is_project_member }.policy do
- enable :admin_issue_link
- end
-
rule { can_read_crm_contacts }.policy do
enable :read_crm_contacts
end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index e0e04174110..bbb0e3df500 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -379,6 +379,7 @@ class ProjectPolicy < BasePolicy
enable :admin_label
enable :admin_milestone
enable :admin_issue_board_list
+ enable :admin_issue_link
enable :read_commit_status
enable :read_build
enable :read_container_image
diff --git a/app/serializers/linked_project_issue_entity.rb b/app/serializers/linked_project_issue_entity.rb
index 28dca69a8d4..c95f68f58a3 100644
--- a/app/serializers/linked_project_issue_entity.rb
+++ b/app/serializers/linked_project_issue_entity.rb
@@ -4,11 +4,10 @@ class LinkedProjectIssueEntity < LinkedIssueEntity
include Gitlab::Utils::StrongMemoize
expose :relation_path, override: true do |issue|
- # Make sure the user can admin the links of one issue and
- # create links in the other issue in order to return the removal link.
- if can_create_or_destroy_issue_link?(issue)
- project_issue_link_path(issuable.project, issuable.iid,
- issue.issue_link_id)
+ # Make sure the user can admin both the current issue AND the
+ # referenced issue projects in order to return the removal link.
+ if can_admin_issue_link_on_current_project? && can_admin_issue_link?(issue.project)
+ project_issue_link_path(issuable.project, issuable.iid, issue.issue_link_id)
end
end
@@ -18,24 +17,13 @@ class LinkedProjectIssueEntity < LinkedIssueEntity
private
- # A user can create/destroy an issue link if they can
- # admin the links for one issue AND create links for the other
- def can_create_or_destroy_issue_link?(issue)
- (can_admin_issue_link?(issuable) && can_create_issue_link?(issue)) ||
- (can_admin_issue_link?(issue) && can_create_issue_link?(issuable))
- end
-
- def can_admin_issue_link_on_current_issue?
- strong_memoize(:can_admin_on_current_issue) do
- can_admin_issue_link?(issuable)
+ def can_admin_issue_link_on_current_project?
+ strong_memoize(:can_admin_on_current_project) do
+ can_admin_issue_link?(issuable.project)
end
end
- def can_admin_issue_link?(issue)
- Ability.allowed?(current_user, :admin_issue_link, issue)
- end
-
- def can_create_issue_link?(issue)
- Ability.allowed?(current_user, :create_issue_link, issue)
+ def can_admin_issue_link?(project)
+ Ability.allowed?(current_user, :admin_issue_link, project)
end
end
diff --git a/app/services/admin/set_feature_flag_service.rb b/app/services/admin/set_feature_flag_service.rb
index 3378be7eddd..e7969d02e0b 100644
--- a/app/services/admin/set_feature_flag_service.rb
+++ b/app/services/admin/set_feature_flag_service.rb
@@ -62,6 +62,7 @@ module Admin
Feature.disable(name)
elsif percentage_of_actors?
Feature.enable_percentage_of_actors(name, percentage)
+ # Deprecated in favor of Feature.enabled?(name, :instance) + Feature.enable_percentage_of_actors(name, percentage)
elsif percentage_of_time?
Feature.enable_percentage_of_time(name, percentage)
else
diff --git a/app/services/issue_links/create_service.rb b/app/services/issue_links/create_service.rb
index d4ef35d3c60..3523e945d37 100644
--- a/app/services/issue_links/create_service.rb
+++ b/app/services/issue_links/create_service.rb
@@ -4,17 +4,8 @@ module IssueLinks
class CreateService < IssuableLinks::CreateService
include IncidentManagement::UsageData
- def execute
- return error(issue_no_permission_error_message, 403) unless can?(current_user, :admin_issue_link, issuable) ||
- can?(current_user, :create_issue_link, issuable)
-
- super
- end
-
def linkable_issuables(issues)
- @linkable_issuables ||= issues.select do |issue|
- can_create_destroy_issue_link?(issue)
- end
+ @linkable_issuables ||= issues.select { |issue| can?(current_user, :admin_issue_link, issue) }
end
def previous_related_issuables
@@ -23,21 +14,6 @@ module IssueLinks
private
- # A user can create/destroy an issue link if they can
- # admin the links for one issue AND create links for the other
- def can_create_destroy_issue_link?(issue)
- (can_admin_issue_link?(issuable) && can_create_issue_link?(issue)) ||
- (can_admin_issue_link?(issue) && can_create_issue_link?(issuable))
- end
-
- def can_admin_issue_link?(issue)
- Ability.allowed?(current_user, :admin_issue_link, issue)
- end
-
- def can_create_issue_link?(issue)
- Ability.allowed?(current_user, :create_issue_link, issue)
- end
-
def readonly_issuables(issuables)
@readonly_issuables ||= issuables.select { |issuable| issuable.readable_by?(current_user) }
end
@@ -49,10 +25,6 @@ module IssueLinks
def link_class
IssueLink
end
-
- def issue_no_permission_error_message
- _("Couldn't link issues. You must have at least the Guest role in the source issue's project.")
- end
end
end
diff --git a/app/services/issue_links/destroy_service.rb b/app/services/issue_links/destroy_service.rb
index 2281bebcb86..9116e9fb703 100644
--- a/app/services/issue_links/destroy_service.rb
+++ b/app/services/issue_links/destroy_service.rb
@@ -3,13 +3,11 @@
module IssueLinks
class DestroyService < IssuableLinks::DestroyService
include IncidentManagement::UsageData
- include Gitlab::Utils::StrongMemoize
private
def permission_to_remove_relation?
- (can?(current_user, :admin_issue_link, link.source) && can?(current_user, :create_issue_link, link.target)) ||
- (can?(current_user, :admin_issue_link, link.target) && can?(current_user, :create_issue_link, link.source))
+ can?(current_user, :admin_issue_link, source) && can?(current_user, :admin_issue_link, target)
end
def track_event
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
index 83b28840d39..fd6c9a86540 100644
--- a/app/services/projects/update_pages_service.rb
+++ b/app/services/projects/update_pages_service.rb
@@ -98,7 +98,8 @@ module Projects
file_count: deployment_update.entries_count,
file_sha256: build.job_artifacts_archive.file_sha256,
ci_build_id: build.id,
- root_directory: build.options[:publish]
+ root_directory: build.options[:publish],
+ upload_ready: false
}
end
diff --git a/db/migrate/20231115091119_add_upload_finished_to_pages_deployments.rb b/db/migrate/20231115091119_add_upload_finished_to_pages_deployments.rb
new file mode 100644
index 00000000000..d35b8a05fb4
--- /dev/null
+++ b/db/migrate/20231115091119_add_upload_finished_to_pages_deployments.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class AddUploadFinishedToPagesDeployments < Gitlab::Database::Migration[2.2]
+ milestone '16.6'
+
+ def change
+ # Existing deployments must be consider `upload_ready` For this reason,
+ # the column is created with `default: true`, and then changed to
+ # `default: false` in post_migrate/20231115151449_update_pages_deployments_upload_ready_default_value.rb.
+ # This way, existing deployments are set as `upload_ready: true`,
+ # but new ones are created as `upload_ready: false`
+ add_column :pages_deployments, :upload_ready, :boolean, default: true
+ end
+end
diff --git a/db/post_migrate/20231115151449_update_pages_deployments_upload_ready_default_value.rb b/db/post_migrate/20231115151449_update_pages_deployments_upload_ready_default_value.rb
new file mode 100644
index 00000000000..976ff8a200c
--- /dev/null
+++ b/db/post_migrate/20231115151449_update_pages_deployments_upload_ready_default_value.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class UpdatePagesDeploymentsUploadReadyDefaultValue < Gitlab::Database::Migration[2.2]
+ milestone '16.6'
+
+ def up
+ change_column_default :pages_deployments, :upload_ready, from: true, to: false
+ end
+
+ def down
+ change_column_default :pages_deployments, :upload_ready, from: false, to: true
+ end
+end
diff --git a/db/schema_migrations/20231115091119 b/db/schema_migrations/20231115091119
new file mode 100644
index 00000000000..9e1669953fd
--- /dev/null
+++ b/db/schema_migrations/20231115091119
@@ -0,0 +1 @@
+8974454db089c031509a6218134ac6c6bb53bd3a028f0ba83e7329d7d6445a59 \ No newline at end of file
diff --git a/db/schema_migrations/20231115151449 b/db/schema_migrations/20231115151449
new file mode 100644
index 00000000000..01d16b2a310
--- /dev/null
+++ b/db/schema_migrations/20231115151449
@@ -0,0 +1 @@
+493ba17c2dd4519c734c7ea31c2c9c6651c73b0892bd17e8fade699491f78a89 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 2a8ac3a5223..a4bb90f3305 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -20738,6 +20738,7 @@ CREATE TABLE pages_deployments (
path_prefix text,
build_ref text,
deleted_at timestamp with time zone,
+ upload_ready boolean DEFAULT false,
CONSTRAINT check_4d04b8dc9a CHECK ((char_length(path_prefix) <= 128)),
CONSTRAINT check_5f9132a958 CHECK ((size IS NOT NULL)),
CONSTRAINT check_7e938c810a CHECK ((char_length(root_directory) <= 255)),
diff --git a/doc/administration/analytics/index.md b/doc/administration/analytics/index.md
index 5ba14222165..de113a79f73 100644
--- a/doc/administration/analytics/index.md
+++ b/doc/administration/analytics/index.md
@@ -12,7 +12,7 @@ Instance-level analytics provide insights into the feature and data usage of you
## View instance-level analytics
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
diff --git a/doc/administration/audit_event_streaming/graphql_api.md b/doc/administration/audit_event_streaming/graphql_api.md
index 58668902b8e..00bbbffbc23 100644
--- a/doc/administration/audit_event_streaming/graphql_api.md
+++ b/doc/administration/audit_event_streaming/graphql_api.md
@@ -378,7 +378,7 @@ Event streaming is enabled if:
List all Google Cloud Logging configuration destinations for a top-level group.
-Prerequisite:
+Prerequisites:
- Owner role for a top-level group.
@@ -410,7 +410,7 @@ You need the ID values returned by this query for the update and delete mutation
Update a Google Cloud Logging configuration destinations for a top-level group.
-Prerequisite:
+Prerequisites:
- Owner role for a top-level group.
@@ -446,7 +446,7 @@ Delete streaming destinations for a top-level group.
When the last destination is successfully deleted, streaming is disabled for the group.
-Prerequisite:
+Prerequisites:
- Owner role for a top-level group.
@@ -786,7 +786,7 @@ Event streaming is enabled if:
List all Google Cloud Logging configuration destinations for an instance.
-Prerequisite:
+Prerequisites:
- You have administrator access to the instance.
@@ -815,7 +815,7 @@ You need the ID values returned by this query for the update and delete mutation
Update the Google Cloud Logging configuration destinations for an instance.
-Prerequisite:
+Prerequisites:
- You have administrator access to the instance.
@@ -851,7 +851,7 @@ Delete streaming destinations for an instance.
When the last destination is successfully deleted, streaming is disabled for the instance.
-Prerequisite:
+Prerequisites:
- You have administrator access to the instance.
diff --git a/doc/administration/docs_self_host.md b/doc/administration/docs_self_host.md
index 1eecc139d1f..60865ca9469 100644
--- a/doc/administration/docs_self_host.md
+++ b/doc/administration/docs_self_host.md
@@ -82,7 +82,7 @@ To run the GitLab product documentation website in a Docker container:
You can use GitLab Pages to host the GitLab product documentation.
-Prerequisite:
+Prerequisites:
- Ensure the Pages site URL does not use a subfolder. Because of the way the
site is pre-compiled, the CSS and JavaScript files are relative to the
diff --git a/doc/administration/license.md b/doc/administration/license.md
index 05b60955ed9..e0fa320d584 100644
--- a/doc/administration/license.md
+++ b/doc/administration/license.md
@@ -15,7 +15,7 @@ your instance with an activation code.
In GitLab Enterprise Edition 14.1 and later, you need an activation code to activate
your instance.
-Prerequisite:
+Prerequisites:
- You must [purchase a subscription](https://about.gitlab.com/pricing/).
- You must be running GitLab Enterprise Edition (EE).
diff --git a/doc/administration/moderate_users.md b/doc/administration/moderate_users.md
index c12eb2b9a95..f6f1b2f70a7 100644
--- a/doc/administration/moderate_users.md
+++ b/doc/administration/moderate_users.md
@@ -71,7 +71,7 @@ GitLab administrators can block and unblock users.
### Block a user
-Prerequisite:
+Prerequisites:
- You must be an administrator for the instance.
@@ -295,7 +295,7 @@ You can trust and untrust users from the Admin Area.
By default, a user is not trusted and is blocked from creating issues, notes, and snippets considered to be spam. When you trust a user, they can create issues, notes, and snippets without being blocked.
-Prerequisite:
+Prerequisites:
- You must be an administrator.
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 97acbf717fe..3e81d8219c1 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -683,7 +683,7 @@ Follow the steps below to configure the proxy listener of GitLab Pages.
## Set global maximum size of each GitLab Pages site **(FREE SELF)**
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
@@ -698,7 +698,7 @@ To set the global maximum pages size for a project:
## Set maximum size of each GitLab Pages site in a group **(PREMIUM SELF)**
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
@@ -712,7 +712,7 @@ To set the maximum size of each GitLab Pages site in a group, overriding the inh
## Set maximum size of GitLab Pages site in a project **(PREMIUM SELF)**
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
@@ -725,7 +725,7 @@ To set the maximum size of GitLab Pages site in a project, overriding the inheri
## Set maximum number of GitLab Pages custom domains for a project
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
diff --git a/doc/administration/raketasks/github_import.md b/doc/administration/raketasks/github_import.md
index a4d52899f21..78c39661a63 100644
--- a/doc/administration/raketasks/github_import.md
+++ b/doc/administration/raketasks/github_import.md
@@ -25,7 +25,7 @@ before/after the brackets. Also, some shells (for example, Zsh) can interpret th
You can only import repositories that are in the namespace of the owner of the GitHub personal access token being used to import. For more information, see
[issue 424105](https://gitlab.com/gitlab-org/gitlab/-/issues/424105).
-Prerequisite:
+Prerequisites:
- At least the Maintainer role on the destination group to import to.
diff --git a/doc/administration/secure_files.md b/doc/administration/secure_files.md
index 6c61c390655..60b7b884206 100644
--- a/doc/administration/secure_files.md
+++ b/doc/administration/secure_files.md
@@ -30,7 +30,7 @@ Secure Files to reduce disk space, or to remove access to the feature.
To disable Secure Files, follow the steps below according to your installation.
-Prerequisite:
+Prerequisites:
- You must be an administrator.
diff --git a/doc/administration/settings/deprecated_api_rate_limits.md b/doc/administration/settings/deprecated_api_rate_limits.md
index 21385a6779d..445c8f97298 100644
--- a/doc/administration/settings/deprecated_api_rate_limits.md
+++ b/doc/administration/settings/deprecated_api_rate_limits.md
@@ -28,7 +28,7 @@ the general user and IP rate limits for requests to deprecated endpoints. You ca
and IP rate limits already in place, and increase or decrease the rate limits
for deprecated API endpoints. No other new features are provided by this override.
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
diff --git a/doc/administration/settings/files_api_rate_limits.md b/doc/administration/settings/files_api_rate_limits.md
index 025f8c86993..aa6a3337fdb 100644
--- a/doc/administration/settings/files_api_rate_limits.md
+++ b/doc/administration/settings/files_api_rate_limits.md
@@ -24,7 +24,7 @@ the general user and IP rate limits for requests to the
and IP rate limits already in place, and increase or decrease the rate limits
for the Files API. No other new features are provided by this override.
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
diff --git a/doc/administration/settings/project_integration_management.md b/doc/administration/settings/project_integration_management.md
index 32756e65eaf..94eaa0233a2 100644
--- a/doc/administration/settings/project_integration_management.md
+++ b/doc/administration/settings/project_integration_management.md
@@ -23,7 +23,7 @@ is proposed in [epic 2137](https://gitlab.com/groups/gitlab-org/-/epics/2137).
## Manage instance-level default settings for a project integration
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
@@ -65,7 +65,7 @@ is proposed in [epic 2137](https://gitlab.com/groups/gitlab-org/-/epics/2137).
### Remove an instance-level default setting
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
@@ -83,7 +83,7 @@ Resetting an instance-level default setting removes the integration from all pro
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218252) in GitLab 14.2.
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
diff --git a/doc/administration/settings/sign_up_restrictions.md b/doc/administration/settings/sign_up_restrictions.md
index da40a2bab05..99e78d89051 100644
--- a/doc/administration/settings/sign_up_restrictions.md
+++ b/doc/administration/settings/sign_up_restrictions.md
@@ -101,7 +101,7 @@ The user cap might apply only retrospectively after the cap has already been exc
To ensure the cap is enabled immediately, set the cap to a value below the current number of
billable users (for example, `1`).
-Prerequisite:
+Prerequisites:
- You must be an administrator.
@@ -121,7 +121,7 @@ administrator approval is not restricted.
After you remove the user cap, users pending approval are automatically approved.
-Prerequisite:
+Prerequisites:
- You must be an administrator.
diff --git a/doc/administration/settings/slack_app.md b/doc/administration/settings/slack_app.md
index de11da281e4..fbc0f7cf251 100644
--- a/doc/administration/settings/slack_app.md
+++ b/doc/administration/settings/slack_app.md
@@ -18,7 +18,7 @@ The app is a private one-time copy installed in your Slack workspace only and no
## Create a GitLab for Slack app
-Prerequisite:
+Prerequisites:
- You must be at least a [Slack workspace administrator](https://slack.com/help/articles/360018112273-Types-of-roles-in-Slack).
@@ -70,7 +70,7 @@ To use Slash commands for a project, configure the [GitLab for Slack app](../../
## Update the GitLab for Slack app
-Prerequisite:
+Prerequisites:
- You must be at least a [Slack workspace administrator](https://slack.com/help/articles/360018112273-Types-of-roles-in-Slack).
diff --git a/doc/administration/terraform_state.md b/doc/administration/terraform_state.md
index bf0774478ee..47fe3150c1e 100644
--- a/doc/administration/terraform_state.md
+++ b/doc/administration/terraform_state.md
@@ -36,7 +36,7 @@ When Terraform state administration is disabled:
To disable Terraform administration, follow the steps below according to your installation.
-Prerequisite:
+Prerequisites:
- You must be an administrator.
diff --git a/doc/api/discussions.md b/doc/api/discussions.md
index dac2c886166..1e99e5e7fb0 100644
--- a/doc/api/discussions.md
+++ b/doc/api/discussions.md
@@ -1010,7 +1010,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
Resolve or unresolve a thread of discussion in a merge request.
-Prerequisite:
+Prerequisites:
- You must have at least the Developer role, or be the author of the change being reviewed.
diff --git a/doc/api/job_artifacts.md b/doc/api/job_artifacts.md
index e9d4915da57..3f6f6606dbe 100644
--- a/doc/api/job_artifacts.md
+++ b/doc/api/job_artifacts.md
@@ -326,7 +326,7 @@ of the regular cleanup of expired job artifacts. Job logs are never deleted.
The regular cleanup occurs asynchronously on a schedule, so there might be a short delay
before artifacts are deleted.
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for the project.
diff --git a/doc/api/pages.md b/doc/api/pages.md
index 1a1ccf4143d..b9500121292 100644
--- a/doc/api/pages.md
+++ b/doc/api/pages.md
@@ -12,7 +12,7 @@ The GitLab Pages feature must be enabled to use these endpoints. Find out more a
## Unpublish Pages
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
diff --git a/doc/api/pages_domains.md b/doc/api/pages_domains.md
index d66c2d9d567..075912f190d 100644
--- a/doc/api/pages_domains.md
+++ b/doc/api/pages_domains.md
@@ -12,7 +12,7 @@ The GitLab Pages feature must be enabled to use these endpoints. Find out more a
## List all Pages domains
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 92b0d02d377..cbed5193040 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -308,7 +308,7 @@ Keyset pagination supports only `order_by=id`. Other sorting options aren't avai
Get a list of visible projects owned by the given user. When accessed without
authentication, only public projects are returned.
-Prerequisite:
+Prerequisites:
- To view [certain attributes](https://gitlab.com/gitlab-org/gitlab/-/blob/520776fa8e5a11b8275b7c597d75246fcfc74c89/lib/api/entities/project.rb#L109-130), you must be an administrator or have the Owner role for the project.
diff --git a/doc/api/users.md b/doc/api/users.md
index 6b60917b78d..53f99bb59f4 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -1715,7 +1715,7 @@ Parameters:
## Delete email for given user **(FREE SELF)**
-Prerequisite:
+Prerequisites:
- You must be an administrator of a self-managed GitLab instance.
diff --git a/doc/ci/chatops/index.md b/doc/ci/chatops/index.md
index 454266942f6..0fbcbae4cf0 100644
--- a/doc/ci/chatops/index.md
+++ b/doc/ci/chatops/index.md
@@ -103,7 +103,7 @@ ls:
## Trigger a CI/CD job using ChatOps
-Prerequisite:
+Prerequisites:
- You must have at least the Developer role for the project.
- The project is configured to use a slash command integration.
diff --git a/doc/ci/environments/deployment_approvals.md b/doc/ci/environments/deployment_approvals.md
index b14ee5eb3eb..3b19569ad4c 100644
--- a/doc/ci/environments/deployment_approvals.md
+++ b/doc/ci/environments/deployment_approvals.md
@@ -23,7 +23,7 @@ require approvals for deployments to production environments.
You can require approvals for deployments to protected environments in
a project.
-Prerequisite:
+Prerequisites:
- To update an environment, you must have at least the Maintainer role.
diff --git a/doc/ci/jobs/ci_job_token.md b/doc/ci/jobs/ci_job_token.md
index 3e632f0a94c..5ef3b21fad4 100644
--- a/doc/ci/jobs/ci_job_token.md
+++ b/doc/ci/jobs/ci_job_token.md
@@ -120,7 +120,7 @@ the following actions without being added to the allowlist:
To limit access to these actions to only the projects on the allowlist, set the visibility
of each feature to be only accessible to project members:
-Prerequisite:
+Prerequisites:
- You must have the Maintainer role for the project.
@@ -145,7 +145,7 @@ your maintainers, the job token could be used in an attempt to access your proje
You can disable the job token scope allowlist for testing or a similar reason,
but you should enable it again as soon as possible.
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for the project.
@@ -166,7 +166,7 @@ You can also disable the allowlist [with the API](../../api/graphql/reference/in
You can add projects to the allowlist for a project. Projects added to the allowlist
can make API calls from running pipelines by using the CI/CD job token.
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role in the current project. If the allowed project
is internal or private, you must have at least the Guest role in that project.
@@ -210,7 +210,7 @@ to make an API request to project `B`, then `B` must be added to the allowlist f
> **Limit CI_JOB_TOKEN access** setting [renamed to **Limit access _from_ this project**](https://gitlab.com/gitlab-org/gitlab/-/issues/411406) in GitLab 16.3.
-Prerequisite:
+Prerequisites:
- You must not have more than 200 projects added to the token's scope.
diff --git a/doc/ci/pipelines/cicd_minutes.md b/doc/ci/pipelines/cicd_minutes.md
index a6b2774dbde..c5b9b27511a 100644
--- a/doc/ci/pipelines/cicd_minutes.md
+++ b/doc/ci/pipelines/cicd_minutes.md
@@ -53,7 +53,7 @@ By default, GitLab instances do not have a compute quota.
The default value for the quota is `0`, which is unlimited.
However, you can change this default value.
-Prerequisite:
+Prerequisites:
- You must be a GitLab administrator.
@@ -75,7 +75,7 @@ If a quota is already defined for a specific namespace, this value does not chan
You can override the global value and set a compute quota
for a specific namespace.
-Prerequisite:
+Prerequisites:
- You must be a GitLab administrator.
@@ -97,7 +97,7 @@ If you set a quota for a subgroup, it is not used.
## View compute usage
-Prerequisite:
+Prerequisites:
- You must have access to the build to view the total usage and quota summary for a namespace associated with a build.
- Access to **Usage Quotas** page is based on your role in the associated namespace or group.
@@ -106,7 +106,7 @@ Prerequisite:
> Displaying shared runners duration per project [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/355666) in GitLab 15.0.
-Prerequisite:
+Prerequisites:
- You must have the Owner role for the group.
@@ -125,7 +125,7 @@ subgroups, sorted in descending order of compute usage.
> Displaying shared runners duration [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345795) in GitLab 15.0.
-Prerequisite:
+Prerequisites:
- The namespace must be your personal namespace.
@@ -164,7 +164,7 @@ You can find pricing for additional compute minutes on the
### Purchase compute minutes for a group **(FREE SAAS)**
-Prerequisite:
+Prerequisites:
- You must have the Owner role for the group.
@@ -183,7 +183,7 @@ namespace.
### Purchase compute minutes for a personal namespace **(FREE SAAS)**
-Prerequisite:
+Prerequisites:
- The namespace must be your personal namespace.
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index f831c53c024..beaf34f63bb 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -70,7 +70,7 @@ as mentioned above. To facilitate this, and if you are using Kubernetes, you can
**Enable review apps** and GitLab prompts you with a template code block that
you can copy and paste into `.gitlab-ci.yml` as a starting point.
-Prerequisite:
+Prerequisites:
- You need at least the Developer role for the project.
diff --git a/doc/ci/runners/runners_scope.md b/doc/ci/runners/runners_scope.md
index 6b6493db2c4..52ce46682d6 100644
--- a/doc/ci/runners/runners_scope.md
+++ b/doc/ci/runners/runners_scope.md
@@ -40,7 +40,7 @@ If you are using GitLab.com:
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/389269) in GitLab 16.0.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/415447) in GitLab 16.2. Feature flag `create_runner_workflow_for_admin` removed.
-Prerequisite:
+Prerequisites:
- You must be an administrator.
@@ -78,7 +78,7 @@ The ability to pass a runner registration token, and support for certain configu
[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/380872) in GitLab 15.6 and will be removed in GitLab 18.0. Runner authentication tokens
should be used instead. For more information, see [Migrating to the new runner registration workflow](new_creation_workflow.md).
-Prerequisite:
+Prerequisites:
- You must be an administrator.
@@ -93,7 +93,7 @@ To create a shared runner:
### Pause or resume a shared runner
-Prerequisite:
+Prerequisites:
- You must be an administrator.
@@ -109,7 +109,7 @@ You can pause a runner so that it does not accept jobs from groups and projects
### Delete shared runners
-Prerequisite:
+Prerequisites:
- You must be an administrator.
@@ -295,7 +295,7 @@ how to [register a runner](https://docs.gitlab.com/runner/register/#register-wit
> Ability for users with the Maintainer role to view group runners [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/384179) in GitLab 16.4.
-Prerequisite:
+Prerequisites:
- You must have the Maintainer or Owner role for the group.
@@ -324,7 +324,7 @@ those in other groups:
### Pause or resume a group runner
-Prerequisite:
+Prerequisites:
- You must be an administrator or have the Owner role for the group.
@@ -342,7 +342,7 @@ instance. If you pause a group runner that is used by multiple projects, the run
> Multiple runner deletion [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/361721/) in GitLab 15.6.
-Prerequisite:
+Prerequisites:
- You must be an administrator or have the Owner role for the group.
@@ -365,7 +365,7 @@ To delete a single or multiple group runners:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/363012) in GitLab 15.1.
-Prerequisite:
+Prerequisites:
- You must have the Owner role for the group.
@@ -469,7 +469,7 @@ The ability to pass a runner registration token, and support for certain configu
[deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/380872) in GitLab 15.6 and will be removed in GitLab 18.0. Runner authentication tokens
should be used instead. For more information, see [Migrating to the new runner registration workflow](new_creation_workflow.md).
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for the project.
@@ -487,7 +487,7 @@ The runner is now enabled for the project.
### Pause or resume a project runner
-Prerequisite:
+Prerequisites:
- You must be an administrator, or have the Maintainer role for the project.
@@ -631,7 +631,7 @@ different places.
### Determine the IP address of a shared runner
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
diff --git a/doc/ci/test_cases/index.md b/doc/ci/test_cases/index.md
index 071884f2bed..9341f8fecea 100644
--- a/doc/ci/test_cases/index.md
+++ b/doc/ci/test_cases/index.md
@@ -21,7 +21,7 @@ For more information, see [Product Stage Direction - Plan](https://about.gitlab.
## Create a test case
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role.
@@ -91,7 +91,7 @@ or editing an existing one.
When you want to stop using a test case, you can archive it. You can [reopen an archived test case](#reopen-an-archived-test-case) later.
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role.
diff --git a/doc/ci/testing/code_quality.md b/doc/ci/testing/code_quality.md
index 93b6ea7c352..b191ce606e9 100644
--- a/doc/ci/testing/code_quality.md
+++ b/doc/ci/testing/code_quality.md
@@ -422,7 +422,7 @@ code_quality:
You can use a Dependency Proxy to reduce the time taken to download dependencies.
-Prerequisite:
+Prerequisites:
- [Dependency Proxy](../../user/packages/dependency_proxy/index.md) enabled in the project's
group.
diff --git a/doc/ci/triggers/index.md b/doc/ci/triggers/index.md
index ee1e05c4fc9..e1d43088678 100644
--- a/doc/ci/triggers/index.md
+++ b/doc/ci/triggers/index.md
@@ -21,7 +21,7 @@ When authenticating with the API, you can use:
You can trigger a pipeline for a branch or tag by generating a pipeline trigger token and using it
to authenticate an API call. The token impersonates a user's project access and permissions.
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for the project.
diff --git a/doc/ci/variables/index.md b/doc/ci/variables/index.md
index 0c05129fb1e..01de75af6bf 100644
--- a/doc/ci/variables/index.md
+++ b/doc/ci/variables/index.md
@@ -130,7 +130,7 @@ all variables become available to the pipeline.
You can add CI/CD variables to a project's settings.
-Prerequisite:
+Prerequisites:
- You must be a project member with the Maintainer role.
@@ -159,7 +159,7 @@ or in [job scripts](#use-cicd-variables-in-job-scripts).
You can make a CI/CD variable available to all projects in a group.
-Prerequisite:
+Prerequisites:
- You must be a group member with the Owner role.
@@ -188,7 +188,7 @@ are recursively inherited.
You can make a CI/CD variable available to all projects and groups in a GitLab instance.
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
@@ -262,7 +262,7 @@ to prevent commands such as `env`/`printenv` from printing secret variables.
You can mask a project, group, or instance CI/CD variable so the value of the variable
does not display in job logs.
-Prerequisite:
+Prerequisites:
- You must have the same role or access level as required to [define a CI/CD variable in the UI](#define-a-cicd-variable-in-the-ui).
@@ -306,7 +306,7 @@ temporary merge commit, not a branch or tag, do not have access to these variabl
[Merge request pipelines](../pipelines/merge_request_pipelines.md), which do not use
a temporary merge commit, can access these variables if the branch is a protected branch.
-Prerequisite:
+Prerequisites:
- You must have the same role or access level as required to [define a CI/CD variable in the UI](#define-a-cicd-variable-in-the-ui).
@@ -626,7 +626,7 @@ Expanded variables treat values with the `$` character as a reference to another
CI/CD variables are expanded by default. To treat variables with a `$` character as raw strings,
disable variable expansion for the variable
-Prerequisite:
+Prerequisites:
- You must have the same role or access level as required to [define a CI/CD variable in the UI](#define-a-cicd-variable-in-the-ui).
diff --git a/doc/development/documentation/topic_types/task.md b/doc/development/documentation/topic_types/task.md
index 42a9826f07f..f6447ca5cb6 100644
--- a/doc/development/documentation/topic_types/task.md
+++ b/doc/development/documentation/topic_types/task.md
@@ -155,6 +155,8 @@ As a best practice, if the task requires the user to have a role other than Gues
put the minimum role in the prerequisites. See [the Word list](../styleguide/word_list.md) for
how to write the phrase for each role.
+`Prerequisites` should always be plural, even if it includes only one item.
+
## Related topics
- [How to write task steps](../styleguide/index.md#navigation)
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index c46cde9a31a..946826e72da 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -1308,6 +1308,24 @@ This sensitive data must be handled carefully to avoid leaks which could lead to
In the event of credential leak through an MR, issue, or any other medium, [reach out to SIRT team](https://about.gitlab.com/handbook/security/security-operations/sirt/#-engaging-sirt).
+### Token prefixes
+
+User error or software bugs can lead to tokens leaking. Consider prepending a static prefix to the beginning of secrets and adding that prefix to our secrets detection capabilities. For example, GitLab Personal Access Tokens have a prefix so that the plaintext is `glpat-1234567890abcdefghij`.
+
+The prefix pattern should be:
+
+1. `gl` for GitLab
+1. lowercase letters abbreviating the token class name
+1. a hyphen (`-`)
+
+Add the new prefix to:
+
+- [`gitlab/app/assets/javascripts/lib/utils/secret_detection.js`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/lib/utils/secret_detection.js)
+- The [GitLab Secret Detection gem](https://gitlab.com/gitlab-org/gitlab/-/tree/master/gems/gitlab-secret_detection)
+- GitLab [secrets SAST analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/secrets)
+- [Tokinator](https://gitlab.com/gitlab-com/gl-security/appsec/tokinator/-/blob/main/CONTRIBUTING.md?ref_type=heads) (internal tool / team members only)
+- [Token Overview](../security/token_overview.md#gitlab-tokens) documentation
+
### Examples
Encrypting a token with `attr_encrypted` so that the plaintext can be retrieved
@@ -1339,6 +1357,19 @@ class WebHookLog < ApplicationRecord
end
```
+Using the `TokenAuthenticatable` class helper to create a prefixed token.
+
+```ruby
+class User
+ FEED_TOKEN_PREFIX = 'glft-'
+
+ add_authentication_token_field :feed_token, format_with_prefix: :prefix_for_feed_token
+
+ def prefix_for_feed_token
+ FEED_TOKEN_PREFIX
+ end
+```
+
## Serialization
Serialization of active record models can leak sensitive attributes if they are not protected.
diff --git a/doc/integration/advanced_search/elasticsearch.md b/doc/integration/advanced_search/elasticsearch.md
index ef756be3ba4..97a6a872a5b 100644
--- a/doc/integration/advanced_search/elasticsearch.md
+++ b/doc/integration/advanced_search/elasticsearch.md
@@ -162,7 +162,7 @@ These errors may occur when indexing Git repository data.
## Enable advanced search
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
diff --git a/doc/integration/jira/jira_server_configuration.md b/doc/integration/jira/jira_server_configuration.md
index 7788714b966..969691fa04c 100644
--- a/doc/integration/jira/jira_server_configuration.md
+++ b/doc/integration/jira/jira_server_configuration.md
@@ -15,7 +15,7 @@ To create Jira credentials, here's what we're going to do:
1. [Create a Jira group for the user](#create-a-jira-group-for-the-user).
1. [Create a permission scheme for the group](#create-a-permission-scheme-for-the-group).
-Prerequisite:
+Prerequisites:
- You must have [site administrator](https://support.atlassian.com/user-management/docs/give-users-admin-permissions/#Make-someone-a-site-admin) access to the Jira instance.
diff --git a/doc/operations/incident_management/escalation_policies.md b/doc/operations/incident_management/escalation_policies.md
index 604e223cf55..3e1585c930d 100644
--- a/doc/operations/incident_management/escalation_policies.md
+++ b/doc/operations/incident_management/escalation_policies.md
@@ -15,7 +15,7 @@ where you manage [On-call schedules](oncall_schedules.md).
## Add an escalation policy
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role.
- You must have an [on-call schedule](oncall_schedules.md).
diff --git a/doc/operations/incident_management/oncall_schedules.md b/doc/operations/incident_management/oncall_schedules.md
index 255cc79b3ce..e885cbd4589 100644
--- a/doc/operations/incident_management/oncall_schedules.md
+++ b/doc/operations/incident_management/oncall_schedules.md
@@ -22,7 +22,7 @@ To use on-call schedules:
Set up an on-call schedule for your team to add rotations to.
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role.
diff --git a/doc/operations/incident_management/status_page.md b/doc/operations/incident_management/status_page.md
index 1d376301250..3835ea3078a 100644
--- a/doc/operations/incident_management/status_page.md
+++ b/doc/operations/incident_management/status_page.md
@@ -39,7 +39,7 @@ To configure a GitLab Status Page you must:
Only AWS S3 is supported as a deploy target.
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role.
diff --git a/doc/security/user_file_uploads.md b/doc/security/user_file_uploads.md
index 91a21454fe5..728fb785272 100644
--- a/doc/security/user_file_uploads.md
+++ b/doc/security/user_file_uploads.md
@@ -40,7 +40,7 @@ Only authenticated project members can view non-image attachments (including PDF
To apply authentication requirements to image files in private or internal projects:
-Prerequisite:
+Prerequisites:
- You must have the Maintainer or Owner role for the project.
- Your project visibility settings must be **Private** or **Internal**.
diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md
index d2c3e2174c1..bcef2684fcf 100644
--- a/doc/security/webhooks.md
+++ b/doc/security/webhooks.md
@@ -38,7 +38,7 @@ can get the GitLab server to make `POST` HTTP requests to endpoints that delete
### Allow requests to the local network from webhooks and integrations
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
@@ -58,7 +58,7 @@ To allow access to these addresses:
### Prevent requests to the local network from system hooks
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
@@ -74,7 +74,7 @@ Prerequisite:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/377371) in GitLab 15.10.
-Prerequisite:
+Prerequisites:
- You must have administrator access to the GitLab instance.
@@ -100,7 +100,7 @@ rules.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44496) in GitLab 12.2.
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md
index d4e7bb71c73..3dcea451995 100644
--- a/doc/subscriptions/gitlab_com/index.md
+++ b/doc/subscriptions/gitlab_com/index.md
@@ -42,7 +42,7 @@ To subscribe to GitLab SaaS:
## View your GitLab SaaS subscription
-Prerequisite:
+Prerequisites:
- You must have the Owner role for the group.
@@ -413,7 +413,7 @@ locked. Projects can only be unlocked by purchasing more storage subscription un
### Purchase more storage and transfer
-Prerequisite:
+Prerequisites:
- You must have the Owner role.
diff --git a/doc/topics/autodevops/cicd_variables.md b/doc/topics/autodevops/cicd_variables.md
index 4fa2ee10c75..ccea1d736a3 100644
--- a/doc/topics/autodevops/cicd_variables.md
+++ b/doc/topics/autodevops/cicd_variables.md
@@ -133,7 +133,7 @@ Auto DevOps detects CI/CD variables starting with `K8S_SECRET_`,
and makes them available to the deployed application as
environment variables.
-Prerequisite:
+Prerequisites:
- The variable value must be a single line.
diff --git a/doc/user/analytics/analytics_dashboards.md b/doc/user/analytics/analytics_dashboards.md
index 65516396bee..832df86f3c6 100644
--- a/doc/user/analytics/analytics_dashboards.md
+++ b/doc/user/analytics/analytics_dashboards.md
@@ -98,7 +98,7 @@ You can use the dashboard designer to:
## View project dashboards
-Prerequisite:
+Prerequisites:
- You must have at least the Developer role for the project.
diff --git a/doc/user/analytics/code_review_analytics.md b/doc/user/analytics/code_review_analytics.md
index e5b475d0e45..850375daa80 100644
--- a/doc/user/analytics/code_review_analytics.md
+++ b/doc/user/analytics/code_review_analytics.md
@@ -28,7 +28,7 @@ For a video explanation, see [Code review analytics: Faster code review](https:/
## View code review analytics
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role.
diff --git a/doc/user/analytics/merge_request_analytics.md b/doc/user/analytics/merge_request_analytics.md
index 0f8eb9ac211..a8e8e6eeb64 100644
--- a/doc/user/analytics/merge_request_analytics.md
+++ b/doc/user/analytics/merge_request_analytics.md
@@ -23,7 +23,7 @@ You can use merge request analytics to identify:
## View merge request analytics
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role.
diff --git a/doc/user/analytics/productivity_analytics.md b/doc/user/analytics/productivity_analytics.md
index a17eb08c53c..5494272db80 100644
--- a/doc/user/analytics/productivity_analytics.md
+++ b/doc/user/analytics/productivity_analytics.md
@@ -22,7 +22,7 @@ To view merge request data for projects, use [Merge request analytics](../analyt
## View productivity analytics
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role for the group.
diff --git a/doc/user/analytics/value_streams_dashboard.md b/doc/user/analytics/value_streams_dashboard.md
index b5358cc81c8..a7b570803d7 100644
--- a/doc/user/analytics/value_streams_dashboard.md
+++ b/doc/user/analytics/value_streams_dashboard.md
@@ -81,7 +81,7 @@ On self-managed GitLab, by default this feature is available. To hide the featur
On GitLab.com, this feature is not available.
This feature is not ready for production use.
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
@@ -96,7 +96,7 @@ To retrieve aggregated usage counts in the group, use the [GraphQL API](../../ap
## View the value streams dashboard
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role for the group.
- Overview background aggregation for Value Streams Dashboards must be enabled.
@@ -136,7 +136,7 @@ Query parameters can still be used to override the YAML configuration.
First, you need to set up the project.
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for the group.
diff --git a/doc/user/application_security/vulnerabilities/index.md b/doc/user/application_security/vulnerabilities/index.md
index 68e7a183f30..13816569b3b 100644
--- a/doc/user/application_security/vulnerabilities/index.md
+++ b/doc/user/application_security/vulnerabilities/index.md
@@ -180,7 +180,7 @@ Adding a link helps track the issue that resolves or mitigates a vulnerability.
### Link a vulnerability to existing GitLab issues
-Prerequisite:
+Prerequisites:
- [Jira issue integration](../../../integration/jira/configure.md) must not be enabled.
@@ -209,7 +209,7 @@ Be aware of the following conditions between a vulnerability and a linked GitLab
### Link a vulnerability to existing Jira issues
-Prerequisite:
+Prerequisites:
- [Jira issue integration](../../../integration/jira/configure.md) must be enabled, with option **Enable Jira issue creation from vulnerabilities** also enabled.
diff --git a/doc/user/clusters/agent/user_access.md b/doc/user/clusters/agent/user_access.md
index b3735770a97..f251c690d4d 100644
--- a/doc/user/clusters/agent/user_access.md
+++ b/doc/user/clusters/agent/user_access.md
@@ -147,7 +147,7 @@ subjects:
You can configure an agent to allow GitLab users to access a cluster with the Kubernetes API.
-Prerequisite:
+Prerequisites:
- You have an agent configured with the `user_access` entry.
diff --git a/doc/user/clusters/agent/work_with_agent.md b/doc/user/clusters/agent/work_with_agent.md
index 70abbebaaad..490e502cf2e 100644
--- a/doc/user/clusters/agent/work_with_agent.md
+++ b/doc/user/clusters/agent/work_with_agent.md
@@ -12,7 +12,7 @@ Use the following tasks when you work with the agent for Kubernetes.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340882) in GitLab 14.8, the installed `agentk` version is displayed on the **Agent** tab.
-Prerequisite:
+Prerequisites:
- You must have at least the Developer role.
diff --git a/doc/user/custom_roles.md b/doc/user/custom_roles.md
index bbb48724078..e0759f7dc9e 100644
--- a/doc/user/custom_roles.md
+++ b/doc/user/custom_roles.md
@@ -50,7 +50,7 @@ with the ability to:
### GitLab SaaS
-Prerequisite:
+Prerequisites:
- You must have the Owner role in the group you are creating the custom role in.
@@ -64,7 +64,7 @@ Prerequisite:
### Self Managed GitLab Instances
-Prerequisite:
+Prerequisites:
- You must be an administrator for the self-managed instance you are creating the custom role in.
@@ -95,7 +95,7 @@ These requirements are documented in the `Required permission` column in the fol
| `read_vulnerability` | GitLab 16.1 and later | Not applicable | View [vulnerability reports](application_security/vulnerability_report/index.md). |
| `admin_vulnerability` | GitLab 16.1 and later | `read_vulnerability` | Change the [status of vulnerabilities](application_security/vulnerabilities/index.md#vulnerability-status-values). |
| `read_dependency` | GitLab 16.3 and later | Not applicable | View [project dependencies](application_security/dependency_list/index.md). |
-| `admin_merge_request` | GitLab 16.4 and later | Not applicable | View and approve [merge requests](project/merge_requests/index.md), and view the associated merge request code. <br> Does not allow users to view or change merge request approval rules. |
+| `admin_merge_request` | GitLab 16.4 and later | Not applicable | View and approve [merge requests](project/merge_requests/index.md), revoke merge request approval, and view the associated merge request code. <br> Does not allow users to view or change merge request approval rules. |
| `manage_project_access_tokens` | GitLab 16.5 and later | Not applicable | Create, delete, and list [project access tokens](project/settings/project_access_tokens.md). |
| `admin_group_member` | GitLab 16.5 and later | Not applicable | Add or remove [group members](group/manage.md). |
| `archive_project` | GitLab 16.6 and later | Not applicable | Archive and unarchive [projects](project/settings/index.md#archive-a-project). |
@@ -143,7 +143,7 @@ the Owner role:
## Remove a custom role
-Prerequisite:
+Prerequisites:
- You must be an administrator or have the Owner role in the group you are removing the custom role from.
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index a3ed888ed53..4ccd710dd81 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -149,7 +149,7 @@ If you edit an existing comment to add a user mention that wasn't there before,
You can prevent public comments in an issue or merge request.
When you do, only project members can add and edit comments.
-Prerequisite:
+Prerequisites:
- In merge requests, you must have at least the Developer role.
- In issues, you must have at least the Reporter role.
diff --git a/doc/user/free_user_limit.md b/doc/user/free_user_limit.md
index c978105c13b..091b97cc0e5 100644
--- a/doc/user/free_user_limit.md
+++ b/doc/user/free_user_limit.md
@@ -21,7 +21,7 @@ To help manage your free user limit,
you can view and manage the total number of members across all projects and groups
in your namespace.
-Prerequisite:
+Prerequisites:
- You must have the Owner role for the group.
diff --git a/doc/user/group/compliance_frameworks.md b/doc/user/group/compliance_frameworks.md
index 7258791a983..863cc52fc65 100644
--- a/doc/user/group/compliance_frameworks.md
+++ b/doc/user/group/compliance_frameworks.md
@@ -25,7 +25,7 @@ or deleted at the subgroup or project level. Project owners can choose a framewo
## Add a compliance framework to a project
-Prerequisite:
+Prerequisites:
- The group to which the project belongs must have a compliance framework.
diff --git a/doc/user/group/custom_project_templates.md b/doc/user/group/custom_project_templates.md
index 967ba4e05d0..4879d14eeb5 100644
--- a/doc/user/group/custom_project_templates.md
+++ b/doc/user/group/custom_project_templates.md
@@ -21,7 +21,7 @@ You can also configure [custom templates for the instance](../../administration/
## Set up group-level project templates
-Prerequisite:
+Prerequisites:
- You must have the Owner role for the group.
diff --git a/doc/user/group/devops_adoption/index.md b/doc/user/group/devops_adoption/index.md
index 5359d7b52a0..79d4f24e621 100644
--- a/doc/user/group/devops_adoption/index.md
+++ b/doc/user/group/devops_adoption/index.md
@@ -30,7 +30,7 @@ how to use those features.
## View DevOps Adoption
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role for the group.
diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md
index ae86ce30399..3367c364676 100644
--- a/doc/user/group/import/index.md
+++ b/doc/user/group/import/index.md
@@ -615,7 +615,7 @@ sure these users exist before importing the desired groups.
### Enable export for a group
-Prerequisite:
+Prerequisites:
- You must have the Owner role for the group.
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 1a4fa9df305..f232ca17768 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -255,7 +255,7 @@ You can sort members by **Account**, **Access granted**, **Max role**, or **Last
You can give a user access to all projects in a group.
-Prerequisite:
+Prerequisites:
- You must have the Owner role.
diff --git a/doc/user/group/manage.md b/doc/user/group/manage.md
index 48f86ee4f0e..2ccb42b93eb 100644
--- a/doc/user/group/manage.md
+++ b/doc/user/group/manage.md
@@ -23,7 +23,7 @@ A single top-level group provides insights in your entire organization via a com
As a group owner or member, you can use a README to provide more information about your team, and invite users to contribute to your projects.
The README is displayed on the group overview page, and can be changed in the group settings. All group members can edit the README.
-Prerequisite:
+Prerequisites:
- To create the README from the group settings, you must have the Owner role for the group.
@@ -254,7 +254,7 @@ disabled for the group and its subgroups.
### Specify a user cap for a group
-Prerequisite:
+Prerequisites:
- You must be assigned the Owner role for the group.
@@ -276,7 +276,7 @@ Increasing the user cap does not approve pending members.
You can remove the user cap, so there is no limit on the number of members you can add to a group.
-Prerequisite:
+Prerequisites:
- You must be assigned the Owner role for the group.
@@ -297,9 +297,9 @@ and must be approved.
Pending members do not count as billable. Members count as billable only after they have been approved and are no longer in a pending state.
-Prerequisite:
+Prerequisites:
-- You must be assigned the Owner role) for the group.
+- You must be assigned the Owner role for the group.
To approve members that are pending because they've exceeded the user cap:
@@ -390,7 +390,7 @@ You can configure [skipped pipelines](../../ci/pipelines/index.md#skip-a-pipelin
See also [the project-level setting](../project/merge_requests/merge_when_pipeline_succeeds.md#allow-merge-after-skipped-pipelines).
-Prerequisite:
+Prerequisites:
- You must be the owner of the group.
@@ -409,7 +409,7 @@ To change this behavior:
You can prevent merge requests from being merged until all threads are resolved. When this setting is enabled, for all child projects in your group, the
**Unresolved threads** count in a merge request is shown in orange when at least one thread remains unresolved.
-Prerequisite:
+Prerequisites:
- You must be the owner of the group.
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index e9064ff72a6..004a074cca9 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -49,7 +49,7 @@ graph TD
## View subgroups of a group
-Prerequisite:
+Prerequisites:
- To view private nested subgroups, you must be a direct or inherited member of
the private subgroup.
@@ -92,7 +92,7 @@ To create a subgroup:
### Change who can create subgroups
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role on the group, depending on the group's setting.
diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md
index 2ed01a0ec05..5ce6bb5dbac 100644
--- a/doc/user/group/value_stream_analytics/index.md
+++ b/doc/user/group/value_stream_analytics/index.md
@@ -302,7 +302,7 @@ In GitLab 13.8 and earlier, deployment frequency metrics are calculated based on
## View lifecycle and DORA metrics
-Prerequisite:
+Prerequisites:
- To view deployment metrics, you must have a
[production environment configured](#how-value-stream-analytics-identifies-the-production-environment).
diff --git a/doc/user/okrs.md b/doc/user/okrs.md
index 3dadc406de2..bc8ad5653d9 100644
--- a/doc/user/okrs.md
+++ b/doc/user/okrs.md
@@ -399,7 +399,7 @@ To turn off a check-in reminder, enter:
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/11198) in GitLab 16.6.
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role for the project.
- The parent objective and child OKR must belong to the same project.
@@ -518,7 +518,7 @@ The relationship only shows up in the UI if the user can see both items.
### Add a linked item
-Prerequisite:
+Prerequisites:
- You must have at least the Guest role for the project.
@@ -540,7 +540,7 @@ them categorized so their relationships can be better understood visually.
### Remove a linked item
-Prerequisite:
+Prerequisites:
- You must have at least the Guest role for the project.
diff --git a/doc/user/packages/nuget_repository/index.md b/doc/user/packages/nuget_repository/index.md
index a12f489d6fe..6f503f3c30b 100644
--- a/doc/user/packages/nuget_repository/index.md
+++ b/doc/user/packages/nuget_repository/index.md
@@ -300,7 +300,7 @@ To use the [project-level](#use-the-gitlab-endpoint-for-nuget-packages) package
## Publish a NuGet package
-Prerequisite:
+Prerequisites:
- Set up the [source](#add-the-package-registry-as-a-source-for-nuget-packages) with a [project-level endpoint](#use-the-gitlab-endpoint-for-nuget-packages).
@@ -406,7 +406,7 @@ updated:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416404) in GitLab 16.2.
-Prerequisite:
+Prerequisites:
- The project-level package registry is a source for Chocolatey.
diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md
index 3934122ffed..96d8220ef85 100644
--- a/doc/user/packages/package_registry/index.md
+++ b/doc/user/packages/package_registry/index.md
@@ -168,7 +168,7 @@ Anyone on the internet can access the package registry for the project.
#### Disable allowing anyone to pull
-Prerequisite:
+Prerequisites:
- You must be an administrator.
diff --git a/doc/user/packages/workflows/build_packages.md b/doc/user/packages/workflows/build_packages.md
index fa72520dff2..6b676a9e718 100644
--- a/doc/user/packages/workflows/build_packages.md
+++ b/doc/user/packages/workflows/build_packages.md
@@ -51,7 +51,7 @@ Learn how to install and build packages different package formats.
### Install Conan
-Prerequisite:
+Prerequisites:
- You must install Conan version 1.x. Support for Conan version 2 is proposed in [epic 8258](https://gitlab.com/groups/gitlab-org/-/epics/8258).
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 0ca54de71f6..38854d3daef 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -110,7 +110,7 @@ The following table lists project permissions available for each role:
| [Issues](project/issues/index.md):<br>View [confidential issues](project/issues/confidential_issues.md) | (2) | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Close / reopen (18) | | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Lock threads | | ✓ | ✓ | ✓ | ✓ |
-| [Issues](project/issues/index.md):<br>Manage [related issues](project/issues/related_issues.md) | ✓ | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Manage [related issues](project/issues/related_issues.md) | | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Manage tracker | | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Move issues (14) | | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Set issue [time tracking](project/time_tracking.md) estimate and time spent | | ✓ | ✓ | ✓ | ✓ |
diff --git a/doc/user/product_analytics/index.md b/doc/user/product_analytics/index.md
index eb2e100c954..245ffc34783 100644
--- a/doc/user/product_analytics/index.md
+++ b/doc/user/product_analytics/index.md
@@ -74,7 +74,7 @@ This feature is not ready for production use.
To track events in your project applications on a self-managed instance,
you must enable and configure product analytics.
-Prerequisite:
+Prerequisites:
- You must be an administrator of a self-managed GitLab instance.
diff --git a/doc/user/profile/account/create_accounts.md b/doc/user/profile/account/create_accounts.md
index 2166b40b575..cced4ae110a 100644
--- a/doc/user/profile/account/create_accounts.md
+++ b/doc/user/profile/account/create_accounts.md
@@ -16,7 +16,7 @@ You can create users:
## Create users on sign-in page
-Prerequisite:
+Prerequisites:
- [Sign-up must be enabled](../../admin_area/settings/sign_up_restrictions.md).
@@ -27,7 +27,7 @@ Users can create their own accounts by either:
## Create users in Admin Area
-Prerequisite:
+Prerequisites:
- You must have administrator access to the instance.
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index e3cd6f6f237..1cadb284058 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -152,7 +152,7 @@ Allowing personal access tokens for service accounts to be created with no expir
#### GitLab.com
-Prerequisite:
+Prerequisites:
- You must have the Owner role in the top-level group.
@@ -164,7 +164,7 @@ You can now create personal access tokens for a service account user with no exp
#### Self-managed GitLab
-Prerequisite:
+Prerequisites:
- You must be an administrator for your self-managed instance.
@@ -181,7 +181,7 @@ You can now create personal access tokens for a service account user with no exp
You can create a predetermined personal access token
as part of your tests or automation.
-Prerequisite:
+Prerequisites:
- You need sufficient access to run a
[Rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session)
@@ -221,7 +221,7 @@ sudo gitlab-rails runner "token = User.find_by_username('automation-bot').person
You can programmatically revoke a personal access token
as part of your tests or automation.
-Prerequisite:
+Prerequisites:
- You need sufficient access to run a [Rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session)
for your GitLab instance.
diff --git a/doc/user/profile/service_accounts.md b/doc/user/profile/service_accounts.md
index 8fa0067f150..6ca07056dfe 100644
--- a/doc/user/profile/service_accounts.md
+++ b/doc/user/profile/service_accounts.md
@@ -40,7 +40,7 @@ How you create an account differs depending on whether you are on GitLab.com or
### GitLab.com
-Prerequisite:
+Prerequisites:
- You must have the Owner role in a top-level group.
@@ -62,7 +62,7 @@ Prerequisite:
### Self-managed GitLab
-Prerequisite:
+Prerequisites:
- You must be an administrator for your self-managed instance.
diff --git a/doc/user/project/import/bitbucket_server.md b/doc/user/project/import/bitbucket_server.md
index 4afe23a29fa..476b7a4b55f 100644
--- a/doc/user/project/import/bitbucket_server.md
+++ b/doc/user/project/import/bitbucket_server.md
@@ -75,7 +75,7 @@ The following items are changed when they are imported:
## User assignment
-Prerequisite:
+Prerequisites:
- Authentication token with administrator access.
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index f9b94774809..5f724c83c49 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -111,7 +111,7 @@ If you are using a self-managed GitLab instance or if you are importing from Git
### Use a GitHub token
-Prerequisite:
+Prerequisites:
- Authentication token with administrator access.
diff --git a/doc/user/project/integrations/index.md b/doc/user/project/integrations/index.md
index 6abe3c5914e..4224d01c4c3 100644
--- a/doc/user/project/integrations/index.md
+++ b/doc/user/project/integrations/index.md
@@ -23,7 +23,7 @@ You can use:
## Manage group-level default settings for a project integration
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for the group.
@@ -64,7 +64,7 @@ is proposed in [epic 2137](https://gitlab.com/groups/gitlab-org/-/epics/2137).
### Remove a group-level default setting
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for the group.
@@ -79,7 +79,7 @@ Resetting a group-level default setting removes integrations that use default se
## Use instance-level or group-level default settings for a project integration
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for the project.
@@ -95,7 +95,7 @@ To use instance-level or group-level default settings for a project integration:
## Use custom settings for a project or group integration
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for the project or group.
diff --git a/doc/user/project/integrations/mattermost_slash_commands.md b/doc/user/project/integrations/mattermost_slash_commands.md
index 715e744988c..619d9a21e6d 100644
--- a/doc/user/project/integrations/mattermost_slash_commands.md
+++ b/doc/user/project/integrations/mattermost_slash_commands.md
@@ -109,7 +109,7 @@ Your slash command can now communicate with your GitLab project.
## Connect your GitLab account to Mattermost
-Prerequisite:
+Prerequisites:
- To run [slash commands](gitlab_slack_application.md#slash-commands), you must have
[permission](../../permissions.md#project-members-permissions) to
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index a162c2d1709..473273889c3 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -132,7 +132,7 @@ To move an issue:
You can move multiple issues at the same time when you're in a project.
You can't move tasks or test cases.
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role for the project.
diff --git a/doc/user/project/issues/related_issues.md b/doc/user/project/issues/related_issues.md
index 2f405aaa810..10c7899ac30 100644
--- a/doc/user/project/issues/related_issues.md
+++ b/doc/user/project/issues/related_issues.md
@@ -25,7 +25,7 @@ To manage linked issues through our API, see [Issue links API](../../../api/issu
Prerequisites:
-- You must have at least the Guest role for the source issue's project, and you must be able to access the target issue.
+- You must have at least the Reporter role for both projects.
To link one issue to another:
diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md
index a008bfdebae..0c191ca1b14 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -113,7 +113,7 @@ graph TD
Add users to a project so they become direct members and have permission
to perform actions.
-Prerequisite:
+Prerequisites:
- You must have the Owner or Maintainer role.
@@ -201,7 +201,7 @@ The **Members** tab shows:
You can import another project's members to your own project.
Imported project members retain the same permissions as the project you import them from.
-Prerequisite:
+Prerequisites:
- You must have the Maintainer or Owner role.
@@ -342,7 +342,7 @@ To withdraw the access request:
You can prevent users from requesting access to a project.
-Prerequisite:
+Prerequisites:
- You must be the project owner.
diff --git a/doc/user/project/merge_requests/approvals/settings.md b/doc/user/project/merge_requests/approvals/settings.md
index 3be546faabe..9a510ed1582 100644
--- a/doc/user/project/merge_requests/approvals/settings.md
+++ b/doc/user/project/merge_requests/approvals/settings.md
@@ -153,7 +153,7 @@ However, approvals are reset if the target branch is changed.
If you only want to remove approvals by Code Owners whose files have been changed when a commit is added:
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for a project.
diff --git a/doc/user/project/merge_requests/commit_templates.md b/doc/user/project/merge_requests/commit_templates.md
index 5ca097da29f..e133f2212a5 100644
--- a/doc/user/project/merge_requests/commit_templates.md
+++ b/doc/user/project/merge_requests/commit_templates.md
@@ -23,7 +23,7 @@ Commit templates use syntax similar to the syntax for
Change the commit templates for your project if the default templates don't
contain the information you need.
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for a project.
diff --git a/doc/user/project/merge_requests/dependencies.md b/doc/user/project/merge_requests/dependencies.md
index 8fb5230c497..c499550cc6b 100644
--- a/doc/user/project/merge_requests/dependencies.md
+++ b/doc/user/project/merge_requests/dependencies.md
@@ -99,7 +99,7 @@ To create a new merge request and mark it as dependent on another:
You can edit an existing merge request and mark it as dependent on another.
-Prerequisite:
+Prerequisites:
- You must have at least the Developer role or be allowed to edit merge requests in the project.
@@ -116,7 +116,7 @@ To do this:
You can edit a dependent merge request and remove a dependency.
-Prerequisite:
+Prerequisites:
- You must have a role in the project that allows you to edit merge requests.
diff --git a/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
index c4c38ef9eaf..1c287825fc1 100644
--- a/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
+++ b/doc/user/project/merge_requests/merge_when_pipeline_succeeds.md
@@ -110,7 +110,7 @@ When the **Pipelines must succeed** checkbox is checked,
[skipped pipelines](../../../ci/pipelines/index.md#skip-a-pipeline) prevent
merge requests from being merged.
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role in the project.
diff --git a/doc/user/project/protected_branches.md b/doc/user/project/protected_branches.md
index f8f44d344d1..f957a5ae2c0 100644
--- a/doc/user/project/protected_branches.md
+++ b/doc/user/project/protected_branches.md
@@ -128,7 +128,7 @@ specific branch is configured with **Allowed to force push** settings at both th
group and project levels, the **Allowed to force push** setting at the _project_ level
is ignored in favor of the group level setting.
-Prerequisite:
+Prerequisites:
- You must have the Owner role in the group.
@@ -153,7 +153,7 @@ If more than one rule applies to a branch, the _most permissive_ rule controls
how the branch behaves. For merge controls to work properly, set
**Allowed to push and merge** to a broader set of users than **Allowed to merge**.
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role.
diff --git a/doc/user/project/protected_tags.md b/doc/user/project/protected_tags.md
index b312acd49f4..9afd65450df 100644
--- a/doc/user/project/protected_tags.md
+++ b/doc/user/project/protected_tags.md
@@ -125,7 +125,7 @@ To allow a deploy key to create a protected tag:
You can manually delete protected tags with the GitLab API, or the
GitLab user interface.
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role in your project.
diff --git a/doc/user/project/repository/mirror/index.md b/doc/user/project/repository/mirror/index.md
index b16197e45b2..a8c9932041f 100644
--- a/doc/user/project/repository/mirror/index.md
+++ b/doc/user/project/repository/mirror/index.md
@@ -107,7 +107,7 @@ While mirrors are scheduled to update automatically, you can force an immediate
- The [interval, in seconds](../../../../administration/instance_limits.md#pull-mirroring-interval)
for pull mirroring limits has not elapsed after its last update.
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for the project.
diff --git a/doc/user/project/repository/push_rules.md b/doc/user/project/repository/push_rules.md
index a8b77dd0cfc..ab9039f6206 100644
--- a/doc/user/project/repository/push_rules.md
+++ b/doc/user/project/repository/push_rules.md
@@ -33,7 +33,7 @@ All projects created after you configure global push rules inherit this
configuration. However, each existing project must be updated manually, using the
process described in [Override global push rules per project](#override-global-push-rules-per-project).
-Prerequisite:
+Prerequisites:
- You must be an administrator.
diff --git a/doc/user/project/requirements/index.md b/doc/user/project/requirements/index.md
index d99729e3c1b..b730f6b4cd8 100644
--- a/doc/user/project/requirements/index.md
+++ b/doc/user/project/requirements/index.md
@@ -43,7 +43,7 @@ For a more in-depth walkthrough see [GitLab Requirements Traceability Walkthroug
A paginated list of requirements is available in each project, and there you
can create a new requirement.
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role.
@@ -73,7 +73,7 @@ next to the requirement title.
You can edit a requirement from the requirements list page.
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role.
@@ -89,7 +89,7 @@ To edit a requirement:
You can archive an open requirement while
you're in the **Open** tab.
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role.
@@ -101,7 +101,7 @@ As soon as a requirement is archived, it no longer appears in the **Open** tab.
You can view the list of archived requirements in the **Archived** tab.
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role.
@@ -294,7 +294,7 @@ By exporting requirements, you and your team can import them into another tool o
your customers. Exporting requirements can aid collaboration with higher-level systems, as well as
audit and regulatory compliance tasks.
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role.
diff --git a/doc/user/project/service_desk/configure.md b/doc/user/project/service_desk/configure.md
index 8d0fbd81ebd..06f0854953d 100644
--- a/doc/user/project/service_desk/configure.md
+++ b/doc/user/project/service_desk/configure.md
@@ -120,7 +120,7 @@ You can set description templates at various levels:
The templates are inherited. For example, in a project, you can also access templates set for the instance, or the project's parent groups.
-Prerequisite:
+Prerequisites:
- You must have [created a description template](../description_templates.md#create-an-issue-template).
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index b67032767ee..f45b3289094 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -11,7 +11,7 @@ Use the **Settings** page to manage the configuration options in your [project](
## View project settings
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for the project.
@@ -42,7 +42,7 @@ The assigned topics are visible only to users with access to the project, but ev
A project's repository name defines its URL and its place on the file disk
where GitLab is installed.
-Prerequisite:
+Prerequisites:
- You must be an administrator or have the Maintainer or Owner role for the project.
@@ -187,7 +187,7 @@ To archive a project:
When you unarchive a project, the read-only restriction is removed,
and the project becomes available in project lists.
-Prerequisite:
+Prerequisites:
- You must be an administrator or have the Owner role for the project.
@@ -244,7 +244,7 @@ To disable the CVE identifier request option in issues in your project:
## Disable project email notifications
-Prerequisite:
+Prerequisites:
- You must have the Owner role for the project.
diff --git a/doc/user/project/working_with_projects.md b/doc/user/project/working_with_projects.md
index c838cc98e89..aa82ab24e69 100644
--- a/doc/user/project/working_with_projects.md
+++ b/doc/user/project/working_with_projects.md
@@ -54,7 +54,7 @@ To view projects you have [starred](#star-a-project):
Use the project general settings to edit your project details.
-Prerequisite:
+Prerequisites:
- You must have at least the Maintainer role for the project.
@@ -162,7 +162,7 @@ After you delete a project:
- Projects in personal namespaces are deleted immediately.
- Projects in groups are deleted after a retention period.
-Prerequisite:
+Prerequisites:
- You must have the Owner role for a project.
@@ -184,7 +184,7 @@ You can also [delete projects using the Rails console](#delete-a-project-using-c
> - [Disabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95495) in GitLab 15.3.
> - Enabled delayed deletion by default and removed the option to delete immediately [on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/393622) and [on self-managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119606) in GitLab 16.0.
-Prerequisite:
+Prerequisites:
- You must have the Owner role for the project.
@@ -295,7 +295,7 @@ A list of projects that use the selected language is displayed.
You can change the visibility of individual features in a project.
-Prerequisite:
+Prerequisites:
- You must have the Owner role for the project.
diff --git a/doc/user/public_access.md b/doc/user/public_access.md
index 37b79c8f1a8..d9c0dbe2139 100644
--- a/doc/user/public_access.md
+++ b/doc/user/public_access.md
@@ -63,7 +63,7 @@ then `/public` is visible only to authenticated users.
You can change the visibility of a project.
-Prerequisite:
+Prerequisites:
- You must have the Owner role for a project.
diff --git a/doc/user/tasks.md b/doc/user/tasks.md
index 173d2e44cf1..29461e58500 100644
--- a/doc/user/tasks.md
+++ b/doc/user/tasks.md
@@ -364,7 +364,7 @@ To copy the task's email address:
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/11198) in GitLab 16.5.
-Prerequisite:
+Prerequisites:
- You must have at least the Reporter role for the project.
- The issue and task must belong to the same project.
@@ -479,7 +479,7 @@ The relationship only shows up in the UI if the user can see both items.
### Add a linked item
-Prerequisite:
+Prerequisites:
- You must have at least the Guest role for the project.
@@ -501,7 +501,7 @@ them categorized so their relationships can be better understood visually.
### Remove a linked item
-Prerequisite:
+Prerequisites:
- You must have at least the Guest role for the project.
diff --git a/doc/user/workspace/configuration.md b/doc/user/workspace/configuration.md
index 3684845c2c7..03108701a04 100644
--- a/doc/user/workspace/configuration.md
+++ b/doc/user/workspace/configuration.md
@@ -101,7 +101,7 @@ When you connect to `gitlab-workspaces-proxy` through the TCP load balancer,
### Set up `gitlab-workspaces-proxy` for SSH connections
-Prerequisite:
+Prerequisites:
- You must have an SSH host key for client verification.
diff --git a/lib/feature.rb b/lib/feature.rb
index 7df692ec552..d6f34cf195f 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -33,14 +33,19 @@ module Feature
# Generates the same flipper_id when in a request
# If not in a request, it generates a unique flipper_id every time
class FlipperRequest
- def id
+ def flipper_id
Gitlab::SafeRequestStore.fetch("flipper_request_id") do
- SecureRandom.uuid
+ "FlipperRequest:#{SecureRandom.uuid}".freeze
end
end
+ end
- def flipper_id
- "FlipperRequest:#{id}"
+ # Generates a unique flipper_id for the current GitLab instance.
+ class FlipperGitlabInstance
+ attr_reader :flipper_id
+
+ def initialize
+ @flipper_id = "FlipperGitlabInstance:#{::Gitlab.config.gitlab.host}".freeze
end
end
@@ -89,14 +94,9 @@ module Feature
# 2. The `default_enabled_if_undefined:` is tech debt related to Gitaly flags
# and should not be used outside of Gitaly's `lib/feature/gitaly.rb`
def enabled?(key, thing = nil, type: :development, default_enabled_if_undefined: nil)
- if check_feature_flags_definition?
- if thing && !thing.respond_to?(:flipper_id) && !thing.is_a?(Flipper::Types::Group)
- raise InvalidFeatureFlagError,
- "The thing '#{thing.class.name}' for feature flag '#{key}' needs to include `FeatureGate` or implement `flipper_id`"
- end
+ thing = sanitized_thing(thing)
- Feature::Definition.valid_usage!(key, type: type)
- end
+ check_feature_flags_definition!(key, thing, type)
default_enabled = Feature::Definition.default_enabled?(key, default_enabled_if_undefined: default_enabled_if_undefined)
feature_value = current_feature_value(key, thing, default_enabled: default_enabled)
@@ -111,11 +111,15 @@ module Feature
end
def disabled?(key, thing = nil, type: :development, default_enabled_if_undefined: nil)
+ thing = sanitized_thing(thing)
+
# we need to make different method calls to make it easy to mock / define expectations in test mode
thing.nil? ? !enabled?(key, type: type, default_enabled_if_undefined: default_enabled_if_undefined) : !enabled?(key, thing, type: type, default_enabled_if_undefined: default_enabled_if_undefined)
end
def enable(key, thing = true)
+ thing = sanitized_thing(thing)
+
log(key: key, action: __method__, thing: thing)
return_value = with_feature(key) { _1.enable(thing) }
@@ -129,12 +133,16 @@ module Feature
end
def disable(key, thing = false)
+ thing = sanitized_thing(thing)
+
log(key: key, action: __method__, thing: thing)
with_feature(key) { _1.disable(thing) }
end
def opted_out?(key, thing)
+ thing = sanitized_thing(thing)
+
return false unless thing.respond_to?(:flipper_id) # Ignore Feature::Types::Group
return false unless persisted_name?(key)
@@ -144,6 +152,8 @@ module Feature
end
def opt_out(key, thing)
+ thing = sanitized_thing(thing)
+
return unless thing.respond_to?(:flipper_id) # Ignore Feature::Types::Group
log(key: key, action: __method__, thing: thing)
@@ -153,6 +163,8 @@ module Feature
end
def remove_opt_out(key, thing)
+ thing = sanitized_thing(thing)
+
return unless thing.respond_to?(:flipper_id) # Ignore Feature::Types::Group
return unless persisted_name?(key)
@@ -228,6 +240,10 @@ module Feature
end
end
+ def gitlab_instance
+ @flipper_gitlab_instance ||= FlipperGitlabInstance.new
+ end
+
def logger
@logger ||= Feature::Logger.build
end
@@ -246,6 +262,17 @@ module Feature
private
+ def sanitized_thing(thing)
+ case thing
+ when :instance
+ gitlab_instance
+ when :request, :current_request
+ current_request
+ else
+ thing
+ end
+ end
+
# Compute if thing is enabled, taking opt-out overrides into account
# Evaluate if `default enabled: false` or the feature has been persisted.
# `persisted_name?` can potentially generate DB queries and also checks for inclusion
@@ -343,6 +370,17 @@ module Feature
Gitlab.dev_or_test_env?
end
+ def check_feature_flags_definition!(key, thing, type)
+ return unless check_feature_flags_definition?
+
+ if thing && !thing.respond_to?(:flipper_id) && !thing.is_a?(Flipper::Types::Group)
+ raise InvalidFeatureFlagError,
+ "The thing '#{thing.class.name}' for feature flag '#{key}' needs to include `FeatureGate` or implement `flipper_id`"
+ end
+
+ Feature::Definition.valid_usage!(key, type: type)
+ end
+
def l1_cache_backend
Gitlab::ProcessMemoryCache.cache_backend
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 670aee863a2..89c8453e677 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -14055,9 +14055,6 @@ msgstr ""
msgid "Couldn't link epics. You must have at least the Guest role in the epic's group."
msgstr ""
-msgid "Couldn't link issues. You must have at least the Guest role in the source issue's project."
-msgstr ""
-
msgid "Country / Region"
msgstr ""
diff --git a/spec/features/issues/related_issues_spec.rb b/spec/features/issues/related_issues_spec.rb
index b2bb2d1dd6e..f460b4b1c7f 100644
--- a/spec/features/issues/related_issues_spec.rb
+++ b/spec/features/issues/related_issues_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Related issues', :js, feature_category: :team_planning do
let_it_be(:project) { create(:project_empty_repo, :public) }
let_it_be(:project_b) { create(:project_empty_repo, :public) }
- let_it_be(:project_unauthorized) { create(:project_empty_repo) }
+ let_it_be(:project_unauthorized) { create(:project_empty_repo, :public) }
let_it_be(:internal_project) { create(:project_empty_repo, :internal) }
let_it_be(:private_project) { create(:project_empty_repo, :private) }
let_it_be(:public_project) { create(:project_empty_repo, :public) }
@@ -90,7 +90,7 @@ RSpec.describe 'Related issues', :js, feature_category: :team_planning do
visit project_issue_path(internal_project, internal_issue)
expect(page).to have_css('.related-issues-block')
- expect(page).to have_button 'Add a related issue'
+ expect(page).not_to have_button 'Add a related issue'
end
it 'shows widget when private project' do
@@ -99,7 +99,7 @@ RSpec.describe 'Related issues', :js, feature_category: :team_planning do
visit project_issue_path(private_project, private_issue)
expect(page).to have_css('.related-issues-block')
- expect(page).to have_button 'Add a related issue'
+ expect(page).not_to have_button 'Add a related issue'
end
it 'shows widget when public project' do
@@ -108,12 +108,45 @@ RSpec.describe 'Related issues', :js, feature_category: :team_planning do
visit project_issue_path(public_project, public_issue)
expect(page).to have_css('.related-issues-block')
+ expect(page).not_to have_button 'Add a related issue'
+ end
+ end
+
+ context 'when logged in and a reporter' do
+ before do
+ sign_in(user)
+ end
+
+ it 'shows widget when internal project' do
+ internal_project.add_reporter(user)
+
+ visit project_issue_path(internal_project, internal_issue)
+
+ expect(page).to have_css('.related-issues-block')
+ expect(page).to have_button 'Add a related issue'
+ end
+
+ it 'shows widget when private project' do
+ private_project.add_reporter(user)
+
+ visit project_issue_path(private_project, private_issue)
+
+ expect(page).to have_css('.related-issues-block')
+ expect(page).to have_button 'Add a related issue'
+ end
+
+ it 'shows widget when public project' do
+ public_project.add_reporter(user)
+
+ visit project_issue_path(public_project, public_issue)
+
+ expect(page).to have_css('.related-issues-block')
expect(page).to have_button 'Add a related issue'
end
it 'shows widget on their own public issue' do
issue = create :issue, project: public_project, author: user
- public_project.add_guest(user)
+ public_project.add_reporter(user)
visit project_issue_path(public_project, issue)
diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb
index 7860d85457a..c7faf267348 100644
--- a/spec/lib/feature_spec.rb
+++ b/spec/lib/feature_spec.rb
@@ -43,6 +43,20 @@ RSpec.describe Feature, :clean_gitlab_redis_feature_flag, stub_feature_flags: fa
end
end
+ describe '.gitlab_instance' do
+ it 'returns a FlipperGitlabInstance with a flipper_id' do
+ flipper_request = described_class.gitlab_instance
+
+ expect(flipper_request.flipper_id).to include("FlipperGitlabInstance:")
+ end
+
+ it 'caches flipper_id' do
+ previous_id = described_class.gitlab_instance.flipper_id
+
+ expect(described_class.gitlab_instance.flipper_id).to eq(previous_id)
+ end
+ end
+
describe '.get' do
let(:feature) { double(:feature) }
let(:key) { 'my_feature' }
@@ -331,36 +345,54 @@ RSpec.describe Feature, :clean_gitlab_redis_feature_flag, stub_feature_flags: fa
end
end
- context 'with current_request actor' do
- context 'when request store is inactive' do
- it 'returns the approximate percentage set' do
- number_of_times = 1_000
- percentage = 50
- described_class.enable_percentage_of_actors(:enabled_feature_flag, percentage)
+ [:current_request, :request, described_class.current_request].each do |thing|
+ context "with #{thing} actor" do
+ context 'when request store is inactive' do
+ it 'returns the approximate percentage set' do
+ number_of_times = 1_000
+ percentage = 50
+ described_class.enable_percentage_of_actors(:enabled_feature_flag, percentage)
- gate_values = Array.new(number_of_times) do
- described_class.enabled?(:enabled_feature_flag, described_class.current_request)
- end
+ gate_values = Array.new(number_of_times) do
+ described_class.enabled?(:enabled_feature_flag, thing)
+ end
- margin_of_error = 0.05 * number_of_times
- expected_size = number_of_times * percentage / 100
- expect(gate_values.count { |v| v }).to be_within(margin_of_error).of(expected_size)
+ margin_of_error = 0.05 * number_of_times
+ expected_size = number_of_times * percentage / 100
+ expect(gate_values.count { |v| v }).to be_within(margin_of_error).of(expected_size)
+ end
end
- end
- context 'when request store is active', :request_store do
- it 'always returns the same gate value' do
- described_class.enable_percentage_of_actors(:enabled_feature_flag, 50)
+ context 'when request store is active', :request_store do
+ it 'always returns the same gate value' do
+ described_class.enable_percentage_of_actors(:enabled_feature_flag, 50)
- previous_gate_value = described_class.enabled?(:enabled_feature_flag, described_class.current_request)
+ previous_gate_value = described_class.enabled?(:enabled_feature_flag, thing)
- 1_000.times do
- expect(described_class.enabled?(:enabled_feature_flag, described_class.current_request)).to eq(previous_gate_value)
+ 1_000.times do
+ expect(described_class.enabled?(:enabled_feature_flag, thing)).to eq(previous_gate_value)
+ end
end
end
end
end
+ context 'with gitlab_instance actor' do
+ it 'always returns the same gate value' do
+ described_class.enable(:enabled_feature_flag, described_class.gitlab_instance)
+
+ expect(described_class.enabled?(:enabled_feature_flag, described_class.gitlab_instance)).to be_truthy
+ end
+ end
+
+ context 'with :instance actor' do
+ it 'always returns the same gate value' do
+ described_class.enable(:enabled_feature_flag, :instance)
+
+ expect(described_class.enabled?(:enabled_feature_flag, :instance)).to be_truthy
+ end
+ end
+
context 'with a group member' do
let(:key) { :awesome_feature }
let(:guinea_pigs) { create_list(:user, 3) }
diff --git a/spec/models/pages_deployment_spec.rb b/spec/models/pages_deployment_spec.rb
index 1e6f8b33a86..fdd320f13ad 100644
--- a/spec/models/pages_deployment_spec.rb
+++ b/spec/models/pages_deployment_spec.rb
@@ -71,6 +71,16 @@ RSpec.describe PagesDeployment, feature_category: :pages do
end
end
+ describe '#upload_ready' do
+ it 'marks #upload_ready as true when upload finishes' do
+ deployment = build(:pages_deployment)
+
+ expect { deployment.save! }
+ .to change { deployment.upload_ready }
+ .from(false).to(true)
+ end
+ end
+
describe '.deactivate_all', :freeze_time do
let!(:deployment) { create(:pages_deployment, project: project, updated_at: 5.minutes.ago) }
let!(:nil_path_prefix_deployment) { create(:pages_deployment, project: project, path_prefix: nil) }
diff --git a/spec/policies/issue_policy_spec.rb b/spec/policies/issue_policy_spec.rb
index fb7a056ee48..c19b7bcf9ea 100644
--- a/spec/policies/issue_policy_spec.rb
+++ b/spec/policies/issue_policy_spec.rb
@@ -91,7 +91,7 @@ RSpec.describe IssuePolicy, feature_category: :team_planning do
end
it 'allows guests to read issues' do
- expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid, :admin_issue_relation, :admin_issue_link, :create_issue_link)
+ expect(permissions(guest, issue)).to be_allowed(:read_issue, :read_issue_iid, :admin_issue_relation)
expect(permissions(guest, issue)).to be_disallowed(:update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :mark_note_as_internal)
expect(permissions(guest, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :admin_issue_relation)
@@ -146,27 +146,13 @@ RSpec.describe IssuePolicy, feature_category: :team_planning do
let(:confidential_issue_no_assignee) { create(:issue, :confidential, project: project) }
it 'does not allow non-members to read confidential issues' do
- expect(permissions(non_member, confidential_issue)).to be_disallowed(
- :read_issue, :read_issue_iid, :update_issue, :admin_issue,
- :admin_issue_relation, :admin_issue_link, :create_issue_link
- )
- expect(permissions(non_member, confidential_issue_no_assignee)).to be_disallowed(
- :read_issue, :read_issue_iid, :update_issue, :admin_issue,
- :set_issue_metadata, :set_confidentiality, :admin_issue_relation,
- :admin_issue_link, :create_issue_link
- )
+ expect(permissions(non_member, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :admin_issue_relation)
+ expect(permissions(non_member, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation)
end
it 'does not allow guests to read confidential issues' do
- expect(permissions(guest, confidential_issue)).to be_disallowed(
- :read_issue, :read_issue_iid, :update_issue, :admin_issue,
- :admin_issue_relation, :admin_issue_link, :create_issue_link
- )
- expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(
- :read_issue, :read_issue_iid, :update_issue, :admin_issue,
- :set_issue_metadata, :set_confidentiality, :admin_issue_relation,
- :admin_issue_link, :create_issue_link
- )
+ expect(permissions(guest, confidential_issue)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :admin_issue_relation)
+ expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality, :admin_issue_relation)
end
it 'allows reporters to read, update, and admin confidential issues' do
@@ -226,23 +212,14 @@ RSpec.describe IssuePolicy, feature_category: :team_planning do
create(:project_group_link, group: group, project: project)
end
- it 'does not allow anonymous user to create todos' do
- expect(permissions(nil, issue)).to be_allowed(:read_issue)
- expect(permissions(nil, issue)).to be_disallowed(:create_todo, :update_subscription, :set_issue_metadata, :set_confidentiality, :admin_issue_relation)
- expect(permissions(nil, new_issue)).to be_disallowed(:create_issue, :set_issue_metadata, :set_confidentiality)
- end
-
- it 'does not allow anonymous user to create issue links' do
- expect(permissions(nil, issue)).to be_disallowed(:create_issue_link)
- end
-
it 'allows guests to award emoji' do
expect(permissions(guest, issue)).to be_allowed(:award_emoji)
- expect(permissions(guest, issue_no_assignee)).to be_allowed(:award_emoji)
end
- it 'allows guests to create and admin issue links' do
- expect(permissions(guest, issue)).to be_allowed(:create_issue_link, :admin_issue_link)
+ it 'does not allow anonymous user to create todos' do
+ expect(permissions(nil, issue)).to be_allowed(:read_issue)
+ expect(permissions(nil, issue)).to be_disallowed(:create_todo, :update_subscription, :set_issue_metadata, :set_confidentiality, :admin_issue_relation)
+ expect(permissions(nil, new_issue)).to be_disallowed(:create_issue, :set_issue_metadata, :set_confidentiality)
end
it 'allows guests to read issues' do
@@ -319,14 +296,6 @@ RSpec.describe IssuePolicy, feature_category: :team_planning do
expect(permissions(non_member, new_issue)).to be_allowed(:set_confidentiality)
end
- it 'allows non-members to create issue links' do
- expect(permissions(non_member, issue)).to be_allowed(:create_issue_link)
- end
-
- it 'does not allow non-members to admin issue links' do
- expect(permissions(non_member, issue)).to be_disallowed(:admin_issue_link)
- end
-
it 'allows support_bot to read issues' do
# support_bot is still allowed read access in public projects through :public_access permission,
# see project_policy public_access rules policy (rule { can?(:public_access) }.policy {...})
@@ -418,10 +387,6 @@ RSpec.describe IssuePolicy, feature_category: :team_planning do
expect(permissions(guest, confidential_issue_no_assignee)).to be_disallowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality)
end
- it 'does not allow guests to create or admin issue links' do
- expect(permissions(guest, confidential_issue)).to be_disallowed(:create_issue_link, :admin_issue_link)
- end
-
it 'allows reporters to read, update, and admin confidential issues' do
expect(permissions(reporter, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :admin_issue_relation)
expect(permissions(reporter, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality)
@@ -432,10 +397,6 @@ RSpec.describe IssuePolicy, feature_category: :team_planning do
expect(permissions(reporter_from_group_link, confidential_issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality)
end
- it 'allows reporters to create and admin issue links' do
- expect(permissions(reporter, confidential_issue)).to be_allowed(:create_issue_link, :admin_issue_link)
- end
-
it 'allows issue authors to read and update their confidential issues' do
expect(permissions(author, confidential_issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue_relation)
expect(permissions(author, confidential_issue)).to be_disallowed(:admin_issue, :set_issue_metadata, :set_confidentiality)
diff --git a/spec/requests/api/issue_links_spec.rb b/spec/requests/api/issue_links_spec.rb
index f06b3168b67..fcb199a91a4 100644
--- a/spec/requests/api/issue_links_spec.rb
+++ b/spec/requests/api/issue_links_spec.rb
@@ -86,16 +86,17 @@ RSpec.describe API::IssueLinks, feature_category: :team_planning do
end
end
- context 'when user does not have access to given issue' do
+ context 'when user does not have write access to given issue' do
it 'returns 403' do
unauthorized_project = create(:project)
target_issue = create(:issue, project: unauthorized_project)
+ unauthorized_project.add_guest(user)
post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
params: { target_project_id: unauthorized_project.id, target_issue_iid: target_issue.iid }
- expect(response).to have_gitlab_http_status(:not_found)
- expect(json_response['message']).to eq("404 Project Not Found")
+ expect(response).to have_gitlab_http_status(:forbidden)
+ expect(json_response['message']).to eq("Couldn't link issue. You must have at least the Reporter role in both projects.")
end
end
@@ -272,11 +273,12 @@ RSpec.describe API::IssueLinks, feature_category: :team_planning do
unauthorized_project = create(:project)
target_issue = create(:issue, project: unauthorized_project)
issue_link = create(:issue_link, source: issue, target: target_issue)
+ unauthorized_project.add_guest(user)
delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}", user)
expect(response).to have_gitlab_http_status(:not_found)
- expect(json_response['message']).to eq('404 Project Not Found')
+ expect(json_response['message']).to eq('No Issue Link found')
end
end
diff --git a/spec/requests/projects/issue_links_controller_spec.rb b/spec/requests/projects/issue_links_controller_spec.rb
index bd53ef583a3..ea73b733285 100644
--- a/spec/requests/projects/issue_links_controller_spec.rb
+++ b/spec/requests/projects/issue_links_controller_spec.rb
@@ -44,15 +44,15 @@ RSpec.describe Projects::IssueLinksController, feature_category: :team_planning
let(:issue_b) { create :issue, project: project }
before do
+ project.add_role(user, user_role)
login_as user
end
context 'with success' do
- let(:user_role) { :guest }
+ let(:user_role) { :developer }
let(:issuable_references) { [issue_b.to_reference] }
it 'returns success JSON' do
- project.add_role(user, user_role)
post namespace_project_issue_links_path(issue_links_params(issuable_references: issuable_references))
list_service_response = IssueLinks::ListService.new(issue, user).execute
@@ -67,19 +67,18 @@ RSpec.describe Projects::IssueLinksController, feature_category: :team_planning
let(:user_role) { :guest }
let(:issuable_references) { [issue_b.to_reference] }
- it 'returns 404' do
+ it 'returns 403' do
post namespace_project_issue_links_path(issue_links_params(issuable_references: issuable_references))
- expect(response).to have_gitlab_http_status(:not_found)
+ expect(response).to have_gitlab_http_status(:forbidden)
end
end
context 'when failing service result' do
- let(:user_role) { :guest }
+ let(:user_role) { :developer }
let(:issuable_references) { ["##{non_existing_record_iid}"] }
it 'returns failure JSON' do
- project.add_role(user, user_role)
post namespace_project_issue_links_path(issue_links_params(issuable_references: issuable_references))
list_service_response = IssueLinks::ListService.new(issue, user).execute
@@ -95,30 +94,29 @@ RSpec.describe Projects::IssueLinksController, feature_category: :team_planning
let(:issue_link) { create :issue_link, source: issue, target: referenced_issue }
before do
- project.add_role(user, user_role) if defined?(user_role)
+ project.add_role(user, user_role)
login_as user
end
- subject(:delete_issue_link) { delete namespace_project_issue_link_path(issue_links_params(id: issue_link.id)) }
-
context 'when unauthorized' do
context 'when no authorization on current project' do
let(:referenced_issue) { create :issue, project: project }
+ let(:user_role) { :guest }
- it 'returns 404' do
- delete_issue_link
+ it 'returns 403' do
+ delete namespace_project_issue_link_path(issue_links_params(id: issue_link.id))
- expect(response).to have_gitlab_http_status(:not_found)
+ expect(response).to have_gitlab_http_status(:forbidden)
end
end
context 'when no authorization on the related issue project' do
# unauthorized project issue
let(:referenced_issue) { create :issue }
- let(:user_role) { :guest }
+ let(:user_role) { :developer }
it 'returns 404' do
- delete_issue_link
+ delete namespace_project_issue_link_path(issue_links_params(id: issue_link.id))
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -127,10 +125,10 @@ RSpec.describe Projects::IssueLinksController, feature_category: :team_planning
context 'when authorized' do
let(:referenced_issue) { create :issue, project: project }
- let(:user_role) { :guest }
+ let(:user_role) { :developer }
it 'returns success JSON' do
- delete_issue_link
+ delete namespace_project_issue_link_path(issue_links_params(id: issue_link.id))
list_service_response = IssueLinks::ListService.new(issue, user).execute
@@ -138,22 +136,26 @@ RSpec.describe Projects::IssueLinksController, feature_category: :team_planning
end
end
- context 'when none of issues of the link is not the issue requested in the path' do
+ context 'when non of issues of the link is not the issue requested in the path' do
let(:referenced_issue) { create(:issue, project: project) }
let(:another_issue) { create(:issue, project: project) }
let(:issue) { create(:issue, project: project) }
- let(:user_role) { :guest }
+ let(:user_role) { :developer }
let!(:issue_link) { create :issue_link, source: another_issue, target: referenced_issue }
+ subject do
+ delete namespace_project_issue_link_path(issue_links_params(id: issue_link.id))
+ end
+
it 'returns 404' do
- delete_issue_link
+ subject
expect(response).to have_gitlab_http_status(:not_found)
end
it 'does not delete the link' do
- expect { delete_issue_link }.not_to change { IssueLink.count }.from(1)
+ expect { subject }.not_to change { IssueLink.count }.from(1)
end
end
end
diff --git a/spec/services/issue_links/create_service_spec.rb b/spec/services/issue_links/create_service_spec.rb
index 6705383f735..71603da1c90 100644
--- a/spec/services/issue_links/create_service_spec.rb
+++ b/spec/services/issue_links/create_service_spec.rb
@@ -23,6 +23,7 @@ RSpec.describe IssueLinks::CreateService, feature_category: :team_planning do
before do
project.add_developer(user)
+ restricted_issuable.project.add_guest(user)
another_project.add_developer(user)
end
diff --git a/spec/services/issue_links/list_service_spec.rb b/spec/services/issue_links/list_service_spec.rb
index af78c95abc0..b5cc8c4dcdc 100644
--- a/spec/services/issue_links/list_service_spec.rb
+++ b/spec/services/issue_links/list_service_spec.rb
@@ -6,10 +6,10 @@ RSpec.describe IssueLinks::ListService, feature_category: :team_planning do
let(:user) { create :user }
let(:project) { create(:project_empty_repo, :private) }
let(:issue) { create :issue, project: project }
- let(:user_role) { :guest }
+ let(:user_role) { :developer }
before do
- project.add_role(user, user_role) if user_role
+ project.add_role(user, user_role)
end
describe '#execute' do
@@ -161,23 +161,26 @@ RSpec.describe IssueLinks::ListService, feature_category: :team_planning do
end
context 'user can admin related issues just on target project' do
- let(:user_role) { nil }
+ let(:user_role) { :guest }
let(:target_project) { create :project }
let(:referenced_issue) { create :issue, project: target_project }
it 'returns no destroy relation path' do
- target_project.add_guest(user)
+ target_project.add_developer(user)
expect(subject.first[:relation_path]).to be_nil
end
end
context 'user can admin related issues just on source project' do
+ let(:user_role) { :developer }
let(:target_project) { create :project }
let(:referenced_issue) { create :issue, project: target_project }
it 'returns no destroy relation path' do
- expect(subject).to eq([])
+ target_project.add_guest(user)
+
+ expect(subject.first[:relation_path]).to be_nil
end
end
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index 83e3af5b588..7cd2cd8f564 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -825,8 +825,7 @@ RSpec.describe Issues::CreateService, feature_category: :team_planning do
end
context 'add related issue' do
- let_it_be(:private_project) { create(:project) }
- let_it_be(:related_issue) { create(:issue, project: private_project) }
+ let_it_be(:related_issue) { create(:issue, project: project) }
let(:opts) do
{ title: 'A new issue', add_related_issue: related_issue }
@@ -840,7 +839,7 @@ RSpec.describe Issues::CreateService, feature_category: :team_planning do
context 'when user has access to the related issue' do
before do
- private_project.add_guest(user)
+ project.add_developer(user)
end
it 'adds a link to the issue' do
diff --git a/spec/support/helpers/stub_feature_flags.rb b/spec/support/helpers/stub_feature_flags.rb
index 42bb9982144..76fc8ebf84d 100644
--- a/spec/support/helpers/stub_feature_flags.rb
+++ b/spec/support/helpers/stub_feature_flags.rb
@@ -29,7 +29,7 @@ module StubFeatureFlags
return unless Gitlab::SafeRequestStore.active?
new_request = Feature::FlipperRequest.new
- allow(new_request).to receive(:id).and_return(SecureRandom.uuid)
+ allow(new_request).to receive(:flipper_id).and_return("FlipperRequest:#{SecureRandom.uuid}")
allow(Feature).to receive(:current_request).and_return(new_request)
end
diff --git a/spec/support/shared_contexts/policies/project_policy_shared_context.rb b/spec/support/shared_contexts/policies/project_policy_shared_context.rb
index 0ef1e041ec6..68eb3539813 100644
--- a/spec/support/shared_contexts/policies/project_policy_shared_context.rb
+++ b/spec/support/shared_contexts/policies/project_policy_shared_context.rb
@@ -32,7 +32,7 @@ RSpec.shared_context 'ProjectPolicy context' do
let(:base_reporter_permissions) do
%i[
- admin_issue admin_label admin_milestone admin_issue_board_list
+ admin_issue admin_issue_link admin_label admin_milestone admin_issue_board_list
create_snippet create_incident daily_statistics create_merge_request_in download_code
download_wiki_code fork_project metrics_dashboard read_build
read_commit_status read_confidential_issues read_container_image
diff --git a/spec/support/shared_examples/policies/project_policy_shared_examples.rb b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
index a79e3d179bb..349e15aa79d 100644
--- a/spec/support/shared_examples/policies/project_policy_shared_examples.rb
+++ b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
@@ -57,7 +57,7 @@ RSpec.shared_examples 'project policies as anonymous' do
context 'when a project has pending invites' do
let(:group) { create(:group, :public) }
let(:project) { create(:project, :public, namespace: group) }
- let(:user_permissions) { [:create_merge_request_in, :create_project, :create_issue, :create_note, :upload_file, :award_emoji, :create_incident, :admin_issue_link] }
+ let(:user_permissions) { [:create_merge_request_in, :create_project, :create_issue, :create_note, :upload_file, :award_emoji, :create_incident] }
let(:anonymous_permissions) { base_guest_permissions - user_permissions }
let(:current_user) { anonymous }
diff --git a/spec/support/shared_examples/services/issuable_links/create_links_shared_examples.rb b/spec/support/shared_examples/services/issuable_links/create_links_shared_examples.rb
index a2897044676..10dc185157c 100644
--- a/spec/support/shared_examples/services/issuable_links/create_links_shared_examples.rb
+++ b/spec/support/shared_examples/services/issuable_links/create_links_shared_examples.rb
@@ -5,6 +5,14 @@ RSpec.shared_examples 'issuable link creation' do |use_references: true|
let(:response_keys) { [:status, :created_references] }
let(:async_notes) { false }
let(:already_assigned_error_msg) { "#{issuable_type.capitalize}(s) already assigned" }
+ let(:permission_error_status) { issuable_type == :issue ? 403 : 404 }
+ let(:permission_error_msg) do
+ if issuable_type == :issue
+ "Couldn't link issue. You must have at least the Reporter role in both projects."
+ else
+ no_found_error_msg
+ end
+ end
let(:no_found_error_msg) do
"No matching #{issuable_type} found. Make sure that you are adding a valid #{issuable_type} URL."
@@ -39,7 +47,7 @@ RSpec.shared_examples 'issuable link creation' do |use_references: true|
let(:params) { set_params([restricted_issuable]) }
it 'returns error' do
- is_expected.to eq(message: no_found_error_msg, status: :error, http_status: 404)
+ is_expected.to eq(message: permission_error_msg, status: :error, http_status: permission_error_status)
end
it 'no relationship is created' do
diff --git a/spec/uploaders/pages/deployment_uploader_spec.rb b/spec/uploaders/pages/deployment_uploader_spec.rb
index a5fe2dfe9ba..efca5bd0cf1 100644
--- a/spec/uploaders/pages/deployment_uploader_spec.rb
+++ b/spec/uploaders/pages/deployment_uploader_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Pages::DeploymentUploader do
+RSpec.describe Pages::DeploymentUploader, feature_category: :pages do
let(:pages_deployment) { create(:pages_deployment) }
let(:uploader) { described_class.new(pages_deployment, :file) }
@@ -22,38 +22,41 @@ RSpec.describe Pages::DeploymentUploader do
stub_pages_object_storage
end
- it_behaves_like 'builds correct paths', store_dir: %r[\A\h{2}/\h{2}/\h{64}/pages_deployments/\d+\z]
+ describe '.default_store' do
+ it 'returns remote store when object storage is enabled' do
+ expect(described_class.default_store).to eq(ObjectStorage::Store::REMOTE)
+ end
+ end
it 'preserves original file when stores it' do
uploader.store!(file)
expect(File.exist?(file.path)).to be true
end
+
+ it_behaves_like 'builds correct paths',
+ store_dir: %r[\A\h{2}/\h{2}/\h{64}/pages_deployments/\d+\z]
end
context 'when file is stored in valid local_path' do
- before do
- uploader.store!(file)
+ describe '.default_store' do
+ it 'returns local store when object storage is not enabled' do
+ expect(described_class.default_store).to eq(ObjectStorage::Store::LOCAL)
+ end
end
- subject { uploader.file.path }
-
- it { is_expected.to match(%r[#{uploader.root}/@hashed/\h{2}/\h{2}/\h{64}/pages_deployments/#{pages_deployment.id}/pages.zip]) }
-
- it 'preserves original file when stores it' do
- expect(File.exist?(file.path)).to be true
- end
- end
+ it 'builds the right file path' do
+ uploader.store!(file)
- describe '.default_store' do
- it 'returns local store when object storage is not enabled' do
- expect(described_class.default_store).to eq(ObjectStorage::Store::LOCAL)
+ expect(uploader.file.path).to match(
+ %r[#{uploader.root}/@hashed/\h{2}/\h{2}/\h{64}/pages_deployments/#{pages_deployment.id}/pages.zip]
+ )
end
- it 'returns remote store when object storage is enabled' do
- stub_pages_object_storage
+ it 'preserves original file when stores it' do
+ uploader.store!(file)
- expect(described_class.default_store).to eq(ObjectStorage::Store::REMOTE)
+ expect(File.exist?(file.path)).to be true
end
end
end