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:
-rw-r--r--.rubocop_todo/layout/hash_alignment.yml20
-rw-r--r--.rubocop_todo/layout/space_inside_block_braces.yml60
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock8
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue31
-rw-r--r--app/assets/javascripts/invite_members/constants.js4
-rw-r--r--app/controllers/concerns/packages_access.rb2
-rw-r--r--app/helpers/deploy_tokens_helper.rb2
-rw-r--r--app/models/concerns/pg_full_text_searchable.rb1
-rw-r--r--app/models/group.rb8
-rw-r--r--app/models/packages/policies/group.rb15
-rw-r--r--app/models/packages/policies/project.rb15
-rw-r--r--app/models/project.rb8
-rw-r--r--app/policies/packages/package_policy.rb2
-rw-r--r--app/policies/packages/policies/group_policy.rb27
-rw-r--r--app/policies/packages/policies/project_policy.rb35
-rw-r--r--app/services/packages/conan/search_service.rb2
-rw-r--r--app/services/packages/rubygems/dependency_resolver_service.rb5
-rw-r--r--config/feature_flags/development/read_package_policy_rule.yml8
-rw-r--r--doc/administration/auth/atlassian.md5
-rw-r--r--doc/administration/auth/jwt.md5
-rw-r--r--doc/administration/auth/ldap/index.md2
-rw-r--r--doc/administration/gitaly/configure_gitaly.md7
-rw-r--r--doc/administration/pages/index.md4
-rw-r--r--doc/administration/pages/source.md5
-rw-r--r--doc/api/members.md1
-rw-r--r--doc/api/project_level_variables.md57
-rw-r--r--doc/integration/cas.md6
-rw-r--r--doc/integration/ding_talk.md4
-rw-r--r--doc/integration/facebook.md5
-rw-r--r--doc/integration/google.md7
-rw-r--r--doc/integration/mattermost/index.md2
-rw-r--r--doc/integration/salesforce.md7
-rw-r--r--doc/integration/saml.md4
-rw-r--r--doc/integration/twitter.md5
-rw-r--r--doc/user/packages/container_registry/reduce_container_registry_storage.md2
-rw-r--r--lib/api/concerns/packages/conan_endpoints.rb8
-rw-r--r--lib/api/helpers/packages/conan/api_helpers.rb4
-rw-r--r--lib/api/helpers/packages_helpers.rb2
-rw-r--r--lib/api/members.rb1
-rw-r--r--lib/api/rubygem_packages.rb2
-rw-r--r--lib/gitlab/cache/import/caching.rb4
-rw-r--r--lib/sidebars/projects/menus/packages_registries_menu.rb3
-rw-r--r--locale/gitlab.pot9
-rw-r--r--spec/factories/ci/build_trace_chunks.rb4
-rw-r--r--spec/factories/ci/job_artifacts.rb2
-rw-r--r--spec/factories/ci/pipeline_artifacts.rb2
-rw-r--r--spec/factories/commit_statuses.rb6
-rw-r--r--spec/factories/emails.rb2
-rw-r--r--spec/factories/external_pull_requests.rb2
-rw-r--r--spec/factories/gitlab/database/postgres_index.rb2
-rw-r--r--spec/factories/packages/dependencies.rb4
-rw-r--r--spec/factories/packages/package_tags.rb2
-rw-r--r--spec/factories/packages/packages.rb10
-rw-r--r--spec/factories/prometheus_alert.rb2
-rw-r--r--spec/factories/prometheus_metrics.rb2
-rw-r--r--spec/frontend/fixtures/api_merge_requests.rb2
-rw-r--r--spec/frontend/fixtures/api_projects.rb2
-rw-r--r--spec/frontend/fixtures/application_settings.rb2
-rw-r--r--spec/frontend/fixtures/blob.rb2
-rw-r--r--spec/frontend/fixtures/branches.rb2
-rw-r--r--spec/frontend/fixtures/clusters.rb2
-rw-r--r--spec/frontend/fixtures/deploy_keys.rb8
-rw-r--r--spec/frontend/fixtures/groups.rb2
-rw-r--r--spec/frontend/fixtures/issues.rb2
-rw-r--r--spec/frontend/fixtures/jobs.rb2
-rw-r--r--spec/frontend/fixtures/labels.rb2
-rw-r--r--spec/frontend/fixtures/merge_requests.rb2
-rw-r--r--spec/frontend/fixtures/merge_requests_diffs.rb2
-rw-r--r--spec/frontend/fixtures/metrics_dashboard.rb2
-rw-r--r--spec/frontend/fixtures/pipeline_schedules.rb2
-rw-r--r--spec/frontend/fixtures/pipelines.rb2
-rw-r--r--spec/frontend/fixtures/projects.rb2
-rw-r--r--spec/frontend/fixtures/raw.rb2
-rw-r--r--spec/frontend/fixtures/snippet.rb2
-rw-r--r--spec/frontend/fixtures/todos.rb2
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js32
-rw-r--r--spec/lib/api/helpers/packages_helpers_spec.rb42
-rw-r--r--spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb16
-rw-r--r--spec/models/concerns/pg_full_text_searchable_spec.rb1
-rw-r--r--spec/models/group_spec.rb17
-rw-r--r--spec/models/project_spec.rb19
-rw-r--r--spec/policies/packages/policies/group_policy_spec.rb79
-rw-r--r--spec/policies/packages/policies/project_policy_spec.rb87
-rw-r--r--spec/support/helpers/cycle_analytics_helpers.rb2
-rw-r--r--spec/support/redis/redis_shared_examples.rb10
-rw-r--r--spec/support/shared_contexts/graphql/requests/packages_shared_context.rb4
-rw-r--r--spec/support/shared_contexts/markdown_golden_master_shared_examples.rb2
-rw-r--r--spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb2
-rw-r--r--spec/support/shared_examples/controllers/error_tracking_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/controllers/snippets_sort_order_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/board_sidebar_labels_examples.rb2
-rw-r--r--spec/support/shared_examples/features/snippets_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/wiki/user_views_asciidoc_page_with_includes_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/cluster_application_core_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb2
-rw-r--r--spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/models/concerns/incident_management/escalatable_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/label_note_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/issues/merge_requests_count_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/labels_api_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/lfs_http_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/services/gitlab_projects_import_service_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/services/merge_request_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/uploaders/object_storage_shared_examples.rb4
113 files changed, 645 insertions, 244 deletions
diff --git a/.rubocop_todo/layout/hash_alignment.yml b/.rubocop_todo/layout/hash_alignment.yml
index a09458eecf9..9ecfe11d765 100644
--- a/.rubocop_todo/layout/hash_alignment.yml
+++ b/.rubocop_todo/layout/hash_alignment.yml
@@ -22,26 +22,6 @@ Layout/HashAlignment:
- 'ee/spec/lib/gitlab/elastic/indexer_spec.rb'
- 'ee/spec/lib/gitlab/insights/loader_spec.rb'
- 'ee/spec/lib/gitlab/template/custom_templates_spec.rb'
- - 'ee/spec/models/application_setting_spec.rb'
- - 'ee/spec/models/approval_merge_request_rule_spec.rb'
- - 'ee/spec/models/member_spec.rb'
- - 'ee/spec/models/preloaders/environments/protected_environment_preloader_spec.rb'
- - 'ee/spec/models/protected_environments/approval_summary_spec.rb'
- - 'ee/spec/models/vulnerabilities/statistic_spec.rb'
- - 'ee/spec/requests/api/deployments_spec.rb'
- - 'ee/spec/requests/api/graphql/app_sec/fuzzing/coverage/corpus_type_spec.rb'
- - 'ee/spec/requests/api/graphql/group/epics_spec.rb'
- - 'ee/spec/requests/api/internal/base_spec.rb'
- - 'ee/spec/requests/api/issues_spec.rb'
- - 'ee/spec/requests/api/protected_environments_spec.rb'
- - 'ee/spec/requests/api/templates_spec.rb'
- - 'ee/spec/requests/ee/projects/environments_controller_spec.rb'
- - 'ee/spec/requests/ee/projects/service_desk_controller_spec.rb'
- - 'ee/spec/requests/projects/security/dast_site_profiles_controller_spec.rb'
- - 'ee/spec/requests/rack_attack_global_spec.rb'
- - 'ee/spec/serializers/integrations/zentao_serializers/issue_entity_spec.rb'
- - 'ee/spec/services/app_sec/dast/profiles/create_associations_service_spec.rb'
- - 'ee/spec/services/app_sec/dast/scan_configs/fetch_service_spec.rb'
- 'ee/spec/services/arkose/blocked_users_report_service_spec.rb'
- 'ee/spec/services/audit_events/protected_branch_audit_event_service_spec.rb'
- 'ee/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb'
diff --git a/.rubocop_todo/layout/space_inside_block_braces.yml b/.rubocop_todo/layout/space_inside_block_braces.yml
index 4fdc308eaa5..25fc6dba4d9 100644
--- a/.rubocop_todo/layout/space_inside_block_braces.yml
+++ b/.rubocop_todo/layout/space_inside_block_braces.yml
@@ -20,18 +20,6 @@ Layout/SpaceInsideBlockBraces:
- 'spec/controllers/snippets/notes_controller_spec.rb'
- 'spec/dependencies/omniauth_saml_spec.rb'
- 'spec/experiments/application_experiment_spec.rb'
- - 'spec/factories/ci/build_trace_chunks.rb'
- - 'spec/factories/ci/job_artifacts.rb'
- - 'spec/factories/ci/pipeline_artifacts.rb'
- - 'spec/factories/commit_statuses.rb'
- - 'spec/factories/emails.rb'
- - 'spec/factories/external_pull_requests.rb'
- - 'spec/factories/gitlab/database/postgres_index.rb'
- - 'spec/factories/packages/dependencies.rb'
- - 'spec/factories/packages/package_tags.rb'
- - 'spec/factories/packages/packages.rb'
- - 'spec/factories/prometheus_alert.rb'
- - 'spec/factories/prometheus_metrics.rb'
- 'spec/finders/ci/jobs_finder_spec.rb'
- 'spec/finders/ci/runners_finder_spec.rb'
- 'spec/finders/concerns/packages/finder_helper_spec.rb'
@@ -41,26 +29,6 @@ Layout/SpaceInsideBlockBraces:
- 'spec/finders/packages/group_packages_finder_spec.rb'
- 'spec/finders/packages/npm/package_finder_spec.rb'
- 'spec/finders/projects_finder_spec.rb'
- - 'spec/frontend/fixtures/api_merge_requests.rb'
- - 'spec/frontend/fixtures/api_projects.rb'
- - 'spec/frontend/fixtures/application_settings.rb'
- - 'spec/frontend/fixtures/blob.rb'
- - 'spec/frontend/fixtures/branches.rb'
- - 'spec/frontend/fixtures/clusters.rb'
- - 'spec/frontend/fixtures/deploy_keys.rb'
- - 'spec/frontend/fixtures/groups.rb'
- - 'spec/frontend/fixtures/issues.rb'
- - 'spec/frontend/fixtures/jobs.rb'
- - 'spec/frontend/fixtures/labels.rb'
- - 'spec/frontend/fixtures/merge_requests.rb'
- - 'spec/frontend/fixtures/merge_requests_diffs.rb'
- - 'spec/frontend/fixtures/metrics_dashboard.rb'
- - 'spec/frontend/fixtures/pipeline_schedules.rb'
- - 'spec/frontend/fixtures/pipelines.rb'
- - 'spec/frontend/fixtures/projects.rb'
- - 'spec/frontend/fixtures/raw.rb'
- - 'spec/frontend/fixtures/snippet.rb'
- - 'spec/frontend/fixtures/todos.rb'
- 'spec/helpers/application_settings_helper_spec.rb'
- 'spec/helpers/blob_helper_spec.rb'
- 'spec/helpers/gitlab_script_tag_helper_spec.rb'
@@ -91,34 +59,6 @@ Layout/SpaceInsideBlockBraces:
- 'spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb'
- 'spec/serializers/cluster_entity_spec.rb'
- 'spec/serializers/import/provider_repo_serializer_spec.rb'
- - 'spec/support/helpers/cycle_analytics_helpers.rb'
- - 'spec/support/redis/redis_shared_examples.rb'
- - 'spec/support/shared_contexts/graphql/requests/packages_shared_context.rb'
- - 'spec/support/shared_contexts/markdown_golden_master_shared_examples.rb'
- - 'spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb'
- - 'spec/support/shared_examples/controllers/error_tracking_shared_examples.rb'
- - 'spec/support/shared_examples/controllers/snippets_sort_order_shared_examples.rb'
- - 'spec/support/shared_examples/features/board_sidebar_labels_examples.rb'
- - 'spec/support/shared_examples/features/snippets_shared_examples.rb'
- - 'spec/support/shared_examples/features/wiki/user_views_asciidoc_page_with_includes_shared_examples.rb'
- - 'spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb'
- - 'spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb'
- - 'spec/support/shared_examples/models/cluster_application_core_shared_examples.rb'
- - 'spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb'
- - 'spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb'
- - 'spec/support/shared_examples/models/concerns/incident_management/escalatable_shared_examples.rb'
- - 'spec/support/shared_examples/models/label_note_shared_examples.rb'
- - 'spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb'
- - 'spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/issues/merge_requests_count_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/labels_api_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb'
- - 'spec/support/shared_examples/requests/lfs_http_shared_examples.rb'
- - 'spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb'
- - 'spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb'
- - 'spec/support/shared_examples/services/gitlab_projects_import_service_shared_examples.rb'
- - 'spec/support/shared_examples/services/merge_request_shared_examples.rb'
- - 'spec/support/shared_examples/uploaders/object_storage_shared_examples.rb'
- 'spec/tasks/gitlab/snippets_rake_spec.rb'
- 'spec/uploaders/packages/debian/distribution_release_file_uploader_spec.rb'
- 'spec/validators/addressable_url_validator_spec.rb'
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 61d6cbe8694..52a7b5b79d7 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-bcabbb9feb2e80a3dd9930a6033997a364996368
+e64db386270cd47b44f88f04b139d34313d4780b
diff --git a/Gemfile b/Gemfile
index 250d8865551..c4a70473566 100644
--- a/Gemfile
+++ b/Gemfile
@@ -29,7 +29,7 @@ gem 'marginalia', '~> 1.10.0'
gem 'declarative_policy', '~> 1.1.0'
# Authentication libraries
-gem 'devise', '~> 4.7.2'
+gem 'devise', '~> 4.8.1'
gem 'devise-pbkdf2-encryptable', '~> 0.0.0', path: 'vendor/gems/devise-pbkdf2-encryptable'
gem 'bcrypt', '~> 3.1', '>= 3.1.14'
gem 'doorkeeper', '~> 5.5.0.rc2'
diff --git a/Gemfile.lock b/Gemfile.lock
index 4f1b5449336..febed30c061 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -306,7 +306,7 @@ GEM
ruby-statistics (>= 2.1)
thor (>= 0.19, < 2)
device_detector (1.0.0)
- devise (4.7.3)
+ devise (4.8.1)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
@@ -1445,8 +1445,8 @@ GEM
concurrent-ruby (~> 1.0)
method_source (~> 1.0)
vmstat (2.3.0)
- warden (1.2.8)
- rack (>= 2.0.6)
+ warden (1.2.9)
+ rack (>= 2.0.9)
warning (1.3.0)
webauthn (2.3.0)
android_key_attestation (~> 0.3.0)
@@ -1536,7 +1536,7 @@ DEPENDENCIES
deprecation_toolkit (~> 1.5.1)
derailed_benchmarks
device_detector
- devise (~> 4.7.2)
+ devise (~> 4.8.1)
devise-pbkdf2-encryptable (~> 0.0.0)!
devise-two-factor (~> 4.0.2)
diff_match_patch (~> 0.1.0)
diff --git a/app/assets/javascripts/invite_members/components/invite_members_modal.vue b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
index 87f1ed31a7f..a334f5e4bf7 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -118,6 +118,7 @@ export default {
selectedAccessLevel: undefined,
errorsLimit: 2,
isErrorsSectionExpanded: false,
+ emptyInvitesError: false,
};
},
computed: {
@@ -133,8 +134,8 @@ export default {
labelIntroText() {
return this.$options.labels[this.inviteTo][this.mode].introText;
},
- inviteDisabled() {
- return this.newUsersToInvite.length === 0;
+ isEmptyInvites() {
+ return Boolean(this.newUsersToInvite.length);
},
hasInvalidMembers() {
return !isEmpty(this.invalidMembers);
@@ -219,6 +220,18 @@ export default {
});
},
},
+ watch: {
+ isEmptyInvites: {
+ handler(updatedValue) {
+ // nothing to do if the invites are **still** empty and the emptyInvites were never set from submit
+ if (!updatedValue && !this.emptyInvitesError) {
+ return;
+ }
+
+ this.clearEmptyInviteError();
+ },
+ },
+ },
mounted() {
eventHub.$on('openModal', (options) => {
this.openModal(options);
@@ -260,10 +273,19 @@ export default {
const tracking = new ExperimentTracking(experimentName);
tracking.event(eventName);
},
+ showEmptyInvitesError() {
+ this.invalidFeedbackMessage = this.$options.labels.emptyInvitesErrorText;
+ this.emptyInvitesError = true;
+ },
sendInvite({ accessLevel, expiresAt }) {
this.isLoading = true;
this.clearValidation();
+ if (!this.isEmptyInvites) {
+ this.showEmptyInvitesError();
+ return;
+ }
+
const [usersToInviteByEmail, usersToAddById] = this.partitionNewUsersToInvite();
const apiAddByInvite = this.isProject
@@ -338,6 +360,10 @@ export default {
this.invalidFeedbackMessage = '';
this.invalidMembers = {};
},
+ clearEmptyInviteError() {
+ this.invalidFeedbackMessage = '';
+ this.emptyInvitesError = false;
+ },
removeToken(token) {
delete this.invalidMembers[memberName(token)];
this.invalidMembers = { ...this.invalidMembers };
@@ -360,7 +386,6 @@ export default {
:label-intro-text="labelIntroText"
:label-search-field="$options.labels.searchField"
:form-group-description="formGroupDescription"
- :submit-disabled="inviteDisabled"
:invalid-feedback-message="invalidFeedbackMessage"
:is-loading="isLoading"
:new-users-to-invite="newUsersToInvite"
diff --git a/app/assets/javascripts/invite_members/constants.js b/app/assets/javascripts/invite_members/constants.js
index 288c2bb9829..f502e1ea369 100644
--- a/app/assets/javascripts/invite_members/constants.js
+++ b/app/assets/javascripts/invite_members/constants.js
@@ -81,6 +81,9 @@ export const MEMBER_ERROR_LIST_TEXT = s__(
);
export const COLLAPSED_ERRORS = s__('InviteMembersModal|Show more (%{count})');
export const EXPANDED_ERRORS = s__('InviteMembersModal|Show less');
+export const EMPTY_INVITES_ERROR_TEXT = s__(
+ 'InviteMembersModal|Please select members or type email addresses to invite',
+);
export const MEMBER_MODAL_LABELS = {
modal: {
@@ -119,6 +122,7 @@ export const MEMBER_MODAL_LABELS = {
memberErrorListText: MEMBER_ERROR_LIST_TEXT,
collapsedErrors: COLLAPSED_ERRORS,
expandedErrors: EXPANDED_ERRORS,
+ emptyInvitesErrorText: EMPTY_INVITES_ERROR_TEXT,
};
export const GROUP_MODAL_LABELS = {
diff --git a/app/controllers/concerns/packages_access.rb b/app/controllers/concerns/packages_access.rb
index 6df2e064bb2..a7d16a5bc88 100644
--- a/app/controllers/concerns/packages_access.rb
+++ b/app/controllers/concerns/packages_access.rb
@@ -15,6 +15,6 @@ module PackagesAccess
end
def verify_read_package!
- authorize_read_package!(project)
+ access_denied! unless can?(current_user, :read_package, project&.packages_policy_subject)
end
end
diff --git a/app/helpers/deploy_tokens_helper.rb b/app/helpers/deploy_tokens_helper.rb
index 560d2fcd29f..d4da928edf1 100644
--- a/app/helpers/deploy_tokens_helper.rb
+++ b/app/helpers/deploy_tokens_helper.rb
@@ -14,7 +14,7 @@ module DeployTokensHelper
def packages_registry_enabled?(group_or_project)
Gitlab.config.packages.enabled &&
- can?(current_user, :read_package, group_or_project)
+ can?(current_user, :read_package, group_or_project&.packages_policy_subject)
end
def deploy_token_revoke_button_data(token:, group_or_project:)
diff --git a/app/models/concerns/pg_full_text_searchable.rb b/app/models/concerns/pg_full_text_searchable.rb
index 813827478da..335fcec2611 100644
--- a/app/models/concerns/pg_full_text_searchable.rb
+++ b/app/models/concerns/pg_full_text_searchable.rb
@@ -108,6 +108,7 @@ module PgFullTextSearchable
# This fixes an inconsistency with how to_tsvector and websearch_to_tsquery process URLs
# See https://gitlab.com/gitlab-org/gitlab/-/issues/354784#note_905431920
search_term = remove_url_scheme(search_term)
+ search_term = ActiveSupport::Inflector.transliterate(search_term)
joins(:search_data).where(
Arel::Nodes::InfixOperation.new(
diff --git a/app/models/group.rb b/app/models/group.rb
index 55455d85531..e0d10030b9f 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -890,6 +890,14 @@ class Group < Namespace
end
end
+ def packages_policy_subject
+ if Feature.enabled?(:read_package_policy_rule, self)
+ ::Packages::Policies::Group.new(self)
+ else
+ self
+ end
+ end
+
private
def feature_flag_enabled_for_self_or_ancestor?(feature_flag)
diff --git a/app/models/packages/policies/group.rb b/app/models/packages/policies/group.rb
new file mode 100644
index 00000000000..66cd361f2ed
--- /dev/null
+++ b/app/models/packages/policies/group.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Packages
+ module Policies
+ class Group
+ attr_accessor :group
+
+ delegate_missing_to :group
+
+ def initialize(group)
+ @group = group
+ end
+ end
+ end
+end
diff --git a/app/models/packages/policies/project.rb b/app/models/packages/policies/project.rb
new file mode 100644
index 00000000000..a5c6703be42
--- /dev/null
+++ b/app/models/packages/policies/project.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Packages
+ module Policies
+ class Project
+ attr_accessor :project
+
+ delegate_missing_to :project
+
+ def initialize(project)
+ @project = project
+ end
+ end
+ end
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 66ed6ea6ce9..175998efe93 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -3050,6 +3050,14 @@ class Project < ApplicationRecord
licensed_feature_available?(:security_training)
end
+ def packages_policy_subject
+ if Feature.enabled?(:read_package_policy_rule, group)
+ ::Packages::Policies::Project.new(self)
+ else
+ self
+ end
+ end
+
def destroy_deployment_by_id(deployment_id)
deployments.where(id: deployment_id).fast_destroy_all
end
diff --git a/app/policies/packages/package_policy.rb b/app/policies/packages/package_policy.rb
index 8eef280c640..829d62a6430 100644
--- a/app/policies/packages/package_policy.rb
+++ b/app/policies/packages/package_policy.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
module Packages
class PackagePolicy < BasePolicy
- delegate { @subject.project }
+ delegate { @subject.project&.packages_policy_subject }
end
end
diff --git a/app/policies/packages/policies/group_policy.rb b/app/policies/packages/policies/group_policy.rb
new file mode 100644
index 00000000000..32dbcb1b65b
--- /dev/null
+++ b/app/policies/packages/policies/group_policy.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Packages
+ module Policies
+ class GroupPolicy < BasePolicy
+ delegate(:group) { @subject.group }
+
+ overrides(:read_package)
+
+ rule { group.public_group }.policy do
+ enable :read_package
+ end
+
+ rule { group.reporter }.policy do
+ enable :read_package
+ end
+
+ rule { group.read_package_registry_deploy_token }.policy do
+ enable :read_package
+ end
+
+ rule { group.write_package_registry_deploy_token }.policy do
+ enable :read_package
+ end
+ end
+ end
+end
diff --git a/app/policies/packages/policies/project_policy.rb b/app/policies/packages/policies/project_policy.rb
new file mode 100644
index 00000000000..8e05165c00d
--- /dev/null
+++ b/app/policies/packages/policies/project_policy.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Packages
+ module Policies
+ class ProjectPolicy < BasePolicy
+ delegate(:project) { @subject.project }
+
+ overrides(:read_package)
+
+ rule { anonymous & ~project.public_project }.prevent_all
+
+ rule { ~project.public_project & ~project.internal_access & ~project.project_allowed_for_job_token }.prevent_all
+
+ rule { project.packages_disabled }.policy do
+ prevent(:read_package)
+ end
+
+ rule { can?(:reporter_access) }.policy do
+ enable :read_package
+ end
+
+ rule { can?(:public_access) }.policy do
+ enable :read_package
+ end
+
+ rule { project.read_package_registry_deploy_token }.policy do
+ enable :read_package
+ end
+
+ rule { project.write_package_registry_deploy_token }.policy do
+ enable :read_package
+ end
+ end
+ end
+end
diff --git a/app/services/packages/conan/search_service.rb b/app/services/packages/conan/search_service.rb
index 31ee9bea084..df22a895c00 100644
--- a/app/services/packages/conan/search_service.rb
+++ b/app/services/packages/conan/search_service.rb
@@ -44,7 +44,7 @@ module Packages
name, version, username, _ = query.split(%r{[@/]})
full_path = Packages::Conan::Metadatum.full_path_from(package_username: username)
project = Project.find_by_full_path(full_path)
- return unless Ability.allowed?(current_user, :read_package, project)
+ return unless Ability.allowed?(current_user, :read_package, project&.packages_policy_subject)
result = project.packages.with_name(name).with_version(version).order_created.last
[result&.conan_recipe].compact
diff --git a/app/services/packages/rubygems/dependency_resolver_service.rb b/app/services/packages/rubygems/dependency_resolver_service.rb
index c44b26e2b92..839a7683632 100644
--- a/app/services/packages/rubygems/dependency_resolver_service.rb
+++ b/app/services/packages/rubygems/dependency_resolver_service.rb
@@ -8,7 +8,10 @@ module Packages
DEFAULT_PLATFORM = 'ruby'
def execute
- return ServiceResponse.error(message: "forbidden", http_status: :forbidden) unless Ability.allowed?(current_user, :read_package, project)
+ unless Ability.allowed?(current_user, :read_package, project&.packages_policy_subject)
+ return ServiceResponse.error(message: "forbidden", http_status: :forbidden)
+ end
+
return ServiceResponse.error(message: "#{gem_name} not found", http_status: :not_found) if packages.empty?
payload = packages.map do |package|
diff --git a/config/feature_flags/development/read_package_policy_rule.yml b/config/feature_flags/development/read_package_policy_rule.yml
new file mode 100644
index 00000000000..151c5a8c0b5
--- /dev/null
+++ b/config/feature_flags/development/read_package_policy_rule.yml
@@ -0,0 +1,8 @@
+---
+name: read_package_policy_rule
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90963
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366711
+milestone: '15.4'
+type: development
+group: group::package
+default_enabled: false
diff --git a/doc/administration/auth/atlassian.md b/doc/administration/auth/atlassian.md
index 6be53922a5a..1d20d87bdf4 100644
--- a/doc/administration/auth/atlassian.md
+++ b/doc/administration/auth/atlassian.md
@@ -71,7 +71,10 @@ To enable the Atlassian OmniAuth provider for passwordless authentication you mu
1. Change `YOUR_CLIENT_ID` and `YOUR_CLIENT_SECRET` to the Client credentials you received in [application registration](#atlassian-application-registration) steps.
1. Save the configuration file.
-1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect if you installed GitLab via Omnibus or from source respectively.
+
+1. For the changes to take effect:
+ - If you installed via Omnibus, [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+ - If you installed from source, [restart GitLab](../restart_gitlab.md#installations-from-source).
On the sign-in page there should now be an Atlassian icon below the regular sign in form. Select the icon to begin the authentication process.
diff --git a/doc/administration/auth/jwt.md b/doc/administration/auth/jwt.md
index 99cba3f220d..71ab084065a 100644
--- a/doc/administration/auth/jwt.md
+++ b/doc/administration/auth/jwt.md
@@ -70,8 +70,9 @@ JWT provides you with a secret key for you to use.
1. Change `YOUR_APP_SECRET` to the client secret and set `auth_url` to your redirect URL.
1. Save the configuration file.
-1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect if you
- installed GitLab via Omnibus or from source respectively.
+1. For the changes to take effect:
+ - If you installed via Omnibus, [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+ - If you installed from source, [restart GitLab](../restart_gitlab.md#installations-from-source).
On the sign in page there should now be a JWT icon below the regular sign in form.
Select the icon to begin the authentication process. JWT asks the user to
diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md
index 2f0a0db9d6f..19f656d2f14 100644
--- a/doc/administration/auth/ldap/index.md
+++ b/doc/administration/auth/ldap/index.md
@@ -344,7 +344,7 @@ The `user_filter` DN can contain special characters. For example:
OU=GitLab\2C Inc,DC=gitlab,DC=com
```
-- Escape open and close brackets with `\28` and `\29`, respectively. For example:
+- Escape open brackets with `\28` and close brackets with `\29`. For example:
```plaintext
OU=Gitlab \28Inc\29,DC=gitlab,DC=com
diff --git a/doc/administration/gitaly/configure_gitaly.md b/doc/administration/gitaly/configure_gitaly.md
index 5b868c274cd..ac03c3ffc02 100644
--- a/doc/administration/gitaly/configure_gitaly.md
+++ b/doc/administration/gitaly/configure_gitaly.md
@@ -1089,9 +1089,10 @@ lots of CI fetch traffic.
The pack-objects cache wraps `git pack-objects`, an internal part of
Git that gets invoked indirectly via the PostUploadPack and
-SSHUploadPack Gitaly RPCs. These are the RPCs that Gitaly runs when a
-user does a Git fetch via HTTP or SSH, respectively. When the cache is
-enabled, anything that uses PostUploadPack or SSHUploadPack can
+SSHUploadPack Gitaly RPCs. Gitaly runs PostUploadPack when a
+user does a Git fetch via HTTP, or SSHUploadPack when a
+user does a Git fetch via SSH.
+When the cache is enabled, anything that uses PostUploadPack or SSHUploadPack can
benefit from it. It is orthogonal to:
- The transport (HTTP or SSH).
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index e545fb3cd1b..d5eb354c104 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -156,7 +156,7 @@ Watch the [video tutorial](https://youtu.be/dD8c7WNcc6s) for this configuration.
**Requirements:**
- [Wildcard DNS setup](#dns-configuration)
-- Wildcard TLS certificate
+- TLS certificate. Can be either Wildcard, or any other type meeting the [requirements](../../user/project/pages/custom_domains_ssl_tls_certification/index.md#manual-addition-of-ssltls-certificates).
---
@@ -368,7 +368,7 @@ world. Custom domains and TLS are supported.
If you don't have IPv6, you can omit the IPv6 address.
-1. If you haven't named your certificate and key `example.io.crt` and `example.io.key` respectively,
+1. If you haven't named your certificate `example.io.crt` and your key `example.io.key`,
then you need to also add the full paths as shown below:
```ruby
diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md
index 5ab508dbaca..5bee96081bb 100644
--- a/doc/administration/pages/source.md
+++ b/doc/administration/pages/source.md
@@ -364,9 +364,8 @@ world. Custom domains and TLS are supported.
```
1. Edit `/etc/default/gitlab` and set `gitlab_pages_enabled` to `true` in
- order to enable the pages daemon. In `gitlab_pages_options` the
- `-pages-domain`, `-listen-http` and `-listen-https` must match the `host`,
- `external_http` and `external_https` settings that you set above respectively.
+ order to enable the pages daemon. In `gitlab_pages_options`, you must match the
+ `-pages-domain` with `host`, `-listen-http` with `external_http`, and `-listen-https` with `external_https` settings.
The `-root-cert` and `-root-key` settings are the wildcard TLS certificates
of the `example.io` domain:
diff --git a/doc/api/members.md b/doc/api/members.md
index a9817918d0b..aa7d697c6c6 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -47,6 +47,7 @@ GET /projects/:id/members
| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](index.md#namespaced-path-encoding) owned by the authenticated user |
| `query` | string | no | A query string to search for members |
| `user_ids` | array of integers | no | Filter the results on the given user IDs |
+| `skip_users` | array of integers | no | Filter skipped users out of the results |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members"
diff --git a/doc/api/project_level_variables.md b/doc/api/project_level_variables.md
index 81bb4a26614..39e7f441b42 100644
--- a/doc/api/project_level_variables.md
+++ b/doc/api/project_level_variables.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, api
---
-# Project-level Variables API **(FREE)**
+# Project-level CI/CD variables API **(FREE)**
## List project variables
@@ -44,9 +44,10 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
]
```
-## Show variable details
+## Get a single variable
-Get the details of a project's specific variable.
+Get the details of a single variable. If there are multiple variables with the same key,
+use `filter` to select the correct `environment_scope`.
```plaintext
GET /projects/:id/variables/:key
@@ -73,9 +74,11 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
}
```
-## Create variable
+## Create a variable
-Create a new variable.
+Create a new variable. If a variable with the same `key` already exists, the new variable
+must have a different `environment_scope`. Otherwise, GitLab returns a message similar to:
+`VARIABLE_NAME has already been taken`.
```plaintext
POST /projects/:id/variables
@@ -107,9 +110,10 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
}
```
-## Update variable
+## Update a variable
-Update a project's variable.
+Update a project's variable. If there are multiple variables with the same key,
+use `filter` to select the correct `environment_scope`.
```plaintext
PUT /projects/:id/variables/:key
@@ -142,9 +146,10 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
}
```
-## Remove variable
+## Delete a variable
-Remove a project's variable.
+Delete a project's variable. If there are multiple variables with the same key,
+use `filter` to select the correct `environment_scope`.
```plaintext
DELETE /projects/:id/variables/:key
@@ -165,10 +170,34 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34490) in GitLab 13.2.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/227052) in GitLab 13.4.
-This parameter is used for filtering by attributes, such as `environment_scope`.
+When multiple variables have the same `key`, [GET](#get-a-single-variable), [PUT](#update-a-variable),
+or [DELETE](#delete-a-variable) requests might return:
-Example usage:
-
-```shell
-curl --globoff --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables/VARIABLE_1?filter[environment_scope]=production"
+```plaintext
+There are multiple variables with provided parameters. Please use 'filter[environment_scope]'.
```
+
+Use `filter[environment_scope]` to select the variable with the matching `environment_scope` attribute.
+
+For example:
+
+- GET:
+
+ ```shell
+ curl --globoff --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/1/variables/SCOPED_VARIABLE_1?filter[environment_scope]=production"
+ ```
+
+- PUT:
+
+ ```shell
+ curl --request PUT --globoff --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/1/variables/SCOPED_VARIABLE_1?value=scoped-variable-updated-value&environment_scope=production&filter[environment_scope]=production"
+ ```
+
+- DELETE:
+
+ ```shell
+ curl --request DELETE --globoff --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/projects/1/variables/SCOPED_VARIABLE_1?filter[environment_scope]=production"
+ ```
diff --git a/doc/integration/cas.md b/doc/integration/cas.md
index 38305967246..45c79cd9726 100644
--- a/doc/integration/cas.md
+++ b/doc/integration/cas.md
@@ -71,8 +71,8 @@ configure CAS for back-channel logout.
1. Save the configuration file.
-1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or
- [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to
- take effect if you installed GitLab via Omnibus or from source respectively.
+1. For the changes to take effect:
+ - If you installed via Omnibus, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
+ - If you installed from source, [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
On the sign in page there should now be a CAS tab in the sign in form.
diff --git a/doc/integration/ding_talk.md b/doc/integration/ding_talk.md
index 437648b1adf..71dadd766b2 100644
--- a/doc/integration/ding_talk.md
+++ b/doc/integration/ding_talk.md
@@ -83,4 +83,6 @@ Sign in to DingTalk Open Platform and create an application on it. DingTalk gene
1. Save the configuration file.
-1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect if you installed GitLab via Omnibus or from source respectively.
+1. For the changes to take effect:
+ - If you installed via Omnibus, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
+ - If you installed from source, [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
diff --git a/doc/integration/facebook.md b/doc/integration/facebook.md
index 99ebce32936..ea5a3cc6d38 100644
--- a/doc/integration/facebook.md
+++ b/doc/integration/facebook.md
@@ -104,8 +104,9 @@ Facebook. Facebook generates an app ID and secret key for you to use.
1. Save the configuration file.
-1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect if you
- installed GitLab via Omnibus or from source respectively.
+1. For the changes to take effect:
+ - If you installed via Omnibus, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
+ - If you installed from source, [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
On the sign in page there should now be a Facebook icon below the regular sign
in form. Select the icon to begin the authentication process. Facebook asks the
diff --git a/doc/integration/google.md b/doc/integration/google.md
index 4862b898ed5..80176fac41b 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -117,10 +117,9 @@ On your GitLab server:
```
1. Save the configuration file.
-1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure)
- or [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for
- the changes to take effect if you installed GitLab via Omnibus or from source
- respectively.
+1. For the changes to take effect:
+ - If you installed via Omnibus, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
+ - If you installed from source, [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
On the sign in page there should now be a Google icon below the regular sign in
form. Select the icon to begin the authentication process. Google asks the
diff --git a/doc/integration/mattermost/index.md b/doc/integration/mattermost/index.md
index 3293732b59b..8b5a374ca11 100644
--- a/doc/integration/mattermost/index.md
+++ b/doc/integration/mattermost/index.md
@@ -79,7 +79,7 @@ mattermost_nginx['ssl_certificate'] = "/etc/gitlab/ssl/mattermost-nginx.crt"
mattermost_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/mattermost-nginx.key"
```
-where `mattermost-nginx.crt` and `mattermost-nginx.key` are SSL cert and key, respectively.
+where `mattermost-nginx.crt` is the SSL certificate and `mattermost-nginx.key` is the SSL key.
Once the configuration is set, run `sudo gitlab-ctl reconfigure` to apply the changes.
diff --git a/doc/integration/salesforce.md b/doc/integration/salesforce.md
index 5300018e888..70d6e0aa0d8 100644
--- a/doc/integration/salesforce.md
+++ b/doc/integration/salesforce.md
@@ -81,9 +81,10 @@ To get the credentials (a pair of Client ID and Client Secret), you must [create
![Salesforce App Secret Details](img/salesforce_app_secret_details.png)
1. Save the configuration file.
-1. [Reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or
- [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes
- to take effect if you installed GitLab via Omnibus or from source respectively.
+
+1. For the changes to take effect:
+ - If you installed via Omnibus, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
+ - If you installed from source, [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
On the sign in page, there should now be a Salesforce icon below the regular sign in form.
Select the icon to begin the authentication process. Salesforce asks the user to sign in and authorize the GitLab application.
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index 0c517d07f41..f484f4cbc02 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -143,7 +143,9 @@ as described in the section on [Security](#security). Otherwise, your users are
1. Change the value of `issuer` to a unique name, which identifies the application
to the IdP.
-1. For the changes to take effect, you must [reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab if you installed via Omnibus or [restart GitLab](../administration/restart_gitlab.md#installations-from-source) if you installed from source.
+1. For the changes to take effect:
+ - If you installed via Omnibus, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
+ - If you installed from source, [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
1. Register the GitLab SP in your SAML 2.0 IdP, using the application name specified
in `issuer`.
diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md
index 2218529a729..aa9014adc49 100644
--- a/doc/integration/twitter.md
+++ b/doc/integration/twitter.md
@@ -88,7 +88,8 @@ Twitter. Twitter generates a client ID and secret key for you to use.
1. Save the configuration file.
-1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect if you
- installed GitLab via Omnibus or from source respectively.
+1. For the changes to take effect:
+ - If you installed via Omnibus, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
+ - If you installed from source, [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
On the sign in page there should now be a Twitter icon below the regular sign in form. Select the icon to begin the authentication process. Twitter asks the user to sign in and authorize the GitLab application. If everything goes well the user is returned to GitLab and signed in.
diff --git a/doc/user/packages/container_registry/reduce_container_registry_storage.md b/doc/user/packages/container_registry/reduce_container_registry_storage.md
index 788e57b6410..f889f4836d9 100644
--- a/doc/user/packages/container_registry/reduce_container_registry_storage.md
+++ b/doc/user/packages/container_registry/reduce_container_registry_storage.md
@@ -219,7 +219,7 @@ Examples:
```shell
curl --request PUT --header 'Content-Type: application/json;charset=UTF-8' --header "PRIVATE-TOKEN: <your_access_token>" \
- --data-binary '{"container_expiration_policy_attributes":{"cadence":"1month","enabled":true,"keep_n":1,"older_than":"14d","name_regex":"","name_regex_delete":".*","name_regex_keep":".*-main"}}' \
+ --data-binary '{"container_expiration_policy_attributes":{"cadence":"1month","enabled":true,"keep_n":1,"older_than":"14d","name_regex":".*","name_regex_keep":".*-main"}}' \
"https://gitlab.example.com/api/v4/projects/2"
```
diff --git a/lib/api/concerns/packages/conan_endpoints.rb b/lib/api/concerns/packages/conan_endpoints.rb
index a90269b565c..d8c2eb4ff33 100644
--- a/lib/api/concerns/packages/conan_endpoints.rb
+++ b/lib/api/concerns/packages/conan_endpoints.rb
@@ -135,7 +135,7 @@ module API
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
get 'packages/:conan_package_reference', urgency: :low do
- authorize!(:read_package, project)
+ authorize_read_package!(project)
presenter = ::Packages::Conan::PackagePresenter.new(
package,
@@ -154,7 +154,7 @@ module API
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
get urgency: :low do
- authorize!(:read_package, project)
+ authorize_read_package!(project)
presenter = ::Packages::Conan::PackagePresenter.new(package, current_user, project)
@@ -237,7 +237,7 @@ module API
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
post 'packages/:conan_package_reference/upload_urls', urgency: :low do
- authorize!(:read_package, project)
+ authorize_read_package!(project)
status 200
present package_upload_urls, with: ::API::Entities::ConanPackage::ConanUploadUrls
@@ -250,7 +250,7 @@ module API
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
post 'upload_urls', urgency: :low do
- authorize!(:read_package, project)
+ authorize_read_package!(project)
status 200
present recipe_upload_urls, with: ::API::Entities::ConanPackage::ConanUploadUrls
diff --git a/lib/api/helpers/packages/conan/api_helpers.rb b/lib/api/helpers/packages/conan/api_helpers.rb
index 994d3c4c473..ba1c409317e 100644
--- a/lib/api/helpers/packages/conan/api_helpers.rb
+++ b/lib/api/helpers/packages/conan/api_helpers.rb
@@ -23,7 +23,7 @@ module API
end
def present_download_urls(entity)
- authorize!(:read_package, project)
+ authorize_read_package!(project)
presenter = ::Packages::Conan::PackagePresenter.new(
package,
@@ -161,7 +161,7 @@ module API
end
def download_package_file(file_type)
- authorize!(:read_package, project)
+ authorize_read_package!(project)
package_file = ::Packages::Conan::PackageFileFinder
.new(
diff --git a/lib/api/helpers/packages_helpers.rb b/lib/api/helpers/packages_helpers.rb
index 2221eec0f82..66c4c661454 100644
--- a/lib/api/helpers/packages_helpers.rb
+++ b/lib/api/helpers/packages_helpers.rb
@@ -14,7 +14,7 @@ module API
end
def authorize_read_package!(subject = user_project)
- authorize!(:read_package, subject)
+ authorize!(:read_package, subject.try(:packages_policy_subject) || subject)
end
def authorize_create_package!(subject = user_project)
diff --git a/lib/api/members.rb b/lib/api/members.rb
index d26fdd09ee7..f4e38207aca 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -24,6 +24,7 @@ module API
params do
optional :query, type: String, desc: 'A query string to search for members'
optional :user_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Array of user ids to look up for membership'
+ optional :skip_users, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Array of user ids to be skipped for membership'
optional :show_seat_info, type: Boolean, desc: 'Show seat information for members'
use :optional_filter_params_ee
use :pagination
diff --git a/lib/api/rubygem_packages.rb b/lib/api/rubygem_packages.rb
index 85bbd0879b7..85d6f0c5a9b 100644
--- a/lib/api/rubygem_packages.rb
+++ b/lib/api/rubygem_packages.rb
@@ -65,7 +65,7 @@ module API
requires :file_name, type: String, desc: 'Package file name'
end
get "gems/:file_name", requirements: FILE_NAME_REQUIREMENTS do
- authorize!(:read_package, user_project)
+ authorize_read_package!(user_project)
package_files = ::Packages::PackageFile
.for_rubygem_with_file_name(user_project, params[:file_name])
diff --git a/lib/gitlab/cache/import/caching.rb b/lib/gitlab/cache/import/caching.rb
index 87988279c8d..4dbce0b05e1 100644
--- a/lib/gitlab/cache/import/caching.rb
+++ b/lib/gitlab/cache/import/caching.rb
@@ -153,11 +153,11 @@ module Gitlab
# timeout - The time after which the cache key should expire.
def self.write_multiple(mapping, key_prefix: nil, timeout: TIMEOUT)
Redis::Cache.with do |redis|
- redis.pipelined do |pipeline|
+ redis.pipelined do |multi|
mapping.each do |raw_key, value|
key = cache_key_for("#{key_prefix}#{raw_key}")
- pipeline.set(key, value, ex: timeout)
+ multi.set(key, value, ex: timeout)
end
end
end
diff --git a/lib/sidebars/projects/menus/packages_registries_menu.rb b/lib/sidebars/projects/menus/packages_registries_menu.rb
index 914368e6fec..e4d4441c687 100644
--- a/lib/sidebars/projects/menus/packages_registries_menu.rb
+++ b/lib/sidebars/projects/menus/packages_registries_menu.rb
@@ -77,7 +77,8 @@ module Sidebars
end
def packages_registry_disabled?
- !::Gitlab.config.packages.enabled || !can?(context.current_user, :read_package, context.project)
+ !::Gitlab.config.packages.enabled ||
+ !can?(context.current_user, :read_package, context.project&.packages_policy_subject)
end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 637a56e8cb6..9bef7fa2c67 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -21572,6 +21572,9 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
+msgid "InviteMembersModal|Please select members or type email addresses to invite"
+msgstr ""
+
msgid "InviteMembersModal|Review the invite errors and try again:"
msgstr ""
@@ -42020,6 +42023,9 @@ msgstr ""
msgid "UsageQuota|CI/CD minutes usage since %{timeElapsed}"
msgstr ""
+msgid "UsageQuota|CI/CD minutes usage since %{usageSince}"
+msgstr ""
+
msgid "UsageQuota|Code packages and container images."
msgstr ""
@@ -42212,9 +42218,6 @@ msgstr ""
msgid "UsageQuota|Usage quotas help link"
msgstr ""
-msgid "UsageQuota|Usage since %{usageSince}"
-msgstr ""
-
msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
msgstr ""
diff --git a/spec/factories/ci/build_trace_chunks.rb b/spec/factories/ci/build_trace_chunks.rb
index 115eb32111c..64a297932de 100644
--- a/spec/factories/ci/build_trace_chunks.rb
+++ b/spec/factories/ci/build_trace_chunks.rb
@@ -23,7 +23,7 @@ FactoryBot.define do
end
trait :database_with_data do
- data_store { :database}
+ data_store { :database }
transient do
initial_data { 'test data' }
@@ -55,7 +55,7 @@ FactoryBot.define do
end
trait :persisted do
- data_store { :database}
+ data_store { :database }
transient do
initial_data { 'test data' }
diff --git a/spec/factories/ci/job_artifacts.rb b/spec/factories/ci/job_artifacts.rb
index 114ad3a5847..f9a3c176ef2 100644
--- a/spec/factories/ci/job_artifacts.rb
+++ b/spec/factories/ci/job_artifacts.rb
@@ -15,7 +15,7 @@ FactoryBot.define do
end
trait :remote_store do
- file_store { JobArtifactUploader::Store::REMOTE}
+ file_store { JobArtifactUploader::Store::REMOTE }
end
after :build do |artifact|
diff --git a/spec/factories/ci/pipeline_artifacts.rb b/spec/factories/ci/pipeline_artifacts.rb
index 85277ce6fbf..d096f149c3a 100644
--- a/spec/factories/ci/pipeline_artifacts.rb
+++ b/spec/factories/ci/pipeline_artifacts.rb
@@ -30,7 +30,7 @@ FactoryBot.define do
end
trait :remote_store do
- file_store { ::ObjectStorage::Store::REMOTE}
+ file_store { ::ObjectStorage::Store::REMOTE }
end
trait :with_coverage_report do
diff --git a/spec/factories/commit_statuses.rb b/spec/factories/commit_statuses.rb
index fa10b37cdbf..b41e30e214c 100644
--- a/spec/factories/commit_statuses.rb
+++ b/spec/factories/commit_statuses.rb
@@ -6,10 +6,10 @@ FactoryBot.define do
stage { 'test' }
stage_idx { 0 }
status { 'success' }
- description { 'commit status'}
+ description { 'commit status' }
pipeline factory: :ci_pipeline
- started_at { 'Tue, 26 Jan 2016 08:21:42 +0100'}
- finished_at { 'Tue, 26 Jan 2016 08:23:42 +0100'}
+ started_at { 'Tue, 26 Jan 2016 08:21:42 +0100' }
+ finished_at { 'Tue, 26 Jan 2016 08:23:42 +0100' }
trait :success do
status { 'success' }
diff --git a/spec/factories/emails.rb b/spec/factories/emails.rb
index b30fa8a5896..e51c3358a9b 100644
--- a/spec/factories/emails.rb
+++ b/spec/factories/emails.rb
@@ -6,6 +6,6 @@ FactoryBot.define do
email { generate(:email_alias) }
trait(:confirmed) { confirmed_at { Time.now } }
- trait(:skip_validate) { to_create {|instance| instance.save!(validate: false) } }
+ trait(:skip_validate) { to_create { |instance| instance.save!(validate: false) } }
end
end
diff --git a/spec/factories/external_pull_requests.rb b/spec/factories/external_pull_requests.rb
index 7a6e77f8572..470814f4360 100644
--- a/spec/factories/external_pull_requests.rb
+++ b/spec/factories/external_pull_requests.rb
@@ -12,6 +12,6 @@ FactoryBot.define do
target_sha { 'a09386439ca39abe575675ffd4b89ae824fec22f' }
status { :open }
- trait(:closed) { status { 'closed'} }
+ trait(:closed) { status { 'closed' } }
end
end
diff --git a/spec/factories/gitlab/database/postgres_index.rb b/spec/factories/gitlab/database/postgres_index.rb
index 54bbb738512..8492b44c404 100644
--- a/spec/factories/gitlab/database/postgres_index.rb
+++ b/spec/factories/gitlab/database/postgres_index.rb
@@ -13,7 +13,7 @@ FactoryBot.define do
exclusion { false }
expression { false }
partial { false }
- definition { "CREATE INDEX #{identifier} ON #{tablename} (bar)"}
+ definition { "CREATE INDEX #{identifier} ON #{tablename} (bar)" }
ondisk_size_bytes { 100.megabytes }
end
end
diff --git a/spec/factories/packages/dependencies.rb b/spec/factories/packages/dependencies.rb
index a62d48c2e73..c99f11d6db3 100644
--- a/spec/factories/packages/dependencies.rb
+++ b/spec/factories/packages/dependencies.rb
@@ -2,11 +2,11 @@
FactoryBot.define do
factory :packages_dependency, class: 'Packages::Dependency' do
- sequence(:name) { |n| "@test/package-#{n}"}
+ sequence(:name) { |n| "@test/package-#{n}" }
sequence(:version_pattern) { |n| "~6.2.#{n}" }
trait(:rubygems) do
- sequence(:name) { |n| "gem-dependency-#{n}"}
+ sequence(:name) { |n| "gem-dependency-#{n}" }
end
end
end
diff --git a/spec/factories/packages/package_tags.rb b/spec/factories/packages/package_tags.rb
index 3d2eea4a73b..1a40d5d600f 100644
--- a/spec/factories/packages/package_tags.rb
+++ b/spec/factories/packages/package_tags.rb
@@ -3,6 +3,6 @@
FactoryBot.define do
factory :packages_tag, class: 'Packages::Tag' do
package
- sequence(:name) { |n| "tag-#{n}"}
+ sequence(:name) { |n| "tag-#{n}" }
end
end
diff --git a/spec/factories/packages/packages.rb b/spec/factories/packages/packages.rb
index 90c68074a3b..3d5bdc95722 100644
--- a/spec/factories/packages/packages.rb
+++ b/spec/factories/packages/packages.rb
@@ -115,7 +115,7 @@ FactoryBot.define do
end
factory :npm_package do
- sequence(:name) { |n| "@#{project.root_namespace.path}/package-#{n}"}
+ sequence(:name) { |n| "@#{project.root_namespace.path}/package-#{n}" }
sequence(:version) { |n| "1.0.#{n}" }
package_type { :npm }
@@ -153,7 +153,7 @@ FactoryBot.define do
end
factory :nuget_package do
- sequence(:name) { |n| "NugetPackage#{n}"}
+ sequence(:name) { |n| "NugetPackage#{n}" }
sequence(:version) { |n| "1.0.#{n}" }
package_type { :nuget }
@@ -175,7 +175,7 @@ FactoryBot.define do
end
factory :pypi_package do
- sequence(:name) { |n| "pypi-package-#{n}"}
+ sequence(:name) { |n| "pypi-package-#{n}" }
sequence(:version) { |n| "1.0.#{n}" }
package_type { :pypi }
@@ -193,7 +193,7 @@ FactoryBot.define do
end
factory :composer_package do
- sequence(:name) { |n| "composer-package-#{n}"}
+ sequence(:name) { |n| "composer-package-#{n}" }
sequence(:version) { |n| "1.0.#{n}" }
package_type { :composer }
@@ -210,7 +210,7 @@ FactoryBot.define do
end
factory :golang_package do
- sequence(:name) { |n| "golang.org/x/pkg-#{n}"}
+ sequence(:name) { |n| "golang.org/x/pkg-#{n}" }
sequence(:version) { |n| "v1.0.#{n}" }
package_type { :golang }
end
diff --git a/spec/factories/prometheus_alert.rb b/spec/factories/prometheus_alert.rb
index ad3868c38ed..14fdd993c7a 100644
--- a/spec/factories/prometheus_alert.rb
+++ b/spec/factories/prometheus_alert.rb
@@ -15,7 +15,7 @@ FactoryBot.define do
end
trait :with_runbook_url do
- runbook_url { 'https://runbooks.gitlab.com/metric_gt_1'}
+ runbook_url { 'https://runbooks.gitlab.com/metric_gt_1' }
end
end
end
diff --git a/spec/factories/prometheus_metrics.rb b/spec/factories/prometheus_metrics.rb
index 503d392a524..e785bf2ac9d 100644
--- a/spec/factories/prometheus_metrics.rb
+++ b/spec/factories/prometheus_metrics.rb
@@ -9,7 +9,7 @@ FactoryBot.define do
group { :business }
project
legend { 'legend' }
- dashboard_path { '.gitlab/dashboards/dashboard_path.yml'}
+ dashboard_path { '.gitlab/dashboards/dashboard_path.yml' }
trait :common do
common { true }
diff --git a/spec/frontend/fixtures/api_merge_requests.rb b/spec/frontend/fixtures/api_merge_requests.rb
index 75bc8c8df25..7d95c506e6c 100644
--- a/spec/frontend/fixtures/api_merge_requests.rb
+++ b/spec/frontend/fixtures/api_merge_requests.rb
@@ -7,7 +7,7 @@ RSpec.describe API::MergeRequests, '(JavaScript fixtures)', type: :request do
include JavaScriptFixturesHelpers
let_it_be(:admin) { create(:admin, name: 'root') }
- let_it_be(:namespace) { create(:namespace, name: 'gitlab-test' )}
+ let_it_be(:namespace) { create(:namespace, name: 'gitlab-test' ) }
let_it_be(:project) { create(:project, :repository, namespace: namespace, path: 'lorem-ipsum') }
let_it_be(:early_mrs) do
4.times { |i| create(:merge_request, source_project: project, source_branch: "branch-#{i}") }
diff --git a/spec/frontend/fixtures/api_projects.rb b/spec/frontend/fixtures/api_projects.rb
index eada2f8e0f7..5acc1095d5c 100644
--- a/spec/frontend/fixtures/api_projects.rb
+++ b/spec/frontend/fixtures/api_projects.rb
@@ -7,7 +7,7 @@ RSpec.describe API::Projects, '(JavaScript fixtures)', type: :request do
include JavaScriptFixturesHelpers
let(:admin) { create(:admin, name: 'root') }
- let(:namespace) { create(:namespace, name: 'gitlab-test' )}
+ let(:namespace) { create(:namespace, name: 'gitlab-test' ) }
let(:project) { create(:project, :repository, namespace: namespace, path: 'lorem-ipsum') }
let(:project_empty) { create(:project_empty_repo, namespace: namespace, path: 'lorem-ipsum-empty') }
diff --git a/spec/frontend/fixtures/application_settings.rb b/spec/frontend/fixtures/application_settings.rb
index a7a989f31ec..b3ce23c8cd7 100644
--- a/spec/frontend/fixtures/application_settings.rb
+++ b/spec/frontend/fixtures/application_settings.rb
@@ -8,7 +8,7 @@ RSpec.describe Admin::ApplicationSettingsController, '(JavaScript fixtures)', ty
include AdminModeHelper
let(:admin) { create(:admin) }
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project_empty_repo, namespace: namespace, path: 'application-settings') }
before do
diff --git a/spec/frontend/fixtures/blob.rb b/spec/frontend/fixtures/blob.rb
index b2bbdd2749e..54c5b83da3e 100644
--- a/spec/frontend/fixtures/blob.rb
+++ b/spec/frontend/fixtures/blob.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::BlobController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project, :repository, namespace: namespace, path: 'branches-project') }
let(:user) { project.first_owner }
diff --git a/spec/frontend/fixtures/branches.rb b/spec/frontend/fixtures/branches.rb
index b3bb4b8873a..6cda2f0f665 100644
--- a/spec/frontend/fixtures/branches.rb
+++ b/spec/frontend/fixtures/branches.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Branches (JavaScript fixtures)' do
include JavaScriptFixturesHelpers
- let_it_be(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let_it_be(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let_it_be(:project) { create(:project, :repository, namespace: namespace, path: 'branches-project') }
let_it_be(:user) { project.first_owner }
diff --git a/spec/frontend/fixtures/clusters.rb b/spec/frontend/fixtures/clusters.rb
index 49596d98774..426a76f29e0 100644
--- a/spec/frontend/fixtures/clusters.rb
+++ b/spec/frontend/fixtures/clusters.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::ClustersController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project, :repository, namespace: namespace) }
let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
let(:user) { project.first_owner }
diff --git a/spec/frontend/fixtures/deploy_keys.rb b/spec/frontend/fixtures/deploy_keys.rb
index 154084e0181..24d602216d8 100644
--- a/spec/frontend/fixtures/deploy_keys.rb
+++ b/spec/frontend/fixtures/deploy_keys.rb
@@ -7,11 +7,11 @@ RSpec.describe Projects::DeployKeysController, '(JavaScript fixtures)', type: :c
include AdminModeHelper
let(:admin) { create(:admin) }
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project_empty_repo, namespace: namespace, path: 'todos-project') }
- let(:project2) { create(:project, :internal)}
- let(:project3) { create(:project, :internal)}
- let(:project4) { create(:project, :internal)}
+ let(:project2) { create(:project, :internal) }
+ let(:project3) { create(:project, :internal) }
+ let(:project4) { create(:project, :internal) }
before do
# Using an admin for these fixtures because they are used for verifying a frontend
diff --git a/spec/frontend/fixtures/groups.rb b/spec/frontend/fixtures/groups.rb
index ddd436b98c6..9c22ff176ff 100644
--- a/spec/frontend/fixtures/groups.rb
+++ b/spec/frontend/fixtures/groups.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Groups (JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
let(:user) { create(:user) }
- let(:group) { create(:group, name: 'frontend-fixtures-group', runners_token: 'runnerstoken:intabulasreferre')}
+ let(:group) { create(:group, name: 'frontend-fixtures-group', runners_token: 'runnerstoken:intabulasreferre') }
before do
group.add_owner(user)
diff --git a/spec/frontend/fixtures/issues.rb b/spec/frontend/fixtures/issues.rb
index cde796497d4..e3d88098841 100644
--- a/spec/frontend/fixtures/issues.rb
+++ b/spec/frontend/fixtures/issues.rb
@@ -6,7 +6,7 @@ RSpec.describe Projects::IssuesController, '(JavaScript fixtures)', type: :contr
include JavaScriptFixturesHelpers
let(:user) { create(:user, feed_token: 'feedtoken:coldfeed') }
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project_empty_repo, namespace: namespace, path: 'issues-project') }
render_views
diff --git a/spec/frontend/fixtures/jobs.rb b/spec/frontend/fixtures/jobs.rb
index 2e15eefdce6..3657a5405a4 100644
--- a/spec/frontend/fixtures/jobs.rb
+++ b/spec/frontend/fixtures/jobs.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Jobs (JavaScript fixtures)' do
include JavaScriptFixturesHelpers
include GraphqlHelpers
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project, :repository, namespace: namespace, path: 'builds-project') }
let(:user) { project.first_owner }
let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.id) }
diff --git a/spec/frontend/fixtures/labels.rb b/spec/frontend/fixtures/labels.rb
index 6736baed199..2445c9376e2 100644
--- a/spec/frontend/fixtures/labels.rb
+++ b/spec/frontend/fixtures/labels.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Labels (JavaScript fixtures)' do
include JavaScriptFixturesHelpers
let(:user) { create(:user) }
- let(:group) { create(:group, name: 'frontend-fixtures-group' )}
+ let(:group) { create(:group, name: 'frontend-fixtures-group' ) }
let(:project) { create(:project_empty_repo, namespace: group, path: 'labels-project') }
let!(:project_label_bug) { create(:label, project: project, title: 'bug', color: '#FF0000') }
diff --git a/spec/frontend/fixtures/merge_requests.rb b/spec/frontend/fixtures/merge_requests.rb
index cb4eb43b88d..cbf26a70e5f 100644
--- a/spec/frontend/fixtures/merge_requests.rb
+++ b/spec/frontend/fixtures/merge_requests.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project, :repository, namespace: namespace, path: 'merge-requests-project') }
let(:user) { project.first_owner }
diff --git a/spec/frontend/fixtures/merge_requests_diffs.rb b/spec/frontend/fixtures/merge_requests_diffs.rb
index 7f0d650b710..ff4b27844a6 100644
--- a/spec/frontend/fixtures/merge_requests_diffs.rb
+++ b/spec/frontend/fixtures/merge_requests_diffs.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project, :repository, namespace: namespace, path: 'merge-requests-project') }
let(:user) { project.first_owner }
let(:merge_request) { create(:merge_request, source_project: project, target_project: project, description: '- [ ] Task List Item') }
diff --git a/spec/frontend/fixtures/metrics_dashboard.rb b/spec/frontend/fixtures/metrics_dashboard.rb
index d59b01b04af..7f8b3d378d3 100644
--- a/spec/frontend/fixtures/metrics_dashboard.rb
+++ b/spec/frontend/fixtures/metrics_dashboard.rb
@@ -7,7 +7,7 @@ RSpec.describe MetricsDashboard, '(JavaScript fixtures)', type: :controller do
include MetricsDashboardHelpers
let_it_be(:user) { create(:user) }
- let_it_be(:namespace) { create(:namespace, name: 'monitoring' )}
+ let_it_be(:namespace) { create(:namespace, name: 'monitoring' ) }
let_it_be(:project) { project_with_dashboard_namespace('.gitlab/dashboards/test.yml', nil, namespace: namespace) }
let_it_be(:environment) { create(:environment, id: 1, project: project) }
let_it_be(:params) { { environment: environment } }
diff --git a/spec/frontend/fixtures/pipeline_schedules.rb b/spec/frontend/fixtures/pipeline_schedules.rb
index e155d27920d..5b7a445557e 100644
--- a/spec/frontend/fixtures/pipeline_schedules.rb
+++ b/spec/frontend/fixtures/pipeline_schedules.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project, :public, :repository) }
let(:user) { project.first_owner }
let!(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: user) }
diff --git a/spec/frontend/fixtures/pipelines.rb b/spec/frontend/fixtures/pipelines.rb
index 709e14183df..114db26d6a9 100644
--- a/spec/frontend/fixtures/pipelines.rb
+++ b/spec/frontend/fixtures/pipelines.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::PipelinesController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
- let_it_be(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let_it_be(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let_it_be(:project) { create(:project, :repository, namespace: namespace, path: 'pipelines-project') }
let_it_be(:commit_without_author) { RepoHelpers.another_sample_commit }
diff --git a/spec/frontend/fixtures/projects.rb b/spec/frontend/fixtures/projects.rb
index fa7d61df3e8..b9c427c7505 100644
--- a/spec/frontend/fixtures/projects.rb
+++ b/spec/frontend/fixtures/projects.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Projects (JavaScript fixtures)', type: :controller do
runners_token = 'runnerstoken:intabulasreferre'
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project, namespace: namespace, path: 'builds-project', runners_token: runners_token, avatar: fixture_file_upload('spec/fixtures/dk.png', 'image/png')) }
let(:project_with_repo) { create(:project, :repository, description: 'Code and stuff', avatar: fixture_file_upload('spec/fixtures/dk.png', 'image/png')) }
let(:project_variable_populated) { create(:project, namespace: namespace, path: 'builds-project2', runners_token: runners_token) }
diff --git a/spec/frontend/fixtures/raw.rb b/spec/frontend/fixtures/raw.rb
index b117cfea5fa..7bd5b8c5f6c 100644
--- a/spec/frontend/fixtures/raw.rb
+++ b/spec/frontend/fixtures/raw.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Raw files', '(JavaScript fixtures)' do
include JavaScriptFixturesHelpers
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project, :repository, namespace: namespace, path: 'raw-project') }
let(:response) { @response }
diff --git a/spec/frontend/fixtures/snippet.rb b/spec/frontend/fixtures/snippet.rb
index f05ff3ee269..58d4bc5c1f3 100644
--- a/spec/frontend/fixtures/snippet.rb
+++ b/spec/frontend/fixtures/snippet.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe SnippetsController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project, :repository, namespace: namespace, path: 'branches-project') }
let(:user) { project.first_owner }
let(:snippet) { create(:personal_snippet, :public, title: 'snippet.md', content: '# snippet', file_name: 'snippet.md', author: user) }
diff --git a/spec/frontend/fixtures/todos.rb b/spec/frontend/fixtures/todos.rb
index 7dce09e8f49..d934396f803 100644
--- a/spec/frontend/fixtures/todos.rb
+++ b/spec/frontend/fixtures/todos.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Todos (JavaScript fixtures)' do
include JavaScriptFixturesHelpers
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project_empty_repo, namespace: namespace, path: 'todos-project') }
let(:user) { project.first_owner }
let(:issue_1) { create(:issue, title: 'issue_1', project: project) }
diff --git a/spec/frontend/invite_members/components/invite_members_modal_spec.js b/spec/frontend/invite_members/components/invite_members_modal_spec.js
index 2058784b033..e9e1fbad07b 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -19,6 +19,7 @@ import {
MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT,
LEARN_GITLAB,
EXPANDED_ERRORS,
+ EMPTY_INVITES_ERROR_TEXT,
} from '~/invite_members/constants';
import eventHub from '~/invite_members/event_hub';
import ContentTransition from '~/vue_shared/components/content_transition.vue';
@@ -255,6 +256,8 @@ describe('InviteMembersModal', () => {
it('tracks the submit for invite_members_for_task', async () => {
await setupComponentWithTasks();
+ await triggerMembersTokenSelect([user1]);
+
clickInviteButton();
expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name, {
@@ -265,6 +268,16 @@ describe('InviteMembersModal', () => {
INVITE_MEMBERS_FOR_TASK.submit,
);
});
+
+ it('does not track the submit for invite_members_for_task when invites have not been entered', async () => {
+ await setupComponentWithTasks();
+ clickInviteButton();
+
+ expect(ExperimentTracking).not.toHaveBeenCalledWith(
+ INVITE_MEMBERS_FOR_TASK.name,
+ expect.any,
+ );
+ });
});
});
@@ -380,6 +393,25 @@ describe('InviteMembersModal', () => {
"The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups.";
const expectedSyntaxError = 'email contains an invalid email address';
+ describe('when no invites have been entered in the form and then some are entered', () => {
+ beforeEach(async () => {
+ createInviteMembersToGroupWrapper();
+ });
+
+ it('displays an error', async () => {
+ clickInviteButton();
+
+ await waitForPromises();
+
+ expect(membersFormGroupInvalidFeedback()).toBe(EMPTY_INVITES_ERROR_TEXT);
+ expect(findMembersSelect().props('exceptionState')).toBe(false);
+
+ await triggerMembersTokenSelect([user1]);
+
+ expect(membersFormGroupInvalidFeedback()).toBe('');
+ });
+ });
+
describe('when inviting an existing user to group by user ID', () => {
const postData = {
user_id: '1,2',
diff --git a/spec/lib/api/helpers/packages_helpers_spec.rb b/spec/lib/api/helpers/packages_helpers_spec.rb
index 0c51e25bad9..69303a12d43 100644
--- a/spec/lib/api/helpers/packages_helpers_spec.rb
+++ b/spec/lib/api/helpers/packages_helpers_spec.rb
@@ -5,6 +5,8 @@ require 'spec_helper'
RSpec.describe API::Helpers::PackagesHelpers do
let_it_be(:helper) { Class.new.include(described_class).new }
let_it_be(:project) { create(:project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:package) { create(:package) }
describe 'authorize_packages_access!' do
subject { helper.authorize_packages_access!(project) }
@@ -17,7 +19,45 @@ RSpec.describe API::Helpers::PackagesHelpers do
end
end
- %i[read_package create_package destroy_package].each do |action|
+ describe 'authorize_read_package!' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:subject, :expected_class) do
+ ref(:project) | ::Packages::Policies::Project
+ ref(:group) | ::Packages::Policies::Group
+ ref(:package) | ::Packages::Package
+ end
+
+ with_them do
+ it 'calls authorize! with correct subject' do
+ expect(helper).to receive(:authorize!).with(:read_package, have_attributes(id: subject.id, class: expected_class))
+
+ expect(helper.send('authorize_read_package!', subject)).to eq nil
+ end
+ end
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(read_package_policy_rule: false)
+ end
+
+ where(:subject, :expected_class) do
+ ref(:project) | ::Project
+ ref(:group) | ::Group
+ ref(:package) | ::Packages::Package
+ end
+
+ with_them do
+ it 'calls authorize! with correct subject' do
+ expect(helper).to receive(:authorize!).with(:read_package, have_attributes(id: subject.id, class: expected_class))
+
+ expect(helper.send('authorize_read_package!', subject)).to eq nil
+ end
+ end
+ end
+ end
+
+ %i[create_package destroy_package].each do |action|
describe "authorize_#{action}!" do
subject { helper.send("authorize_#{action}!", project) }
diff --git a/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
index 9b78fc807bf..f24c40cfe89 100644
--- a/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
+++ b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb
@@ -65,7 +65,7 @@ RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu do
describe 'Packages Registry' do
let(:item_id) { :packages_registry }
- context 'when user can read packages' do
+ shared_examples 'when user can read packages' do
context 'when config package setting is disabled' do
it 'the menu item is not added to list of menu items' do
stub_config(packages: { enabled: false })
@@ -83,13 +83,25 @@ RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu do
end
end
- context 'when user cannot read packages' do
+ shared_examples 'when user cannot read packages' do
let(:user) { nil }
it 'the menu item is not added to list of menu items' do
is_expected.to be_nil
end
end
+
+ it_behaves_like 'when user can read packages'
+ it_behaves_like 'when user cannot read packages'
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(read_package_policy_rule: false)
+ end
+
+ it_behaves_like 'when user can read packages'
+ it_behaves_like 'when user cannot read packages'
+ end
end
describe 'Container Registry' do
diff --git a/spec/models/concerns/pg_full_text_searchable_spec.rb b/spec/models/concerns/pg_full_text_searchable_spec.rb
index 55e3caf3c4c..3e42a3504ac 100644
--- a/spec/models/concerns/pg_full_text_searchable_spec.rb
+++ b/spec/models/concerns/pg_full_text_searchable_spec.rb
@@ -96,6 +96,7 @@ RSpec.describe PgFullTextSearchable do
it 'ignores accents' do
expect(model_class.pg_full_text_search('jurgen')).to contain_exactly(with_accent)
+ expect(model_class.pg_full_text_search('Jürgen')).to contain_exactly(with_accent)
end
it 'does not support searching by non-Latin characters' do
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 61662411ac8..a36b656a864 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -3465,6 +3465,23 @@ RSpec.describe Group do
end
end
+ describe '#packages_policy_subject' do
+ it 'returns wrapper' do
+ expect(group.packages_policy_subject).to be_a(Packages::Policies::Group)
+ expect(group.packages_policy_subject.group).to eq(group)
+ end
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(read_package_policy_rule: false)
+ end
+
+ it 'returns group' do
+ expect(group.packages_policy_subject).to eq(group)
+ end
+ end
+ end
+
describe '#gitlab_deploy_token' do
subject(:gitlab_deploy_token) { group.gitlab_deploy_token }
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 49d6ff97894..f4628844eaf 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -8450,6 +8450,25 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#packages_policy_subject' do
+ let_it_be(:project) { create(:project) }
+
+ it 'returns wrapper' do
+ expect(project.packages_policy_subject).to be_a(Packages::Policies::Project)
+ expect(project.packages_policy_subject.project).to eq(project)
+ end
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(read_package_policy_rule: false)
+ end
+
+ it 'returns project' do
+ expect(project.packages_policy_subject).to eq(project)
+ end
+ end
+ end
+
describe '#destroy_deployment_by_id' do
let(:project) { create(:project, :repository) }
diff --git a/spec/policies/packages/policies/group_policy_spec.rb b/spec/policies/packages/policies/group_policy_spec.rb
new file mode 100644
index 00000000000..d0d9a9a22f5
--- /dev/null
+++ b/spec/policies/packages/policies/group_policy_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Policies::GroupPolicy do
+ include_context 'GroupPolicy context'
+
+ subject { described_class.new(current_user, group.packages_policy_subject) }
+
+ describe 'read_package' do
+ context 'with admin' do
+ let(:current_user) { admin }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'when admin mode is disabled' do
+ it { is_expected.to be_disallowed(:read_package) }
+ end
+ end
+
+ context 'with owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'with maintainer' do
+ let(:current_user) { maintainer }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'with reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'with guest' do
+ let(:current_user) { guest }
+
+ it { is_expected.to be_disallowed(:read_package) }
+ end
+
+ context 'with non member' do
+ let(:current_user) { create(:user) }
+
+ it { is_expected.to be_disallowed(:read_package) }
+ end
+
+ context 'with anonymous' do
+ let(:current_user) { nil }
+
+ it { is_expected.to be_disallowed(:read_package) }
+ end
+ end
+
+ describe 'deploy token access' do
+ let!(:group_deploy_token) do
+ create(:group_deploy_token, group: group, deploy_token: deploy_token)
+ end
+
+ subject { described_class.new(deploy_token, group.packages_policy_subject) }
+
+ context 'when a deploy token with read_package_registry scope' do
+ let(:deploy_token) { create(:deploy_token, :group, read_package_registry: true) }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'when a deploy token with write_package_registry scope' do
+ let(:deploy_token) { create(:deploy_token, :group, write_package_registry: true) }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+ end
+end
diff --git a/spec/policies/packages/policies/project_policy_spec.rb b/spec/policies/packages/policies/project_policy_spec.rb
new file mode 100644
index 00000000000..15c5942ea4d
--- /dev/null
+++ b/spec/policies/packages/policies/project_policy_spec.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::Policies::ProjectPolicy do
+ include_context 'ProjectPolicy context'
+
+ let(:project) { public_project }
+
+ subject { described_class.new(current_user, project.packages_policy_subject) }
+
+ describe 'deploy token access' do
+ let!(:project_deploy_token) do
+ create(:project_deploy_token, project: project, deploy_token: deploy_token)
+ end
+
+ subject { described_class.new(deploy_token, project.packages_policy_subject) }
+
+ context 'when a deploy token with read_package_registry scope' do
+ let(:deploy_token) { create(:deploy_token, read_package_registry: true) }
+
+ it { is_expected.to be_allowed(:read_package) }
+
+ it_behaves_like 'package access with repository disabled'
+ end
+
+ context 'when a deploy token with write_package_registry scope' do
+ let(:deploy_token) { create(:deploy_token, write_package_registry: true) }
+
+ it { is_expected.to be_allowed(:read_package) }
+
+ it_behaves_like 'package access with repository disabled'
+ end
+ end
+
+ describe 'read_package' do
+ context 'with admin' do
+ let(:current_user) { admin }
+
+ it { is_expected.to be_allowed(:read_package) }
+
+ it_behaves_like 'package access with repository disabled'
+ end
+
+ context 'with owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'with maintainer' do
+ let(:current_user) { maintainer }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'with developer' do
+ let(:current_user) { developer }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'with reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'with guest' do
+ let(:current_user) { guest }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'with non member' do
+ let(:current_user) { non_member }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+
+ context 'with anonymous' do
+ let(:current_user) { anonymous }
+
+ it { is_expected.to be_allowed(:read_package) }
+ end
+ end
+end
diff --git a/spec/support/helpers/cycle_analytics_helpers.rb b/spec/support/helpers/cycle_analytics_helpers.rb
index 05e9a099a2b..6d41d7b7414 100644
--- a/spec/support/helpers/cycle_analytics_helpers.rb
+++ b/spec/support/helpers/cycle_analytics_helpers.rb
@@ -7,7 +7,7 @@ module CycleAnalyticsHelpers
def path_nav_stage_names_without_median
# Returns the path names with the median value stripped out
- page.all('.gl-path-button').collect(&:text).map {|name_with_median| name_with_median.split("\n")[0] }
+ page.all('.gl-path-button').collect(&:text).map { |name_with_median| name_with_median.split("\n")[0] }
end
def fill_in_custom_stage_fields
diff --git a/spec/support/redis/redis_shared_examples.rb b/spec/support/redis/redis_shared_examples.rb
index d4c8682ec71..33945509675 100644
--- a/spec/support/redis/redis_shared_examples.rb
+++ b/spec/support/redis/redis_shared_examples.rb
@@ -3,19 +3,19 @@
RSpec.shared_examples "redis_shared_examples" do
include StubENV
- let(:test_redis_url) { "redis://redishost:#{redis_port}"}
+ let(:test_redis_url) { "redis://redishost:#{redis_port}" }
let(:config_file_name) { instance_specific_config_file }
let(:config_old_format_socket) { "spec/fixtures/config/redis_old_format_socket.yml" }
let(:config_new_format_socket) { "spec/fixtures/config/redis_new_format_socket.yml" }
- let(:old_socket_path) {"/path/to/old/redis.sock" }
- let(:new_socket_path) {"/path/to/redis.sock" }
+ let(:old_socket_path) { "/path/to/old/redis.sock" }
+ let(:new_socket_path) { "/path/to/redis.sock" }
let(:config_old_format_host) { "spec/fixtures/config/redis_old_format_host.yml" }
let(:config_new_format_host) { "spec/fixtures/config/redis_new_format_host.yml" }
let(:redis_port) { 6379 }
let(:redis_database) { 99 }
let(:sentinel_port) { 26379 }
- let(:config_with_environment_variable_inside) { "spec/fixtures/config/redis_config_with_env.yml"}
- let(:config_env_variable_url) {"TEST_GITLAB_REDIS_URL"}
+ let(:config_with_environment_variable_inside) { "spec/fixtures/config/redis_config_with_env.yml" }
+ let(:config_env_variable_url) { "TEST_GITLAB_REDIS_URL" }
let(:rails_root) { Dir.mktmpdir('redis_shared_examples') }
before do
diff --git a/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb b/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb
index b29a231f3a6..d7cfdc09732 100644
--- a/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb
+++ b/spec/support/shared_contexts/graphql/requests/packages_shared_context.rb
@@ -16,8 +16,8 @@ RSpec.shared_context 'package details setup' do
let(:metadata_response) { graphql_data_at(:package, :metadata) }
let(:first_file) { package.package_files.find { |f| a_graphql_entity_for(f).matches?(first_file_response) } }
let(:package_files_response) { graphql_data_at(:package, :package_files, :nodes) }
- let(:first_file_response) { graphql_data_at(:package, :package_files, :nodes, 0)}
- let(:first_file_response_metadata) { graphql_data_at(:package, :package_files, :nodes, 0, :file_metadata)}
+ let(:first_file_response) { graphql_data_at(:package, :package_files, :nodes, 0) }
+ let(:first_file_response_metadata) { graphql_data_at(:package, :package_files, :nodes, 0, :file_metadata) }
let(:query) do
graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
diff --git a/spec/support/shared_contexts/markdown_golden_master_shared_examples.rb b/spec/support/shared_contexts/markdown_golden_master_shared_examples.rb
index dea03af2248..168aef0f174 100644
--- a/spec/support/shared_contexts/markdown_golden_master_shared_examples.rb
+++ b/spec/support/shared_contexts/markdown_golden_master_shared_examples.rb
@@ -42,7 +42,7 @@ RSpec.shared_context 'API::Markdown Golden Master shared context' do |markdown_y
if focused_markdown_examples_string = ENV['FOCUSED_MARKDOWN_EXAMPLES']
focused_markdown_examples = focused_markdown_examples_string.split(',').map(&:strip) || []
- markdown_examples.reject! {|markdown_example| !focused_markdown_examples.include?(markdown_example.fetch(:name)) }
+ markdown_examples.reject! { |markdown_example| !focused_markdown_examples.include?(markdown_example.fetch(:name)) }
end
markdown_examples.each do |markdown_example|
diff --git a/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb b/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
index b90270356f8..3974338238a 100644
--- a/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
+++ b/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
@@ -64,5 +64,5 @@ RSpec.shared_context 'conan file upload endpoints' do
let(:jwt) { build_jwt(personal_access_token) }
let(:headers_with_token) { build_token_auth_header(jwt.encoded).merge(workhorse_headers) }
- let(:recipe_path) { "foo/bar/#{project.full_path.tr('/', '+')}/baz"}
+ let(:recipe_path) { "foo/bar/#{project.full_path.tr('/', '+')}/baz" }
end
diff --git a/spec/support/shared_examples/controllers/error_tracking_shared_examples.rb b/spec/support/shared_examples/controllers/error_tracking_shared_examples.rb
index 08e5efcf63c..1bf2f158504 100644
--- a/spec/support/shared_examples/controllers/error_tracking_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/error_tracking_shared_examples.rb
@@ -3,5 +3,5 @@
RSpec.shared_examples 'sets the polling header' do
subject { response.headers[Gitlab::PollingInterval::HEADER_NAME] }
- it { is_expected.to eq '1000'}
+ it { is_expected.to eq '1000' }
end
diff --git a/spec/support/shared_examples/controllers/snippets_sort_order_shared_examples.rb b/spec/support/shared_examples/controllers/snippets_sort_order_shared_examples.rb
index aa4d78b23f4..112b9cbb204 100644
--- a/spec/support/shared_examples/controllers/snippets_sort_order_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/snippets_sort_order_shared_examples.rb
@@ -3,7 +3,7 @@
RSpec.shared_examples 'snippets sort order' do
let(:params) { {} }
let(:sort_argument) { {} }
- let(:sort_params) { params.merge(sort_argument)}
+ let(:sort_params) { params.merge(sort_argument) }
before do
sign_in(user)
diff --git a/spec/support/shared_examples/features/board_sidebar_labels_examples.rb b/spec/support/shared_examples/features/board_sidebar_labels_examples.rb
index 520980c2615..4e5b371c18d 100644
--- a/spec/support/shared_examples/features/board_sidebar_labels_examples.rb
+++ b/spec/support/shared_examples/features/board_sidebar_labels_examples.rb
@@ -17,7 +17,7 @@ RSpec.shared_context 'labels from nested groups and projects' do
let_it_be(:maintainer) { create(:user) }
let(:labels_select) { find("[data-testid='sidebar-labels']") }
- let(:labels_dropdown) { labels_select.find('[data-testid="dropdown-content"]')}
+ let(:labels_dropdown) { labels_select.find('[data-testid="dropdown-content"]') }
before do
group.add_maintainer(maintainer)
diff --git a/spec/support/shared_examples/features/snippets_shared_examples.rb b/spec/support/shared_examples/features/snippets_shared_examples.rb
index c402333107c..bf870b3ce66 100644
--- a/spec/support/shared_examples/features/snippets_shared_examples.rb
+++ b/spec/support/shared_examples/features/snippets_shared_examples.rb
@@ -194,7 +194,7 @@ end
RSpec.shared_examples 'personal snippet with references' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:merge_request) { create(:merge_request, source_project: project) }
- let_it_be(:project_snippet) { create(:project_snippet, :repository, project: project)}
+ let_it_be(:project_snippet) { create(:project_snippet, :repository, project: project) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:commit) { project.commit }
diff --git a/spec/support/shared_examples/features/wiki/user_views_asciidoc_page_with_includes_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_asciidoc_page_with_includes_shared_examples.rb
index 6fdc5ecae73..91bd7c6cb29 100644
--- a/spec/support/shared_examples/features/wiki/user_views_asciidoc_page_with_includes_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_views_asciidoc_page_with_includes_shared_examples.rb
@@ -2,7 +2,7 @@
RSpec.shared_examples 'User views AsciiDoc page with includes' do
let_it_be(:wiki_content_selector) { '[data-qa-selector=wiki_page_content]' } # rubocop:disable QA/SelectorUsage
- let!(:included_wiki_page) { create_wiki_page('included_page', content: 'Content from the included page')}
+ let!(:included_wiki_page) { create_wiki_page('included_page', content: 'Content from the included page') }
let!(:wiki_page) { create_wiki_page('home', content: "Content from the main page.\ninclude::included_page.asciidoc[]") }
def create_wiki_page(title, content:)
diff --git a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
index b786d7e5527..c388a3a2c7f 100644
--- a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
@@ -131,7 +131,7 @@ RSpec.shared_examples 'common trace features' do
end
context 'logs contains "section_start"' do
- let(:log) { "section_start:1506417476:a_section\r\033[0Klooks like a section_start:invalid\nsection_end:1506417477:a_section\r\033[0K"}
+ let(:log) { "section_start:1506417476:a_section\r\033[0Klooks like a section_start:invalid\nsection_end:1506417477:a_section\r\033[0K" }
it "returns only one section" do
expect(sections).not_to be_empty
@@ -144,7 +144,7 @@ RSpec.shared_examples 'common trace features' do
end
context 'missing section_end' do
- let(:log) { "section_start:1506417476:a_section\r\033[0KSome logs\nNo section_end\n"}
+ let(:log) { "section_start:1506417476:a_section\r\033[0KSome logs\nNo section_end\n" }
it "returns no sections" do
expect(sections).to be_empty
@@ -152,7 +152,7 @@ RSpec.shared_examples 'common trace features' do
end
context 'missing section_start' do
- let(:log) { "Some logs\nNo section_start\nsection_end:1506417476:a_section\r\033[0K"}
+ let(:log) { "Some logs\nNo section_start\nsection_end:1506417476:a_section\r\033[0K" }
it "returns no sections" do
expect(sections).to be_empty
@@ -160,7 +160,7 @@ RSpec.shared_examples 'common trace features' do
end
context 'inverted section_start section_end' do
- let(:log) { "section_end:1506417476:a_section\r\033[0Klooks like a section_start:invalid\nsection_start:1506417477:a_section\r\033[0K"}
+ let(:log) { "section_end:1506417476:a_section\r\033[0Klooks like a section_start:invalid\nsection_start:1506417477:a_section\r\033[0K" }
it "returns no sections" do
expect(sections).to be_empty
@@ -169,7 +169,7 @@ RSpec.shared_examples 'common trace features' do
end
describe '#write' do
- subject { trace.send(:write, mode) { } }
+ subject { trace.send(:write, mode) {} }
let(:mode) { 'wb' }
diff --git a/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb
index ead8b174d46..ec7b2794703 100644
--- a/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb
@@ -25,7 +25,7 @@ RSpec.shared_examples 'SQL set operator' do |operator_keyword|
empty_relation = User.none.select(:id)
set_operator = described_class.new([empty_relation, relation_1, relation_2])
- expect {User.where("users.id IN (#{set_operator.to_sql})").to_a}.not_to raise_error
+ expect { User.where("users.id IN (#{set_operator.to_sql})").to_a }.not_to raise_error
expect(set_operator.to_sql).to eq("(#{to_sql(relation_1)})\n#{operator_keyword}\n(#{to_sql(relation_2)})")
end
diff --git a/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
index 51071ae47c3..ca9122bf61f 100644
--- a/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
+++ b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
@@ -37,7 +37,7 @@ RSpec.shared_examples 'cluster application core specs' do |application_name|
with_them do
subject { described_class.new(cluster: cluster).helm_command_module }
- let(:cluster) { build(:cluster, helm_major_version: helm_major_version)}
+ let(:cluster) { build(:cluster, helm_major_version: helm_major_version) }
it { is_expected.to eq(expected_helm_command_module) }
end
diff --git a/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb b/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
index 8ff30021d6e..6f104f400bc 100644
--- a/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
+++ b/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
@@ -89,7 +89,7 @@ RSpec.shared_examples 'StageEventModel' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:user) }
let_it_be(:milestone) { create(:milestone) }
- let_it_be(:issuable_with_assignee) { create(issuable_factory, assignees: [user])}
+ let_it_be(:issuable_with_assignee) { create(issuable_factory, assignees: [user]) }
let_it_be(:record) { create(stage_event_factory, start_event_timestamp: 3.years.ago.to_date, end_event_timestamp: 2.years.ago.to_date) }
let_it_be(:record_with_author) { create(stage_event_factory, author_id: user.id) }
diff --git a/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb b/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb
index a403a27adef..0a07c9d677b 100644
--- a/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb
@@ -125,17 +125,17 @@ RSpec.shared_examples 'model with repository' do
end
describe '#valid_repo?' do
- it { expect(stubbed_container.valid_repo?).to be(false)}
+ it { expect(stubbed_container.valid_repo?).to be(false) }
it { expect(container.valid_repo?).to be(true) }
end
describe '#repository_exists?' do
- it { expect(stubbed_container.repository_exists?).to be(false)}
+ it { expect(stubbed_container.repository_exists?).to be(false) }
it { expect(container.repository_exists?).to be(true) }
end
describe '#repo_exists?' do
- it { expect(stubbed_container.repo_exists?).to be(false)}
+ it { expect(stubbed_container.repo_exists?).to be(false) }
it { expect(container.repo_exists?).to be(true) }
end
diff --git a/spec/support/shared_examples/models/concerns/incident_management/escalatable_shared_examples.rb b/spec/support/shared_examples/models/concerns/incident_management/escalatable_shared_examples.rb
index 8ee76efc896..a5970f134d9 100644
--- a/spec/support/shared_examples/models/concerns/incident_management/escalatable_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/incident_management/escalatable_shared_examples.rb
@@ -77,7 +77,7 @@ RSpec.shared_examples 'a model including Escalatable' do
end
context 'scopes' do
- let(:all_escalatables) { described_class.where(id: [triggered_escalatable, acknowledged_escalatable, ignored_escalatable, resolved_escalatable])}
+ let(:all_escalatables) { described_class.where(id: [triggered_escalatable, acknowledged_escalatable, ignored_escalatable, resolved_escalatable]) }
describe '.order_status' do
subject { all_escalatables.order_status(order) }
diff --git a/spec/support/shared_examples/models/label_note_shared_examples.rb b/spec/support/shared_examples/models/label_note_shared_examples.rb
index 73066fb631a..f61007f57fd 100644
--- a/spec/support/shared_examples/models/label_note_shared_examples.rb
+++ b/spec/support/shared_examples/models/label_note_shared_examples.rb
@@ -12,7 +12,7 @@ RSpec.shared_examples 'label note created from events' do
def label_refs(events)
labels = events.map(&:label).compact
- labels.map { |l| l.to_reference}.sort.join(' ')
+ labels.map { |l| l.to_reference }.sort.join(' ')
end
let(:time) { Time.now }
diff --git a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
index 6b0ae589efb..3d7d97bbeae 100644
--- a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
+++ b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
@@ -202,17 +202,17 @@ RSpec.shared_examples 'Debian Distribution' do |factory, container, can_freeze|
end
else
describe 'group distribution specifics' do
- let_it_be(:public_project) { create(:project, :public, group: distribution_with_suite.container)}
+ let_it_be(:public_project) { create(:project, :public, group: distribution_with_suite.container) }
let_it_be(:public_distribution_with_same_codename) { create(:debian_project_distribution, container: public_project, codename: distribution_with_suite.codename) }
- let_it_be(:public_package_with_same_codename) { create(:debian_package, project: public_project, published_in: public_distribution_with_same_codename)}
+ let_it_be(:public_package_with_same_codename) { create(:debian_package, project: public_project, published_in: public_distribution_with_same_codename) }
let_it_be(:public_distribution_with_same_suite) { create(:debian_project_distribution, container: public_project, suite: distribution_with_suite.suite) }
- let_it_be(:public_package_with_same_suite) { create(:debian_package, project: public_project, published_in: public_distribution_with_same_suite)}
+ let_it_be(:public_package_with_same_suite) { create(:debian_package, project: public_project, published_in: public_distribution_with_same_suite) }
- let_it_be(:private_project) { create(:project, :private, group: distribution_with_suite.container)}
+ let_it_be(:private_project) { create(:project, :private, group: distribution_with_suite.container) }
let_it_be(:private_distribution_with_same_codename) { create(:debian_project_distribution, container: private_project, codename: distribution_with_suite.codename) }
- let_it_be(:private_package_with_same_codename) { create(:debian_package, project: private_project, published_in: private_distribution_with_same_codename)}
+ let_it_be(:private_package_with_same_codename) { create(:debian_package, project: private_project, published_in: private_distribution_with_same_codename) }
let_it_be(:private_distribution_with_same_suite) { create(:debian_project_distribution, container: private_project, suite: distribution_with_suite.suite) }
- let_it_be(:private_package_with_same_suite) { create(:debian_package, project: private_project, published_in: private_distribution_with_same_codename)}
+ let_it_be(:private_package_with_same_suite) { create(:debian_package, project: private_project, published_in: private_distribution_with_same_codename) }
describe '#packages' do
subject { distribution_with_suite.packages }
diff --git a/spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb b/spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb
index 66cd8d1df12..9093b386a5d 100644
--- a/spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb
+++ b/spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb
@@ -64,7 +64,7 @@ RSpec.shared_examples 'latest successful build for sha or ref' do
context 'with build belonging to a child pipeline' do
let(:child_pipeline) { create_pipeline(project) }
let(:parent_bridge) { create(:ci_bridge, pipeline: pipeline, project: pipeline.project) }
- let!(:pipeline_source) { create(:ci_sources_pipeline, source_job: parent_bridge, pipeline: child_pipeline)}
+ let!(:pipeline_source) { create(:ci_sources_pipeline, source_job: parent_bridge, pipeline: child_pipeline) }
let!(:child_build) { create_build(child_pipeline, 'child-build') }
let(:build_name) { child_build.name }
diff --git a/spec/support/shared_examples/requests/api/issues/merge_requests_count_shared_examples.rb b/spec/support/shared_examples/requests/api/issues/merge_requests_count_shared_examples.rb
index 971b21b5b32..8c4ff120471 100644
--- a/spec/support/shared_examples/requests/api/issues/merge_requests_count_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/issues/merge_requests_count_shared_examples.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
def get_issue
- json_response.is_a?(Array) ? json_response.detect {|issue| issue['id'] == target_issue.id} : json_response
+ json_response.is_a?(Array) ? json_response.detect { |issue| issue['id'] == target_issue.id } : json_response
end
RSpec.shared_examples 'accessible merge requests count' do
diff --git a/spec/support/shared_examples/requests/api/labels_api_shared_examples.rb b/spec/support/shared_examples/requests/api/labels_api_shared_examples.rb
index 02e50b789cc..41d21490343 100644
--- a/spec/support/shared_examples/requests/api/labels_api_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/labels_api_shared_examples.rb
@@ -9,6 +9,6 @@ RSpec.shared_examples 'fetches labels' do
expect(json_response).to be_an Array
expect(json_response).to all(match_schema('public_api/v4/labels/label'))
expect(json_response.size).to eq(expected_labels.size)
- expect(json_response.map {|r| r['name'] }).to match_array(expected_labels)
+ expect(json_response.map { |r| r['name'] }).to match_array(expected_labels)
end
end
diff --git a/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb b/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb
index 3ca2b9fa6de..2d036cb2aa3 100644
--- a/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb
@@ -70,7 +70,7 @@ RSpec.shared_examples 'repository_storage_moves API' do |container_type|
get_container_repository_storage_moves
- json_ids = json_response.map {|storage_move| storage_move['id'] }
+ json_ids = json_response.map { |storage_move| storage_move['id'] }
expect(json_ids).to eq([
storage_move.id,
storage_move_middle.id,
diff --git a/spec/support/shared_examples/requests/lfs_http_shared_examples.rb b/spec/support/shared_examples/requests/lfs_http_shared_examples.rb
index 294ceffd77b..83be0cc1fe3 100644
--- a/spec/support/shared_examples/requests/lfs_http_shared_examples.rb
+++ b/spec/support/shared_examples/requests/lfs_http_shared_examples.rb
@@ -49,7 +49,7 @@ RSpec.shared_examples 'LFS http 404 response' do
end
RSpec.shared_examples 'LFS http expected response code and message' do
- let(:response_code) { }
+ let(:response_code) {}
let(:response_headers) { {} }
let(:content_type) { LfsRequest::CONTENT_TYPE }
let(:message) {}
diff --git a/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb b/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb
index 6cae7d8e00f..9546b6cbea4 100644
--- a/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb
+++ b/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb
@@ -23,7 +23,7 @@ RSpec.shared_examples 'creates an alert management alert or errors' do
end
context 'and fails to save' do
- let(:errors) { double(messages: { hosts: ['hosts array is over 255 chars'] }, '[]': [] )}
+ let(:errors) { double(messages: { hosts: ['hosts array is over 255 chars'] }, '[]': [] ) }
before do
allow(service).to receive(:alert).and_call_original
diff --git a/spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb b/spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb
index a46c2f0ac5c..1638e2fa86a 100644
--- a/spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb
@@ -3,8 +3,8 @@
RSpec.shared_examples 'issues move service' do |group|
shared_examples 'updating timestamps' do
it 'updates updated_at' do
- expect {described_class.new(parent, user, params).execute(issue)}
- .to change {issue.reload.updated_at}
+ expect { described_class.new(parent, user, params).execute(issue) }
+ .to change { issue.reload.updated_at }
end
end
diff --git a/spec/support/shared_examples/services/gitlab_projects_import_service_shared_examples.rb b/spec/support/shared_examples/services/gitlab_projects_import_service_shared_examples.rb
index 2aac7e328f0..366fa4763e1 100644
--- a/spec/support/shared_examples/services/gitlab_projects_import_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/gitlab_projects_import_service_shared_examples.rb
@@ -33,7 +33,7 @@ RSpec.shared_examples 'gitlab projects import validations' do
context 'when there is a project with the same path' do
let(:existing_project) { create(:project, namespace: namespace) }
- let(:path) { existing_project.path}
+ let(:path) { existing_project.path }
it 'does not create the project' do
project = subject.execute
diff --git a/spec/support/shared_examples/services/merge_request_shared_examples.rb b/spec/support/shared_examples/services/merge_request_shared_examples.rb
index d2595b92cbc..b3ba0a1be93 100644
--- a/spec/support/shared_examples/services/merge_request_shared_examples.rb
+++ b/spec/support/shared_examples/services/merge_request_shared_examples.rb
@@ -123,7 +123,7 @@ end
RSpec.shared_examples 'with an existing branch that has a merge request open' do |count|
let(:changes) { existing_branch_changes }
- let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch) }
it_behaves_like 'a service that does not create a merge request'
it_behaves_like 'a service that can change assignees of a merge request', count
diff --git a/spec/support/shared_examples/uploaders/object_storage_shared_examples.rb b/spec/support/shared_examples/uploaders/object_storage_shared_examples.rb
index f8b00d1e4c0..3c977e62a10 100644
--- a/spec/support/shared_examples/uploaders/object_storage_shared_examples.rb
+++ b/spec/support/shared_examples/uploaders/object_storage_shared_examples.rb
@@ -56,8 +56,8 @@ RSpec.shared_examples "migrates" do |to_store:, from_store: nil|
it 'can access to the original file during migration' do
file = subject.file
- allow(subject).to receive(:delete_migrated_file) { } # Remove as a callback of :migrate
- allow(subject).to receive(:record_upload) { } # Remove as a callback of :store (:record_upload)
+ allow(subject).to receive(:delete_migrated_file) {} # Remove as a callback of :migrate
+ allow(subject).to receive(:record_upload) {} # Remove as a callback of :store (:record_upload)
expect(file.exists?).to be_truthy
expect { migrate(to) }.not_to change { file.exists? }