From 9ee836ec2b67ef6e7537f2f68fceb6be16fa5e8a Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Mon, 15 Apr 2024 18:11:15 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- Gemfile | 2 +- Gemfile.checksum | 2 +- Gemfile.lock | 4 +- .../graph/components/job_group_dropdown.vue | 1 + app/assets/javascripts/lib/utils/autosave.js | 3 + .../notes/components/noteable_discussion.vue | 14 +- .../notes/components/notes_app.vue | 11 +- ...prise_users_from_identity_verification.yml | 8 - doc/api/graphql/reference/index.md | 25 +++ .../blueprints/tailwindcss/index.md | 48 +---- doc/development/fe_guide/style/scss.md | 30 +-- doc/user/project/integrations/squash_tm.md | 5 + keeps/helpers/file_helper.rb | 59 +++++ keeps/quarantine_flaky_tests.rb | 9 +- keeps/remove_duplicated_indexes.rb | 202 ++++++++++++++++++ locale/gitlab.pot | 24 +++ qa/Gemfile | 2 +- qa/Gemfile.lock | 6 +- .../application_cable/connection_spec.rb | 2 +- .../components/noteable_discussion_spec.js | 29 +++ spec/keeps/helpers/file_helper_spec.rb | 140 ++++++++++++ .../api/ci/runner/jobs_artifacts_spec.rb | 6 +- .../api/ci/runner/jobs_request_yamls_spec.rb | 6 +- spec/requests/api/ci/runners_spec.rb | 22 +- spec/requests/api/ci/secure_files_spec.rb | 8 +- spec/requests/api/commits_spec.rb | 2 +- .../error_tracking/project_settings_spec.rb | 11 +- spec/requests/api/feature_flags_spec.rb | 9 +- .../api/feature_flags_user_lists_spec.rb | 9 +- spec/requests/api/files_spec.rb | 12 +- .../user_achievements_query_spec.rb | 6 +- .../api/graphql/ci/catalog/resource_spec.rb | 6 +- .../api/graphql/ci/catalog/resources_spec.rb | 6 +- .../graphql/current_user/groups_query_spec.rb | 18 +- .../graphql/current_user/todos_query_spec.rb | 6 +- spec/requests/api/graphql/issues_spec.rb | 6 +- .../mutations/achievements/award_spec.rb | 7 +- .../mutations/achievements/create_spec.rb | 7 +- .../mutations/achievements/delete_spec.rb | 7 +- .../delete_user_achievement_spec.rb | 7 +- .../mutations/achievements/revoke_spec.rb | 7 +- .../mutations/achievements/update_spec.rb | 7 +- .../alerts/set_assignees_spec.rb | 6 +- .../boards/issues/issue_move_list_spec.rb | 6 +- .../api/graphql/mutations/ci/job/play_spec.rb | 6 +- .../graphql/mutations/ci/job/retry_spec.rb | 6 +- .../mutations/ci/pipeline_cancel_spec.rb | 6 +- .../mutations/ci/pipeline_retry_spec.rb | 6 +- .../pipeline_schedule/take_ownership_spec.rb | 6 +- .../canary_ingress/update_spec.rb | 9 +- .../issues/set_escalation_status_spec.rb | 6 +- .../graphql/mutations/snippets/update_spec.rb | 6 +- .../mutations/todos/mark_all_done_spec.rb | 6 +- .../graphql/mutations/todos/mark_done_spec.rb | 6 +- .../mutations/todos/restore_many_spec.rb | 6 +- .../graphql/mutations/todos/restore_spec.rb | 6 +- .../api/graphql/project/fork_targets_spec.rb | 7 +- .../api/graphql/projects/projects_spec.rb | 6 +- .../user/user_achievements_query_spec.rb | 6 +- spec/requests/api/groups_spec.rb | 9 +- spec/requests/api/internal/kubernetes_spec.rb | 12 +- .../api/issues/get_project_issues_spec.rb | 10 +- spec/requests/api/issues/issues_spec.rb | 6 +- .../project_container_repositories_spec.rb | 20 +- spec/requests/api/project_hooks_spec.rb | 10 +- spec/requests/api/project_milestones_spec.rb | 6 +- spec/requests/api/protected_branches_spec.rb | 12 +- spec/requests/api/todos_spec.rb | 7 +- .../groups/autocomplete_sources_spec.rb | 6 +- .../settings/access_tokens_controller_spec.rb | 9 +- .../groups/settings/slacks_controller_spec.rb | 6 +- .../alert_management_controller_spec.rb | 9 +- .../revoke_oauth_controller_spec.rb | 2 +- .../projects/redirect_controller_spec.rb | 6 +- .../settings/access_tokens_controller_spec.rb | 9 +- .../settings/slacks_controller_spec.rb | 6 +- spec/requests/verifies_with_email_spec.rb | 12 +- spec/routing/user_routing_spec.rb | 2 +- spec/support/helpers/session_helpers.rb | 4 +- .../mutations/snippets_shared_examples.rb | 6 +- .../requests/rack_attack_shared_examples.rb | 4 +- 81 files changed, 647 insertions(+), 433 deletions(-) delete mode 100644 config/feature_flags/development/exempt_paid_namespace_members_and_enterprise_users_from_identity_verification.yml create mode 100644 keeps/helpers/file_helper.rb create mode 100644 keeps/remove_duplicated_indexes.rb create mode 100644 spec/keeps/helpers/file_helper_spec.rb diff --git a/Gemfile b/Gemfile index dacf2473597..0ace0463473 100644 --- a/Gemfile +++ b/Gemfile @@ -528,7 +528,7 @@ group :test do # Moved in `test` because https://gitlab.com/gitlab-org/gitlab/-/issues/217527 gem 'derailed_benchmarks', require: false # rubocop:todo Gemfile/MissingFeatureCategory - gem 'gitlab_quality-test_tooling', '~> 1.21.1', require: false, feature_category: :tooling + gem 'gitlab_quality-test_tooling', '~> 1.22.0', require: false, feature_category: :tooling end gem 'octokit', '~> 8.1', feature_category: :importers diff --git a/Gemfile.checksum b/Gemfile.checksum index c12c8b9c9c6..4a116096437 100644 --- a/Gemfile.checksum +++ b/Gemfile.checksum @@ -226,7 +226,7 @@ {"name":"gitlab-styles","version":"11.0.0","platform":"ruby","checksum":"0dd8ec066ce9955ac51d3616c6bfded30f75bb526f39ff392ece6f43d5b9406b"}, {"name":"gitlab_chronic_duration","version":"0.12.0","platform":"ruby","checksum":"0d766944d415b5c831f176871ee8625783fc0c5bfbef2d79a3a616f207ffc16d"}, {"name":"gitlab_omniauth-ldap","version":"2.2.0","platform":"ruby","checksum":"bb4d20acb3b123ed654a8f6a47d3fac673ece7ed0b6992edb92dca14bad2838c"}, -{"name":"gitlab_quality-test_tooling","version":"1.21.1","platform":"ruby","checksum":"83f2a115d21e921b0b540ba87765cad98f0766178244abc3d06d18dd1bd58ebc"}, +{"name":"gitlab_quality-test_tooling","version":"1.22.0","platform":"ruby","checksum":"266f2ceac880dc52f3f989ef5357580295d3624b5abc096e293749e5814743e5"}, {"name":"globalid","version":"1.1.0","platform":"ruby","checksum":"b337e1746f0c8cb0a6c918234b03a1ddeb4966206ce288fbb57779f59b2d154f"}, {"name":"gon","version":"6.4.0","platform":"ruby","checksum":"e3a618d659392890f1aa7db420f17c75fd7d35aeb5f8fe003697d02c4b88d2f0"}, {"name":"google-apis-androidpublisher_v3","version":"0.34.0","platform":"ruby","checksum":"d7e1d7dd92f79c498fe2082222a1740d788e022e660c135564b3fd299cab5425"}, diff --git a/Gemfile.lock b/Gemfile.lock index bb661693ff4..694e5a91892 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -743,7 +743,7 @@ GEM omniauth (>= 1.3, < 3) pyu-ruby-sasl (>= 0.0.3.3, < 0.1) rubyntlm (~> 0.5) - gitlab_quality-test_tooling (1.21.1) + gitlab_quality-test_tooling (1.22.0) activesupport (>= 6.1, < 7.2) amatch (~> 0.4.1) gitlab (~> 4.19) @@ -1932,7 +1932,7 @@ DEPENDENCIES gitlab-utils! gitlab_chronic_duration (~> 0.12) gitlab_omniauth-ldap (~> 2.2.0) - gitlab_quality-test_tooling (~> 1.21.1) + gitlab_quality-test_tooling (~> 1.22.0) gon (~> 6.4.0) google-apis-androidpublisher_v3 (~> 0.34.0) google-apis-cloudbilling_v1 (~> 0.21.0) diff --git a/app/assets/javascripts/ci/pipeline_details/graph/components/job_group_dropdown.vue b/app/assets/javascripts/ci/pipeline_details/graph/components/job_group_dropdown.vue index 17896a629af..b6633c3b936 100644 --- a/app/assets/javascripts/ci/pipeline_details/graph/components/job_group_dropdown.vue +++ b/app/assets/javascripts/ci/pipeline_details/graph/components/job_group_dropdown.vue @@ -74,6 +74,7 @@ export default { :id="computedJobId" class="ci-job-group-dropdown" block + fluid-width placement="right-start" data-testid="job-dropdown-container" > diff --git a/app/assets/javascripts/lib/utils/autosave.js b/app/assets/javascripts/lib/utils/autosave.js index 01316be06a2..9cf817bc5a1 100644 --- a/app/assets/javascripts/lib/utils/autosave.js +++ b/app/assets/javascripts/lib/utils/autosave.js @@ -63,3 +63,6 @@ export const updateDraft = (autosaveKey, text, lockVersion) => { export const getDiscussionReplyKey = (noteableType, discussionId) => /* eslint-disable-next-line @gitlab/require-i18n-strings */ ['Note', capitalizeFirstCharacter(noteableType), discussionId, 'Reply'].join('/'); + +export const getAutoSaveKeyFromDiscussion = (discussion) => + getDiscussionReplyKey(discussion.notes.slice(0, 1)[0].noteable_type, discussion.id); diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index 493beb8cea9..394f64d51bd 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -4,7 +4,7 @@ import { GlTooltipDirective, GlIcon } from '@gitlab/ui'; import { mapActions, mapGetters } from 'vuex'; import DraftNote from '~/batch_comments/components/draft_note.vue'; import { createAlert } from '~/alert'; -import { clearDraft, getDiscussionReplyKey } from '~/lib/utils/autosave'; +import { clearDraft, getDraft, getAutoSaveKeyFromDiscussion } from '~/lib/utils/autosave'; import { isLoggedIn } from '~/lib/utils/common_utils'; import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal'; import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending'; @@ -119,14 +119,11 @@ export default { return this.discussion.internal ? __('internal note') : __('comment'); }, autosaveKey() { - return getDiscussionReplyKey(this.firstNote.noteable_type, this.discussion.id); + return getAutoSaveKeyFromDiscussion(this.discussion); }, newNotePath() { return this.getNoteableData.create_note_path; }, - firstNote() { - return this.discussion.notes.slice(0, 1)[0]; - }, saveButtonTitle() { return this.discussion.internal ? __('Reply internally') : __('Reply'); }, @@ -187,9 +184,15 @@ export default { 'gl-pt-0!': !this.discussion.diff_discussion && this.isReplying, }; }, + hasDraft() { + return Boolean(getDraft(this.autosaveKey)); + }, }, created() { eventHub.$on('startReplying', this.onStartReplying); + if (this.hasDraft) { + this.showReplyForm(); + } }, beforeDestroy() { eventHub.$off('startReplying', this.onStartReplying); @@ -360,6 +363,7 @@ export default { :diff-file="diffFile" :line="diffLine" :save-button-title="saveButtonTitle" + :autofocus="!hasDraft" :autosave-key="autosaveKey" @handleFormUpdateAddToReview="addReplyToReview" @handleFormUpdate="saveReply" diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index eb6764a7937..b9d3afb5404 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -3,6 +3,7 @@ import { mapGetters, mapActions } from 'vuex'; import { v4 as uuidv4 } from 'uuid'; import { InternalEvents } from '~/tracking'; +import { getDraft, getAutoSaveKeyFromDiscussion } from '~/lib/utils/autosave'; import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import OrderedLayout from '~/vue_shared/components/ordered_layout.vue'; @@ -197,7 +198,11 @@ export default { 'fetchNotes', ]), discussionIsIndividualNoteAndNotConverted(discussion) { - return discussion.individual_note && !this.convertedDisscussionIds.includes(discussion.id); + return ( + discussion.individual_note && + !this.convertedDisscussionIds.includes(discussion.id) && + !this.hasDraft(discussion) + ); }, handleHashChanged() { const noteId = this.checkLocationHash(); @@ -238,6 +243,10 @@ export default { this.trackEvent(types[event.name]); } }, + hasDraft(discussion) { + const autoSaveKey = getAutoSaveKeyFromDiscussion(discussion); + return Boolean(getDraft(autoSaveKey)); + }, }, systemNote: constants.SYSTEM_NOTE, }; diff --git a/config/feature_flags/development/exempt_paid_namespace_members_and_enterprise_users_from_identity_verification.yml b/config/feature_flags/development/exempt_paid_namespace_members_and_enterprise_users_from_identity_verification.yml deleted file mode 100644 index 497f8004b48..00000000000 --- a/config/feature_flags/development/exempt_paid_namespace_members_and_enterprise_users_from_identity_verification.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: exempt_paid_namespace_members_and_enterprise_users_from_identity_verification -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139101 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/434810 -milestone: '16.7' -type: development -group: group::anti-abuse -default_enabled: false diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index b7759f084b2..fd1e3991886 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -1493,6 +1493,31 @@ Input type: `AiAgentCreateInput` | `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | | `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | +### `Mutation.aiAgentDestroy` + +DETAILS: +**Introduced** in GitLab 16.11. +**Status**: Experiment. + +Input type: `AiAgentDestroyInput` + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `agentId` | [`AiAgentID!`](#aiagentid) | Global ID of the AI Agent to be deleted. | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `projectPath` | [`ID!`](#id) | Project to which the agent belongs. | + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `agent` | [`AiAgent`](#aiagent) | Agent after mutation. | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | +| `message` | [`String`](#string) | AI Agent deletion result message. | + ### `Mutation.aiAgentUpdate` DETAILS: diff --git a/doc/architecture/blueprints/tailwindcss/index.md b/doc/architecture/blueprints/tailwindcss/index.md index 726785138bb..dc79aa0110b 100644 --- a/doc/architecture/blueprints/tailwindcss/index.md +++ b/doc/architecture/blueprints/tailwindcss/index.md @@ -129,44 +129,10 @@ not a one size fits all solution and that we might need to adjust to some cases Here's the basic process: -1. Deprecate a collection of utility mixins in GitLab UI. This entails replacing the `gl-` prefix - with `gl-deprecated-` in the mixin's name, and updating all usages in both GitLab UI _and_ GitLab - accordingly. We will typically focus on a single mixins file at a time, though we might want to - deprecate several files at once if they are small enough. Conversely, some files might be too big - to be deprecated in one go and would require several iterations. -1. Enable the corresponding [Tailwind CSS core plugins](https://tailwindcss.com/docs/configuration#core-plugins) so that we can immediately start using the - newer utilities. -1. Migrate deprecated utilities to their Tailwind CSS equivalents. - -```mermaid -flowchart TD - RequiresDeprecation(Is the mixins collection widely used in GitLab?) - DeprecateMixins[Mark the mixins as deprecated with the `gl-deprecated-` prefix] - - HasTailwindEq(Does Tailwind CSS have equivalents?) - EnableCorePlugin["Enable the corresponding Tailwind CSS core plugin(s)"] - WriteCustomUtil[Write a custom Tailwind CSS utility] - - MigrateUtils[Migrate legacy utils to Tailwind CSS] - - RequiresDeprecation -- Yes --> DeprecateMixins - DeprecateMixins --> HasTailwindEq - RequiresDeprecation -- No --> HasTailwindEq - HasTailwindEq -- Yes --> EnableCorePlugin - HasTailwindEq -- No --> WriteCustomUtil - EnableCorePlugin --> MigrateUtils - WriteCustomUtil --> MigrateUtils -``` - -The deprecation step gives us some margin to evaluate each migration without risking breakages in -production. It does have some drawbacks: - -- We might cause merge conflicts for others as we will be touching several areas of the product in - our deprecation MRs. We will make sure to communicate these changes efficiently to not make things - too confusing. We will also use our best judgement to split MRs when we feel like their scope gets - too large. -- Deprecation MRs might require approval from several departments, which is another reason to - be transparent and iterative throughout the process. -- We are purposefully introducing technical debt which we are committed to pay in a reasonable time frame. - We acknowledge that the actual duration of this initiative may be affected by a number of factors (uncovering - edge-cases, DRIs' capacity, department-wide involvement, etc.), but we expect to have it completed in 6-12 months. +1. The base Tailwind config is defined in `@gitlab/ui` and exported as `tailwind.defaults.js`. This config defines breakpoints, colors, spacing, font size, and other configuration that should be consistent across all projects. +1. `gitlab-org/gitlab` has a `tailwind.config.js` file that uses `@gitlab/ui/tailwind.defaults.js` as a preset so all configuration is inherited. The `content` property is set to scan Vue, JS, HAML, and Ruby files in `gitlab-org/gitlab` and `@gitlab/ui`. +1. [scripts/frontend/tailwind_all_the_way.mjs](https://gitlab.com/gitlab-org/gitlab/-/blob/c1b1ac2a6282f0f2a6b8b43d212079829ec8d3d3/scripts/frontend/tailwind_all_the_way.mjs) compares Tailwind utilities to `@gitlab/ui` utilities. The utilities that are not a perfect match are added to `config/helpers/tailwind/css_in_js.js` in `gitlab-org/gitlab`. The utilities that are a perfect match are automatically generated by Tailwind. +1. `config/helpers/tailwind/css_in_js.js` is imported in `tailwind.config.js` and uses the [`addUtilities`](https://tailwindcss.com/docs/plugins#static-utilities) function to register these utilities. +1. Legacy utility usages in `gitlab-org/gitlab` are iteratively migrated to their Tailwind equivalents. This causes `config/helpers/tailwind/css_in_js.js` to shrink. +1. Legacy utility usages in `@gitlab/ui` are migrated to their Tailwind equivalents. When no legacy utility usages remain in `@gitlab/ui`, `config/helpers/tailwind/css_in_js.js` is empty and can be removed along with the supporting tooling. +1. All SCSS utility mixins are removed from `@gitlab/ui` and a major version is released. diff --git a/doc/development/fe_guide/style/scss.md b/doc/development/fe_guide/style/scss.md index 8b69fa14551..812317b8b16 100644 --- a/doc/development/fe_guide/style/scss.md +++ b/doc/development/fe_guide/style/scss.md @@ -8,9 +8,6 @@ info: Any user with at least the Maintainer role can merge updates to this conte ## Utility Classes -NOTE: -Please do not use any utilities that are prefixed with `gl-deprecated-`, instead use a Tailwind utility. - In order to reduce the generation of more CSS as our site grows, prefer the use of utility classes over adding new CSS. In complex cases, CSS can be addressed by adding component classes. ### Tailwind CSS @@ -31,15 +28,9 @@ However the bundle gets built, the output is saved to `app/assets/builds/tailwin ### Where are utility classes defined? -Prefer the use of [utility classes defined in GitLab UI](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/main/doc/css.md#utilities). +Utility classes are generated by [Tailwind CSS](https://tailwindcss.com/). To see available utility classes install the [VSCode Tailwind CSS IntelliSense plugin](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) or if you are using RubyMine the autocomplete should be available by default. - - -An easy list of classes can also be [seen on Unpkg](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss). - - - -Or using an extension like [CSS Class completion](https://marketplace.visualstudio.com/items?itemName=Zignd.html-css-class-completion). +There are also legacy utility classes defined in `config/helpers/tailwind/css_in_js.js`. These utility classes do not comply with Tailwind naming conventions and will be iteratively migrated to the Tailwind equivalent. Please do not add new instances of these utility classes, instead use the Tailwind equivalent. Classes in [`utilities.scss`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/stylesheets/utilities.scss) and [`common.scss`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/stylesheets/framework/common.scss) are being deprecated. Classes in [`common.scss`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/stylesheets/framework/common.scss) that use non-design-system values should be avoided. Use classes with conforming values instead. @@ -56,8 +47,7 @@ result (such as `ml-1` becoming `gl-ml-2`). ### Where should you put new utility classes? -Because we are in the process of [migrating to Tailwind](#tailwind-css) the utility class you need may already be -available from Tailwind. The [IntelliSense for VS Code plugin](https://tailwindcss.com/docs/editor-setup#intelli-sense-for-vs-code) will tell you what utility classes are available. If the utility class you need is not available from Tailwind, you should continue to use the [utility classes defined in GitLab UI](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/main/doc/css.md#utilities) which can be [seen on Unpkg](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss). If the utility class is still not available we need to enable a new core plugin in Tailwind. [Find the relevant core plugin](https://tailwindcss.com/docs/theme#configuration-reference) and open a MR to add the core plugin to the `corePlugins` array in [tailwind.defaults.js](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/bad526b4662f38868cfc3d89157b22f5cc9a94c5/tailwind.defaults.js). +Utility classes are generated by [Tailwind CSS](https://tailwindcss.com/) which supports most CSS features. If there is something that is not available we should update `tailwind.defaults.js` in GitLab UI. ### When should you create component classes? @@ -75,7 +65,7 @@ Inspiration: ### Utility mixins -We are currently in the process of [migrating to Tailwind](#tailwind-css). The migration removes utility mixins so please do not add any new usages of utility mixins. Instead use [pre-defined CSS keywords](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Values_and_Units#pre-defined_keyword_values) with SCSS variables. +We are currently in the process of [migrating to Tailwind](#tailwind-css). The migration removes utility mixins so please do not add any new usages of utility mixins. Instead, you can use the [`@apply` directive](https://tailwindcss.com/docs/reusing-styles#extracting-classes-with-apply) to add Tailwind styles to a CSS selector. `@apply` should be used for any CSS properties that are dependent on our design system (e.g. `margin`, `padding`). For CSS properties that are unit-less (e.g `display: flex`) it is okay to use CSS properties directly. ```scss // Bad @@ -83,19 +73,19 @@ We are currently in the process of [migrating to Tailwind](#tailwind-css). The m @include gl-mt-3; } -// Very bad -.my-class { - @include gl-deprecated-mt-3; -} - // Bad .my-class { margin-top: 0.5rem; } +// Okay +.my-class { + display: flex; +} + // Good .my-class { - margin-top: $gl-spacing-scale-3; + @apply gl-mt-5 gl-flex; } ``` diff --git a/doc/user/project/integrations/squash_tm.md b/doc/user/project/integrations/squash_tm.md index 638c0c5ac4e..e8860604980 100644 --- a/doc/user/project/integrations/squash_tm.md +++ b/doc/user/project/integrations/squash_tm.md @@ -16,6 +16,11 @@ When [Squash TM](https://www.squashtest.com/squash-gitlab-platform?lang=en) (Tes integration is enabled and configured in GitLab, issues (typically user stories) created in GitLab are synchronized as requirements in Squash TM and test progress is reported in GitLab issues. + +For an overview of optimizing your DevSecOps workflow with the Squash TM and GitLab integration, +see [Leverage Requirements and Test management in your SDLC](https://www.youtube.com/watch?v=XAiNUmBiqm4). + + ## Configure Squash TM 1. Optional. Ask your system administrator to [configure a token in the properties file](https://tm-en.doc.squashtest.com/latest/redirect/gitlab-integration-token.html). diff --git a/keeps/helpers/file_helper.rb b/keeps/helpers/file_helper.rb new file mode 100644 index 00000000000..d6e57e196fa --- /dev/null +++ b/keeps/helpers/file_helper.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'rubocop' + +module Keeps + module Helpers + class FileHelper + def initialize(file) + @file = file + @source = RuboCop::ProcessedSource.from_file(file, RuboCop::ConfigStore.new.for_file('.').target_ruby_version) + @rewriter = Parser::Source::TreeRewriter.new(@source.buffer) + end + + def replace_method_content(method_name, content, strip_comments_from_file: false) + method = source.ast.each_node(:class).first.each_node(:def).find do |child| + child.method_name == method_name.to_sym + end + + rewriter.replace(method.loc.expression, content) + + strip_comments if strip_comments_from_file + + File.write(file, process) + + process + end + + private + + attr_reader :file, :source, :rewriter, :corrector + + # Strip comments from the source file, except the for frozen_string_literal: true + def strip_comments + source.comments.each do |comment| + next if comment.text.include?('frozen_string_literal: true') + + rewriter.remove(comment_range(comment)) + end + end + + # Finds the proper range for the comment. + # + # @Note inline comments can cause trailing whitespaces. + # For such cases, the extra whitespace needs to be removed + def comment_range(comment) + range = comment.loc.expression + adjusted_range = range.adjust(begin_pos: -1) + + return range if comment.document? + + adjusted_range.source.start_with?(' ') ? adjusted_range : range + end + + def process + @process ||= rewriter.process.lstrip.gsub(/\n{3,}/, "\n\n") + end + end + end +end diff --git a/keeps/quarantine_flaky_tests.rb b/keeps/quarantine_flaky_tests.rb index 8c24a14cd99..e0fcfca396b 100644 --- a/keeps/quarantine_flaky_tests.rb +++ b/keeps/quarantine_flaky_tests.rb @@ -54,15 +54,10 @@ module Keeps file_lines[line_number - 1].sub!(EXAMPLE_LINE_REGEX, "\\1, quarantine: '#{flaky_issue['web_url']}' do") - if file_lines[line_number - 1].size > 120 - file_lines[line_number - 1].sub!( - /\n\z/, - " # rubocop:disable Layout/LineLength -- We prefer to keep it on a single line, for simplicity sake\n" - ) - end - File.write(file, file_lines.join) + ::Gitlab::Housekeeper::Shell.rubocop_autocorrect(file) + construct_change(filename, line_number, description, flaky_issue) end diff --git a/keeps/remove_duplicated_indexes.rb b/keeps/remove_duplicated_indexes.rb new file mode 100644 index 00000000000..15dc4282a13 --- /dev/null +++ b/keeps/remove_duplicated_indexes.rb @@ -0,0 +1,202 @@ +# frozen_string_literal: true + +require 'rails/generators' +require 'rails/generators/active_record' +require 'rails/generators/active_record/migration/migration_generator' + +require_relative 'helpers/file_helper' +require_relative '../spec/support/helpers/database/duplicate_indexes' + +module Keeps + # This is an implementation of a ::Gitlab::Housekeeper::Keep. This keep will look for duplicated indexes + # and it will generate the corresponding files to have the index dropped. For each index to be dropped, the Keep will + # generate a new migration and its schema migration file. It also updates the `db/schema.sql` for each migration file. + # + # This keep uses the test databases to generate a updated version of the schema. Each time the keep is invoked it will + # recreate the `gitlabhq_test` and `gitlabhq_test_ci` databases. + # + # You can run it individually with: + # + # ``` + # bundle exec gitlab-housekeeper -d \ + # -k Keeps::RemoveDuplicatedIndexes + # ``` + class RemoveDuplicatedIndexes < ::Gitlab::Housekeeper::Keep + MIGRATION_TEMPLATE = 'generator_templates/active_record/migration/' + DEFAULT_REVIEWER_GROUP = 'database' + + def initialize + ::Gitlab::Application.load_tasks + ::ActiveRecord::Generators::MigrationGenerator.source_root(MIGRATION_TEMPLATE) + + @indexes_to_drop = {} + + reset_db + migrate + load_indexes_to_drop + + super + end + + def each_change + indexes_to_drop.each do |table_name, indexes| + change = build_change(table_name, indexes) + change.changed_files = [] + + indexes.each do |index_to_drop, _| + migration_file, migration_number = generate_migration_file(table_name, index_to_drop) + change.changed_files << migration_file + change.changed_files << Pathname.new('db').join('schema_migrations', migration_number).to_s + end + + migrate + + change.changed_files << Pathname.new('db').join('structure.sql').to_s + + yield(change) + + reset_db + end + end + + private + + attr_reader :indexes_to_drop + + def load_indexes_to_drop + establish_test_db_connection do |connection| + connection.tables.sort.each do |table| + # Skip partitioned tables for now + next if Gitlab::Database::PostgresPartition.partition_exists?(table) + + result = process_result(Database::DuplicateIndexes.new(table, connection.indexes(table)).duplicate_indexes) + + next if result.empty? + + indexes_to_drop[table] = result + end + end + end + + def build_change(table_name, indexes) + change = ::Gitlab::Housekeeper::Change.new + change.title = "Remove duplicated index from #{table_name}".truncate(70, omission: '') + change.identifiers = [self.class.name.demodulize, table_name] + change.labels = labels(table_name) + change.reviewers = pick_reviewers(table_name, change.identifiers).uniq + + removes_section = indexes.map do |index_to_drop, matching_indexes| + matching_indexes_table = matching_indexes.map do |idx| + <<-MARKDOWN.strip + | `#{idx.name}` | #{idx.columns.map { |col| "`#{col[:name]} #{col[:order]}`" }.join(', ')} | + MARKDOWN + end + + <<~MARKDOWN.strip + Drop `#{index_to_drop.name}` as it's already covered by: + | Index | Columns | + | ----- | ------ | + #{matching_indexes_table.join("\n")} + MARKDOWN + end + + change.description = <<~MARKDOWN.chomp + ## What does this MR do and why? + + Remove duplicated index from `#{table_name}` table. + + ### It removes: + + #{removes_section.join("\n")} + + It is possible that this MR will still need some changes to drop the index from the database. + Currently, the `gitlab-housekeeper` is not always capable of removing all references, so you must check the diff and pipeline failures to confirm if there are any issues. + Ensure that the index exists in the production database by checking Joe Bot trough https://console.postgres.ai/gitlab. + If the index was already removed or if the index it's being removed in another merge request, consider closing this merge request. + MARKDOWN + + change + end + + def process_result(duplicated_indexes) + duplicates_map = Hash.new { |h, k| h[k] = [] } + + duplicated_indexes.each do |index, duplicates| + duplicates.each do |duplicate| + duplicates_map[duplicate] << index + end + end + + duplicates_map + end + + def generate_migration_file(table_name, index_to_drop) + migration_name = "drop_#{index_to_drop.name}".truncate(100, omission: '') + generator = ::ActiveRecord::Generators::MigrationGenerator.new([migration_name]) + migration_content = <<~RUBY.strip + disable_ddl_transaction! + + TABLE_NAME = :#{table_name} + INDEX_NAME = :#{index_to_drop.name} + COLUMN_NAMES = #{index_to_drop.columns.map { |col| col[:name].to_sym }} + + def up + remove_concurrent_index_by_name(TABLE_NAME, INDEX_NAME) + end + + def down + add_concurrent_index(TABLE_NAME, COLUMN_NAMES, name: INDEX_NAME) + end + RUBY + + migration_file = generator.invoke_all.first + file_helper = ::Keeps::Helpers::FileHelper.new(migration_file) + file_helper.replace_method_content(:change, migration_content, strip_comments_from_file: true) + + ::Gitlab::Housekeeper::Shell.execute('rubocop', '-a', migration_file) + + [migration_file, generator.migration_number] + end + + def pick_reviewers(table_name, identifiers) + table_info = Gitlab::Database::Dictionary.entries.find_by_table_name(table_name) + + table_info.feature_categories.map do |feature_category| + group = groups_helper.group_for_feature_category(feature_category) + + group = groups_helper.group_for_feature_category(DEFAULT_REVIEWER_GROUP) if group['backend_engineers'].empty? + + groups_helper.pick_reviewer(group, identifiers) + end + end + + def labels(table_name) + table_info = Gitlab::Database::Dictionary.entries.find_by_table_name(table_name) + + group_labels = table_info.feature_categories.map do |feature_category| + groups_helper.group_for_feature_category(feature_category)['label'] + end + + group_labels + %w[maintenance::scalability type::maintenance Category:Database] + end + + def establish_test_db_connection + # rubocop:disable Database/EstablishConnection -- We should use test database only + yield ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations.find_db_config('test')).connection + # rubocop:enable Database/EstablishConnection + end + + def reset_db + ApplicationRecord.clear_all_connections! + ::Gitlab::Housekeeper::Shell.execute({ 'RAILS_ENV' => 'test' }, 'rails', 'db:reset') + end + + def migrate + ::Gitlab::Housekeeper::Shell.execute({ 'RAILS_ENV' => 'test' }, 'rails', 'db:migrate') + end + + def groups_helper + @groups_helper ||= ::Keeps::Helpers::Groups.new + end + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 158e5c7ebea..26f57a1e9d1 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1987,6 +1987,9 @@ msgstr "" msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'" msgstr "" +msgid "AI Agent was successfully deleted" +msgstr "" + msgid "AI actions" msgstr "" @@ -1999,6 +2002,9 @@ msgstr "" msgid "AIAgents|Agent Settings" msgstr "" +msgid "AIAgents|An error has occurred when deleting the agent." +msgstr "" + msgid "AIAgents|An error has occurred when saving the agent." msgstr "" @@ -2014,6 +2020,9 @@ msgstr "" msgid "AIAgents|Update the name and prompt for this agent." msgstr "" +msgid "AIAgent|AI Agent %{codeStart}%{agentName}%{codeEnd} will be permanently deleted. Are you sure?" +msgstr "" + msgid "AIAgent|Agent" msgstr "" @@ -2026,6 +2035,15 @@ msgstr "" msgid "AIAgent|Create agent" msgstr "" +msgid "AIAgent|Delete Agent" +msgstr "" + +msgid "AIAgent|Delete agent?" +msgstr "" + +msgid "AIAgent|Delete this agent" +msgstr "" + msgid "AIAgent|Edit Ai Agent" msgstr "" @@ -2035,6 +2053,9 @@ msgstr "" msgid "AIAgent|Settings" msgstr "" +msgid "AIAgent|This action permanently deletes the %{codeStart}%{agentName}%{codeEnd} AI Agent." +msgstr "" + msgid "AIAgent|Try out your agent" msgstr "" @@ -21335,6 +21356,9 @@ msgstr "" msgid "Failed to create wiki" msgstr "" +msgid "Failed to delete AI Agent: %{msg}" +msgstr "" + msgid "Failed to delete branch target" msgstr "" diff --git a/qa/Gemfile b/qa/Gemfile index 9e744494a17..0627f9454cc 100644 --- a/qa/Gemfile +++ b/qa/Gemfile @@ -24,7 +24,7 @@ gem 'parallel', '~> 1.24' gem 'rainbow', '~> 3.1.1' gem 'rspec-parameterized', '~> 1.0.0' gem 'octokit', '~> 8.1.0' -gem "faraday-retry", "~> 2.2" +gem "faraday-retry", "~> 2.2", ">= 2.2.1" gem 'zeitwerk', '~> 2.6', '>= 2.6.13' gem 'influxdb-client', '~> 3.1' gem 'terminal-table', '~> 3.0.2', require: false diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock index 5ecc0942d3d..e8f166bd63b 100644 --- a/qa/Gemfile.lock +++ b/qa/Gemfile.lock @@ -86,7 +86,7 @@ GEM faraday-net_http (>= 2.0, < 3.1) ruby2_keywords (>= 0.0.4) faraday-net_http (3.0.0) - faraday-retry (2.2.0) + faraday-retry (2.2.1) faraday (~> 2.0) ffi (1.16.3) ffi-compiler (1.0.1) @@ -357,7 +357,7 @@ DEPENDENCIES deprecation_toolkit (~> 2.2.0) factory_bot (~> 6.3.0) faker (~> 3.3, >= 3.3.1) - faraday-retry (~> 2.2) + faraday-retry (~> 2.2, >= 2.2.1) fog-core (= 2.1.0) fog-google (~> 1.19) gitlab-qa (~> 14, >= 14.7.0) @@ -386,4 +386,4 @@ DEPENDENCIES zeitwerk (~> 2.6, >= 2.6.13) BUNDLED WITH - 2.5.7 + 2.5.9 diff --git a/spec/channels/application_cable/connection_spec.rb b/spec/channels/application_cable/connection_spec.rb index 28a852c46fa..d4e5fd3ab3a 100644 --- a/spec/channels/application_cable/connection_spec.rb +++ b/spec/channels/application_cable/connection_spec.rb @@ -7,7 +7,7 @@ RSpec.describe ApplicationCable::Connection, :clean_gitlab_redis_sessions do context 'when session cookie is set' do before do - stub_session(**session_hash) + stub_session(session_data: session_hash) end context 'when user is logged in' do diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js index 41da9d9ebf3..e7a201cc8d4 100644 --- a/spec/frontend/notes/components/noteable_discussion_spec.js +++ b/spec/frontend/notes/components/noteable_discussion_spec.js @@ -27,6 +27,7 @@ import { loggedOutnoteableData, userDataMock, } from '../mock_data'; +import { useLocalStorageSpy } from '../../__helpers__/local_storage_helper'; Vue.use(Vuex); @@ -98,6 +99,34 @@ describe('noteable_discussion component', () => { expect(wrapper.vm.canShowReplyActions).toBe(false); }); + describe('drafts', () => { + useLocalStorageSpy(); + + afterEach(() => { + localStorage.clear(); + }); + + it.each` + show | exists | hasDraft + ${'show'} | ${'exists'} | ${true} + ${'not show'} | ${'does not exist'} | ${false} + `( + 'should $show markdown editor on create if reply draft $exists in localStorage', + ({ hasDraft }) => { + if (hasDraft) { + localStorage.setItem(`autosave/Note/Issue/${discussionMock.id}/Reply`, 'draft'); + } + window.gon.current_user_id = userDataMock.id; + store.dispatch('setUserData', userDataMock); + wrapper = mount(NoteableDiscussion, { + store, + propsData: { discussion: discussionMock }, + }); + expect(wrapper.find('.note-edit-form').exists()).toBe(hasDraft); + }, + ); + }); + describe('actions', () => { it('should toggle reply form', async () => { await nextTick(); diff --git a/spec/keeps/helpers/file_helper_spec.rb b/spec/keeps/helpers/file_helper_spec.rb new file mode 100644 index 00000000000..05391f5bf3d --- /dev/null +++ b/spec/keeps/helpers/file_helper_spec.rb @@ -0,0 +1,140 @@ +# frozen_string_literal: true + +require 'spec_helper' +require './keeps/helpers/file_helper' + +RSpec.describe Keeps::Helpers::FileHelper, feature_category: :tooling do + let(:helper) { described_class.new(temp_file.path) } + let(:temp_file) { Tempfile.new(filename) } + let(:unparsed_content) do + <<~RUBY + # Migration type +class+ + # frozen_string_literal: true + + # See https://docs.gitlab.com/ee/development/migration_style_guide.html + # for more information on how to write migrations for GitLab. + + =begin + This migration adds + a new column to project + =end + class AddColToProjects < Gitlab::Database::Migration[2.2] + milestone '16.11' # Inline comment + + def change + add_column :projects, :bool_col, :boolean, default: false, null: false # adds a new column + end + end# Another inline comment + RUBY + end + + before do + temp_file.write(unparsed_content) + temp_file.rewind + temp_file.close + end + + after do + temp_file.unlink + end + + describe '#replace_method_content' do + before do + helper.replace_method_content(:change, content, strip_comments_from_file: strip_content) + end + + context 'when striping comments from file' do + let(:filename) { 'migration_two.txt' } + let(:strip_content) { true } + let(:content) do + <<~RUBY + disable_ddl_transaction! + + def up + add_column :projects, :bool_col, :boolean, default: false, null: false # adds a boolean type col + end + + def down + remove_column :projects, :bool_col, if_exists: true + end + RUBY + end + + let(:parsed_file) do + <<~RUBY + # frozen_string_literal: true + + class AddColToProjects < Gitlab::Database::Migration[2.2] + milestone '16.11' + + disable_ddl_transaction! + + def up + add_column :projects, :bool_col, :boolean, default: false, null: false # adds a boolean type col + end + + def down + remove_column :projects, :bool_col, if_exists: true + end + + end + RUBY + end + + it 'parses the file as expected' do + expect(temp_file.open.read).to eq(parsed_file) + end + end + + context 'when keeping comments in the file' do + let(:filename) { 'migration_two.txt' } + let(:strip_content) { false } + let(:content) do + <<~RUBY + disable_ddl_transaction! + + def up + add_column :projects, :bool_col, :boolean, default: false, null: false + end + + def down + remove_column :projects, :bool_col, if_exists: true + end + RUBY + end + + let(:parsed_file) do + <<~RUBY + # Migration type +class+ + # frozen_string_literal: true + + # See https://docs.gitlab.com/ee/development/migration_style_guide.html + # for more information on how to write migrations for GitLab. + + =begin + This migration adds + a new column to project + =end + class AddColToProjects < Gitlab::Database::Migration[2.2] + milestone '16.11' # Inline comment + + disable_ddl_transaction! + + def up + add_column :projects, :bool_col, :boolean, default: false, null: false + end + + def down + remove_column :projects, :bool_col, if_exists: true + end + + end# Another inline comment + RUBY + end + + it 'parses the file as expected' do + expect(temp_file.open.read).to eq(parsed_file) + end + end + end +end diff --git a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb index 637469411d5..d87564b9a8c 100644 --- a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb +++ b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb @@ -13,14 +13,10 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state, feature_catego let_it_be(:pipeline) { create(:ci_pipeline, project: project, ref: 'master') } let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) } - let_it_be(:user) { create(:user) } + let_it_be(:user) { create(:user, developer_of: project) } let(:registration_token) { 'abcdefg123456' } - before_all do - project.add_developer(user) - end - before do stub_feature_flags(ci_enable_live_trace: true) stub_gitlab_calls diff --git a/spec/requests/api/ci/runner/jobs_request_yamls_spec.rb b/spec/requests/api/ci/runner/jobs_request_yamls_spec.rb index f399c3e310e..73deb7d51c2 100644 --- a/spec/requests/api/ci/runner/jobs_request_yamls_spec.rb +++ b/spec/requests/api/ci/runner/jobs_request_yamls_spec.rb @@ -6,15 +6,11 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state, feature_catego include StubGitlabCalls let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, :repository, shared_runners_enabled: false) } + let_it_be(:project) { create(:project, :repository, shared_runners_enabled: false, maintainers: user) } let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) } let(:user_agent) { 'gitlab-runner 9.0.0 (9-0-stable; go1.7.4; linux/amd64)' } - before_all do - project.add_maintainer(user) - end - Dir[Rails.root.join("spec/requests/api/ci/runner/yamls/*.yml")].each do |yml_file| context "for #{File.basename(yml_file)}" do let(:yaml_content) { YAML.load_file(yml_file) } diff --git a/spec/requests/api/ci/runners_spec.rb b/spec/requests/api/ci/runners_spec.rb index 83d5c9521ac..c2ad5a30418 100644 --- a/spec/requests/api/ci/runners_spec.rb +++ b/spec/requests/api/ci/runners_spec.rb @@ -6,13 +6,13 @@ RSpec.describe API::Ci::Runners, :aggregate_failures, feature_category: :fleet_v let_it_be(:admin) { create(:user, :admin) } let_it_be(:user) { create(:user) } let_it_be(:user2) { create(:user) } - let_it_be(:group_guest) { create(:user) } - let_it_be(:group_reporter) { create(:user) } - let_it_be(:group_developer) { create(:user) } - let_it_be(:group_maintainer) { create(:user) } + let_it_be(:group_guest) { create(:user, guest_of: group) } + let_it_be(:group_reporter) { create(:user, reporter_of: group) } + let_it_be(:group_developer) { create(:user, developer_of: group) } + let_it_be(:group_maintainer) { create(:user, maintainer_of: group) } - let_it_be(:project) { create(:project, creator_id: user.id) } - let_it_be(:project2) { create(:project, creator_id: user.id) } + let_it_be(:project) { create(:project, creator_id: user.id, maintainers: user, reporters: user2) } + let_it_be(:project2) { create(:project, creator_id: user.id, maintainers: user) } let_it_be(:group) { create(:group, owners: user) } let_it_be(:subgroup) { create(:group, parent: group) } @@ -23,16 +23,6 @@ RSpec.describe API::Ci::Runners, :aggregate_failures, feature_category: :fleet_v let_it_be(:group_runner_a) { create(:ci_runner, :group, description: 'Group runner A', groups: [group]) } let_it_be(:group_runner_b) { create(:ci_runner, :group, description: 'Group runner B', groups: [subgroup]) } - before_all do - group.add_guest(group_guest) - group.add_reporter(group_reporter) - group.add_developer(group_developer) - group.add_maintainer(group_maintainer) - project.add_maintainer(user) - project2.add_maintainer(user) - project.add_reporter(user2) - end - describe 'GET /runners' do context 'authorized user' do it 'returns response status and headers' do diff --git a/spec/requests/api/ci/secure_files_spec.rb b/spec/requests/api/ci/secure_files_spec.rb index 4e1afd66683..b973d0b5acc 100644 --- a/spec/requests/api/ci/secure_files_spec.rb +++ b/spec/requests/api/ci/secure_files_spec.rb @@ -13,7 +13,7 @@ RSpec.describe API::Ci::SecureFiles, feature_category: :mobile_devops do let_it_be(:guest) { create(:user) } let_it_be(:anonymous) { create(:user) } let_it_be(:unconfirmed) { create(:user, :unconfirmed) } - let_it_be(:project) { create(:project, creator_id: maintainer.id) } + let_it_be(:project) { create(:project, creator_id: maintainer.id, maintainers: maintainer, developers: developer, guests: guest) } let_it_be(:secure_file) { create(:ci_secure_file, project: project) } let(:file_params) do @@ -23,12 +23,6 @@ RSpec.describe API::Ci::SecureFiles, feature_category: :mobile_devops do } end - before_all do - project.add_maintainer(maintainer) - project.add_developer(developer) - project.add_guest(guest) - end - describe 'GET /projects/:id/secure_files' do context 'ci_secure_files_read_only feature flag' do context 'when the flag is enabled' do diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index 67085da80e7..85a07d85174 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -599,7 +599,7 @@ RSpec.describe API::Commits, feature_category: :source_code_management do context 'when using warden', :snowplow, :clean_gitlab_redis_sessions do before do - stub_session('warden.user.user.key' => [[user.id], user.authenticatable_salt]) + stub_session(session_data: { 'warden.user.user.key' => [[user.id], user.authenticatable_salt] }) end subject { post api(url), params: valid_c_params } diff --git a/spec/requests/api/error_tracking/project_settings_spec.rb b/spec/requests/api/error_tracking/project_settings_spec.rb index 93ad0233ca3..bf9befe6442 100644 --- a/spec/requests/api/error_tracking/project_settings_spec.rb +++ b/spec/requests/api/error_tracking/project_settings_spec.rb @@ -6,18 +6,11 @@ RSpec.describe API::ErrorTracking::ProjectSettings, feature_category: :error_tra let_it_be(:project) { create(:project) } let_it_be(:setting) { create(:project_error_tracking_setting, project: project) } let_it_be(:project_without_setting) { create(:project) } - let_it_be(:developer) { create(:user) } - let_it_be(:maintainer) { create(:user) } + let_it_be(:developer) { create(:user, developer_of: [project, project_without_setting]) } + let_it_be(:maintainer) { create(:user, maintainer_of: [project, project_without_setting]) } let_it_be(:non_member) { create(:user) } let(:user) { maintainer } - before_all do - project.add_developer(developer) - project.add_maintainer(maintainer) - project_without_setting.add_developer(developer) - project_without_setting.add_maintainer(maintainer) - end - shared_examples 'returns project settings' do it 'returns correct project settings' do make_request diff --git a/spec/requests/api/feature_flags_spec.rb b/spec/requests/api/feature_flags_spec.rb index ab06a538357..1781b66d64e 100644 --- a/spec/requests/api/feature_flags_spec.rb +++ b/spec/requests/api/feature_flags_spec.rb @@ -5,17 +5,12 @@ RSpec.describe API::FeatureFlags, feature_category: :feature_flags do include FeatureFlagHelpers let_it_be(:project) { create(:project) } - let_it_be(:developer) { create(:user) } - let_it_be(:reporter) { create(:user) } + let_it_be(:developer) { create(:user, developer_of: project) } + let_it_be(:reporter) { create(:user, reporter_of: project) } let_it_be(:non_project_member) { create(:user) } let(:user) { developer } - before_all do - project.add_developer(developer) - project.add_reporter(reporter) - end - shared_examples_for 'check user permission' do context 'when user is reporter' do let(:user) { reporter } diff --git a/spec/requests/api/feature_flags_user_lists_spec.rb b/spec/requests/api/feature_flags_user_lists_spec.rb index 443cbbea147..93d5f8636f6 100644 --- a/spec/requests/api/feature_flags_user_lists_spec.rb +++ b/spec/requests/api/feature_flags_user_lists_spec.rb @@ -5,13 +5,8 @@ require 'spec_helper' RSpec.describe API::FeatureFlagsUserLists, feature_category: :feature_flags do let_it_be(:project, refind: true) { create(:project) } let_it_be(:client, refind: true) { create(:operations_feature_flags_client, project: project) } - let_it_be(:developer) { create(:user) } - let_it_be(:reporter) { create(:user) } - - before_all do - project.add_developer(developer) - project.add_reporter(reporter) - end + let_it_be(:developer) { create(:user, developer_of: project) } + let_it_be(:reporter) { create(:user, reporter_of: project) } def create_list(name: 'mylist', user_xids: 'user1') create(:operations_feature_flag_user_list, project: project, name: name, user_xids: user_xids) diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb index 01acb83360c..aa30b58338e 100644 --- a/spec/requests/api/files_spec.rb +++ b/spec/requests/api/files_spec.rb @@ -25,9 +25,9 @@ RSpec.describe API::Files, feature_category: :source_code_management do end let_it_be_with_refind(:user) { create(:user) } - let_it_be(:inherited_guest) { create(:user) } - let_it_be(:inherited_reporter) { create(:user) } - let_it_be(:inherited_developer) { create(:user) } + let_it_be(:inherited_guest) { create(:user, guest_of: group) } + let_it_be(:inherited_reporter) { create(:user, reporter_of: group) } + let_it_be(:inherited_developer) { create(:user, developer_of: group) } let_it_be_with_reload(:project) { create(:project, :repository, namespace: user.namespace) } let_it_be_with_reload(:public_project) { create(:project, :public, :repository) } @@ -65,12 +65,6 @@ RSpec.describe API::Files, feature_category: :source_code_management do let(:author_name) { 'John Doe' } end - before_all do - group.add_guest(inherited_guest) - group.add_reporter(inherited_reporter) - group.add_developer(inherited_developer) - end - before do project.add_developer(user) end diff --git a/spec/requests/api/graphql/achievements/user_achievements_query_spec.rb b/spec/requests/api/graphql/achievements/user_achievements_query_spec.rb index 94678bd18da..1016d668d94 100644 --- a/spec/requests/api/graphql/achievements/user_achievements_query_spec.rb +++ b/spec/requests/api/graphql/achievements/user_achievements_query_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'UserAchievements', feature_category: :user_profile do include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:group) { create(:group, :public) } + let_it_be(:group) { create(:group, :public, guests: user) } let_it_be(:achievement) { create(:achievement, namespace: group) } let_it_be(:non_revoked_achievement1) { create(:user_achievement, achievement: achievement, user: user) } let_it_be(:non_revoked_achievement2) { create(:user_achievement, :revoked, achievement: achievement, user: user) } @@ -45,10 +45,6 @@ RSpec.describe 'UserAchievements', feature_category: :user_profile do graphql_query_for('namespace', { full_path: group.full_path }, fields) end - before_all do - group.add_guest(user) - end - before do post_graphql(query, current_user: current_user) end diff --git a/spec/requests/api/graphql/ci/catalog/resource_spec.rb b/spec/requests/api/graphql/ci/catalog/resource_spec.rb index 5ce623b9583..876b9b76c6a 100644 --- a/spec/requests/api/graphql/ci/catalog/resource_spec.rb +++ b/spec/requests/api/graphql/ci/catalog/resource_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'Query.ciCatalogResource', feature_category: :pipeline_compositio include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:namespace) { create(:group) } + let_it_be(:namespace) { create(:group, developers: user) } let_it_be(:project) do create( @@ -36,10 +36,6 @@ RSpec.describe 'Query.ciCatalogResource', feature_category: :pipeline_compositio subject(:post_query) { post_graphql(query, current_user: user) } - before_all do - namespace.add_developer(user) - end - context 'when the current user has permission to read the namespace catalog' do it 'returns the resource with the expected data' do post_query diff --git a/spec/requests/api/graphql/ci/catalog/resources_spec.rb b/spec/requests/api/graphql/ci/catalog/resources_spec.rb index 767d5267381..fe071ea5758 100644 --- a/spec/requests/api/graphql/ci/catalog/resources_spec.rb +++ b/spec/requests/api/graphql/ci/catalog/resources_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'Query.ciCatalogResources', feature_category: :pipeline_compositi include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:namespace) { create(:group) } + let_it_be(:namespace) { create(:group, developers: user) } let_it_be(:project2) { create(:project, namespace: namespace) } let_it_be(:project1) do @@ -58,10 +58,6 @@ RSpec.describe 'Query.ciCatalogResources', feature_category: :pipeline_compositi subject(:post_query) { post_graphql(query, current_user: user) } - before_all do - namespace.add_developer(user) - end - shared_examples 'avoids N+1 queries' do it do ctx = { current_user: user } diff --git a/spec/requests/api/graphql/current_user/groups_query_spec.rb b/spec/requests/api/graphql/current_user/groups_query_spec.rb index 435e5e62f69..c7bb87f4548 100644 --- a/spec/requests/api/graphql/current_user/groups_query_spec.rb +++ b/spec/requests/api/graphql/current_user/groups_query_spec.rb @@ -7,11 +7,11 @@ RSpec.describe 'Query current user groups', feature_category: :groups_and_projec let_it_be(:user) { create(:user) } let_it_be(:root_group) { create(:group, name: 'Root group', path: 'root-group') } - let_it_be(:guest_group) { create(:group, name: 'public guest', path: 'public-guest') } - let_it_be(:private_maintainer_group) { create(:group, :private, name: 'b private maintainer', path: 'b-private-maintainer', parent: root_group) } - let_it_be(:public_developer_group) { create(:group, project_creation_level: nil, name: 'c public developer', path: 'c-public-developer') } - let_it_be(:public_maintainer_group) { create(:group, name: 'a public maintainer', path: 'a-public-maintainer', parent: root_group) } - let_it_be(:public_owner_group) { create(:group, name: 'a public owner', path: 'a-public-owner') } + let_it_be(:guest_group) { create(:group, name: 'public guest', path: 'public-guest', guests: user) } + let_it_be(:private_maintainer_group) { create(:group, :private, name: 'b private maintainer', path: 'b-private-maintainer', parent: root_group, maintainers: user) } + let_it_be(:public_developer_group) { create(:group, project_creation_level: nil, name: 'c public developer', path: 'c-public-developer', developers: user) } + let_it_be(:public_maintainer_group) { create(:group, name: 'a public maintainer', path: 'a-public-maintainer', parent: root_group, maintainers: user) } + let_it_be(:public_owner_group) { create(:group, name: 'a public owner', path: 'a-public-owner', owners: user) } let(:group_arguments) { {} } let(:current_user) { user } @@ -26,14 +26,6 @@ RSpec.describe 'Query current user groups', feature_category: :groups_and_projec graphql_query_for('currentUser', {}, query_graphql_field('groups', group_arguments, fields)) end - before_all do - guest_group.add_guest(user) - private_maintainer_group.add_maintainer(user) - public_developer_group.add_developer(user) - public_maintainer_group.add_maintainer(user) - public_owner_group.add_owner(user) - end - subject { graphql_data.dig('currentUser', 'groups', 'nodes') } before do diff --git a/spec/requests/api/graphql/current_user/todos_query_spec.rb b/spec/requests/api/graphql/current_user/todos_query_spec.rb index 790ae4b955e..0bd4fcc6629 100644 --- a/spec/requests/api/graphql/current_user/todos_query_spec.rb +++ b/spec/requests/api/graphql/current_user/todos_query_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'Query current user todos', feature_category: :source_code_manage include DesignManagementTestHelpers let_it_be(:current_user) { create(:user) } - let_it_be(:project) { create(:project, :repository) } + let_it_be(:project) { create(:project, :repository, developers: current_user) } let_it_be(:unauthorize_project) { create(:project) } let_it_be(:commit_todo) { create(:on_commit_todo, user: current_user, project: project) } let_it_be(:issue) { create(:issue, project: project) } @@ -28,10 +28,6 @@ RSpec.describe 'Query current user todos', feature_category: :source_code_manage graphql_query_for('currentUser', {}, query_graphql_field('todos', {}, fields)) end - before_all do - project.add_developer(current_user) - end - subject { graphql_data.dig('currentUser', 'todos', 'nodes') } before do diff --git a/spec/requests/api/graphql/issues_spec.rb b/spec/requests/api/graphql/issues_spec.rb index 913f1fc6367..69b250a2d2f 100644 --- a/spec/requests/api/graphql/issues_spec.rb +++ b/spec/requests/api/graphql/issues_spec.rb @@ -10,7 +10,7 @@ RSpec.describe 'getting an issue list at root level', feature_category: :team_pl let_it_be(:reporter) { create(:user) } let_it_be(:current_user) { developer } let_it_be(:group1) { create(:group, developers: developer) } - let_it_be(:group2) { create(:group, developers: developer) } + let_it_be(:group2) { create(:group, developers: developer, reporters: reporter) } let_it_be(:project_a) { create(:project, :repository, :public, group: group1) } let_it_be(:project_b) { create(:project, :repository, :private, group: group1) } let_it_be(:project_c) { create(:project, :repository, :public, group: group2) } @@ -97,10 +97,6 @@ RSpec.describe 'getting an issue list at root level', feature_category: :team_pl QUERY end - before_all do - group2.add_reporter(reporter) - end - shared_examples 'query that requires at least one filter' do it 'requires at least one filter to be provided to the query' do post_graphql(query, current_user: developer) diff --git a/spec/requests/api/graphql/mutations/achievements/award_spec.rb b/spec/requests/api/graphql/mutations/achievements/award_spec.rb index 9bc0751e924..682e66649b1 100644 --- a/spec/requests/api/graphql/mutations/achievements/award_spec.rb +++ b/spec/requests/api/graphql/mutations/achievements/award_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Mutations::Achievements::Award, feature_category: :user_profile d let_it_be(:developer) { create(:user) } let_it_be(:maintainer) { create(:user) } - let_it_be(:group) { create(:group) } + let_it_be(:group) { create(:group, developers: developer, maintainers: maintainer) } let_it_be(:achievement) { create(:achievement, namespace: group) } let_it_be(:recipient) { create(:user) } @@ -27,11 +27,6 @@ RSpec.describe Mutations::Achievements::Award, feature_category: :user_profile d graphql_mutation_response(:achievements_create) end - before_all do - group.add_developer(developer) - group.add_maintainer(maintainer) - end - context 'when the user does not have permission' do let(:current_user) { developer } diff --git a/spec/requests/api/graphql/mutations/achievements/create_spec.rb b/spec/requests/api/graphql/mutations/achievements/create_spec.rb index 3082629d40f..6dbebf7739d 100644 --- a/spec/requests/api/graphql/mutations/achievements/create_spec.rb +++ b/spec/requests/api/graphql/mutations/achievements/create_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Mutations::Achievements::Create, feature_category: :user_profile let_it_be(:developer) { create(:user) } let_it_be(:maintainer) { create(:user) } - let_it_be(:group) { create(:group) } + let_it_be(:group) { create(:group, developers: developer, maintainers: maintainer) } let(:mutation) { graphql_mutation(:achievements_create, params) } let(:name) { 'Name' } @@ -29,11 +29,6 @@ RSpec.describe Mutations::Achievements::Create, feature_category: :user_profile graphql_mutation_response(:achievements_create) end - before_all do - group.add_developer(developer) - group.add_maintainer(maintainer) - end - context 'when the user does not have permission' do let(:current_user) { developer } let(:avatar) {} diff --git a/spec/requests/api/graphql/mutations/achievements/delete_spec.rb b/spec/requests/api/graphql/mutations/achievements/delete_spec.rb index 276da4f46a8..f502675eecb 100644 --- a/spec/requests/api/graphql/mutations/achievements/delete_spec.rb +++ b/spec/requests/api/graphql/mutations/achievements/delete_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Mutations::Achievements::Delete, feature_category: :user_profile let_it_be(:developer) { create(:user) } let_it_be(:maintainer) { create(:user) } - let_it_be(:group) { create(:group) } + let_it_be(:group) { create(:group, developers: developer, maintainers: maintainer) } let!(:achievement) { create(:achievement, namespace: group) } let(:mutation) { graphql_mutation(:achievements_delete, params) } @@ -20,11 +20,6 @@ RSpec.describe Mutations::Achievements::Delete, feature_category: :user_profile graphql_mutation_response(:achievements_delete) end - before_all do - group.add_developer(developer) - group.add_maintainer(maintainer) - end - context 'when the user does not have permission' do let(:current_user) { developer } diff --git a/spec/requests/api/graphql/mutations/achievements/delete_user_achievement_spec.rb b/spec/requests/api/graphql/mutations/achievements/delete_user_achievement_spec.rb index f759e6dce08..fa10433a581 100644 --- a/spec/requests/api/graphql/mutations/achievements/delete_user_achievement_spec.rb +++ b/spec/requests/api/graphql/mutations/achievements/delete_user_achievement_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Mutations::Achievements::DeleteUserAchievement, feature_category: let_it_be(:maintainer) { create(:user) } let_it_be(:owner) { create(:user) } - let_it_be(:group) { create(:group) } + let_it_be(:group) { create(:group, maintainers: maintainer, owners: owner) } let_it_be(:achievement) { create(:achievement, namespace: group) } let_it_be(:user_achievement) { create(:user_achievement, achievement: achievement) } @@ -17,11 +17,6 @@ RSpec.describe Mutations::Achievements::DeleteUserAchievement, feature_category: subject { post_graphql_mutation(mutation, current_user: current_user) } - before_all do - group.add_maintainer(maintainer) - group.add_owner(owner) - end - context 'when the user does not have permission' do let(:current_user) { maintainer } diff --git a/spec/requests/api/graphql/mutations/achievements/revoke_spec.rb b/spec/requests/api/graphql/mutations/achievements/revoke_spec.rb index 925a1bb9fcc..aea6322b3f9 100644 --- a/spec/requests/api/graphql/mutations/achievements/revoke_spec.rb +++ b/spec/requests/api/graphql/mutations/achievements/revoke_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Mutations::Achievements::Revoke, feature_category: :user_profile let_it_be(:developer) { create(:user) } let_it_be(:maintainer) { create(:user) } - let_it_be(:group) { create(:group) } + let_it_be(:group) { create(:group, developers: developer, maintainers: maintainer) } let_it_be(:achievement) { create(:achievement, namespace: group) } let_it_be(:user_achievement) { create(:user_achievement, achievement: achievement) } @@ -21,11 +21,6 @@ RSpec.describe Mutations::Achievements::Revoke, feature_category: :user_profile graphql_mutation_response(:achievements_create) end - before_all do - group.add_developer(developer) - group.add_maintainer(maintainer) - end - context 'when the user does not have permission' do let(:current_user) { developer } diff --git a/spec/requests/api/graphql/mutations/achievements/update_spec.rb b/spec/requests/api/graphql/mutations/achievements/update_spec.rb index b2bb01b564c..b6dac305585 100644 --- a/spec/requests/api/graphql/mutations/achievements/update_spec.rb +++ b/spec/requests/api/graphql/mutations/achievements/update_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Mutations::Achievements::Update, feature_category: :user_profile let_it_be(:developer) { create(:user) } let_it_be(:maintainer) { create(:user) } - let_it_be(:group) { create(:group) } + let_it_be(:group) { create(:group, developers: developer, maintainers: maintainer) } let!(:achievement) { create(:achievement, namespace: group) } let(:mutation) { graphql_mutation(:achievements_update, params) } @@ -22,11 +22,6 @@ RSpec.describe Mutations::Achievements::Update, feature_category: :user_profile graphql_mutation_response(:achievements_update) end - before_all do - group.add_developer(developer) - group.add_maintainer(maintainer) - end - context 'when the user does not have permission' do let(:current_user) { developer } diff --git a/spec/requests/api/graphql/mutations/alert_management/alerts/set_assignees_spec.rb b/spec/requests/api/graphql/mutations/alert_management/alerts/set_assignees_spec.rb index 935856814c4..2d123ed0773 100644 --- a/spec/requests/api/graphql/mutations/alert_management/alerts/set_assignees_spec.rb +++ b/spec/requests/api/graphql/mutations/alert_management/alerts/set_assignees_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'Setting assignees of an alert', feature_category: :incident_mana include GraphqlHelpers let_it_be(:project) { create(:project) } - let_it_be(:current_user) { create(:user) } + let_it_be(:current_user) { create(:user, developer_of: project) } let_it_be(:alert) { create(:alert_management_alert, project: project) } let(:input) { { assignee_usernames: [current_user.username] } } @@ -31,10 +31,6 @@ RSpec.describe 'Setting assignees of an alert', feature_category: :incident_mana let(:mutation_response) { graphql_mutation_response(:alert_set_assignees) } - before_all do - project.add_developer(current_user) - end - it 'updates the assignee of the alert' do post_graphql_mutation(mutation, current_user: current_user) diff --git a/spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb b/spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb index 8e71d77f7bc..2d9fd1b0cb5 100644 --- a/spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb +++ b/spec/requests/api/graphql/mutations/boards/issues/issue_move_list_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'Reposition and move issue within board lists', feature_category: let_it_be(:group) { create(:group, :private) } let_it_be(:project) { create(:project, group: group) } let_it_be(:board) { create(:board, group: group) } - let_it_be(:user) { create(:user) } + let_it_be(:user) { create(:user, maintainer_of: group) } let_it_be(:development) { create(:label, project: project, name: 'Development') } let_it_be(:testing) { create(:label, project: project, name: 'Testing') } let_it_be(:list1) { create(:list, board: board, label: development, position: 0) } @@ -30,10 +30,6 @@ RSpec.describe 'Reposition and move issue within board lists', feature_category: } end - before_all do - group.add_maintainer(user) - end - shared_examples 'returns an error' do let(:message) do "The resource that you are attempting to access does not exist or you don't have " \ diff --git a/spec/requests/api/graphql/mutations/ci/job/play_spec.rb b/spec/requests/api/graphql/mutations/ci/job/play_spec.rb index 0c700248f85..89e1cd8d151 100644 --- a/spec/requests/api/graphql/mutations/ci/job/play_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/job/play_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'JobPlay', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project) } + let_it_be(:project) { create(:project, maintainers: user) } let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) } let_it_be(:job) { create(:ci_build, :playable, pipeline: pipeline, name: 'build') } @@ -34,10 +34,6 @@ RSpec.describe 'JobPlay', feature_category: :continuous_integration do let(:mutation_response) { graphql_mutation_response(:job_play) } - before_all do - project.add_maintainer(user) - end - it 'returns an error if the user is not allowed to play the job' do post_graphql_mutation(mutation, current_user: create(:user)) diff --git a/spec/requests/api/graphql/mutations/ci/job/retry_spec.rb b/spec/requests/api/graphql/mutations/ci/job/retry_spec.rb index 82988854719..5b73485e335 100644 --- a/spec/requests/api/graphql/mutations/ci/job/retry_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/job/retry_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'JobRetry', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project) } + let_it_be(:project) { create(:project, maintainers: user) } let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) } let(:job) { create(:ci_build, :success, pipeline: pipeline, name: 'build') } @@ -27,10 +27,6 @@ RSpec.describe 'JobRetry', feature_category: :continuous_integration do let(:mutation_response) { graphql_mutation_response(:job_retry) } - before_all do - project.add_maintainer(user) - end - it 'returns an error if the user is not allowed to retry the job' do post_graphql_mutation(mutation, current_user: create(:user)) diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb index be619394b6f..21cfb211b8b 100644 --- a/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'PipelineCancel', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project) } + let_it_be(:project) { create(:project, maintainers: user) } let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) } let(:mutation) do @@ -18,10 +18,6 @@ RSpec.describe 'PipelineCancel', feature_category: :continuous_integration do let(:mutation_response) { graphql_mutation_response(:pipeline_cancel) } - before_all do - project.add_maintainer(user) - end - it 'does not cancel any pipelines not owned by the current user' do build = create(:ci_build, :running, pipeline: pipeline) diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_retry_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_retry_spec.rb index 70b154946ef..102f79b6ced 100644 --- a/spec/requests/api/graphql/mutations/ci/pipeline_retry_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/pipeline_retry_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'PipelineRetry', feature_category: :continuous_integration do include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project) } + let_it_be(:project) { create(:project, maintainers: user) } let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) } let(:mutation) do @@ -27,10 +27,6 @@ RSpec.describe 'PipelineRetry', feature_category: :continuous_integration do let(:mutation_response) { graphql_mutation_response(:pipeline_retry) } - before_all do - project.add_maintainer(user) - end - it 'returns an error if the user is not allowed to retry the pipeline' do post_graphql_mutation(mutation, current_user: create(:user)) diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_schedule/take_ownership_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_schedule/take_ownership_spec.rb index 2d1f1565a73..133e1a68604 100644 --- a/spec/requests/api/graphql/mutations/ci/pipeline_schedule/take_ownership_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/pipeline_schedule/take_ownership_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'PipelineScheduleTakeOwnership', feature_category: :continuous_in let_it_be(:user) { create(:user) } let_it_be(:owner) { create(:user) } - let_it_be(:project) { create(:project) } + let_it_be(:project) { create(:project, maintainers: user) } let_it_be(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: owner) } let(:mutation) do @@ -22,10 +22,6 @@ RSpec.describe 'PipelineScheduleTakeOwnership', feature_category: :continuous_in let(:pipeline_schedule_id) { pipeline_schedule.to_global_id.to_s } - before_all do - project.add_maintainer(user) - end - it 'returns an error if the user is not allowed to take ownership of the schedule' do post_graphql_mutation(mutation, current_user: create(:user)) diff --git a/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb b/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb index 0e9317a4879..c1421af1c3d 100644 --- a/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb +++ b/spec/requests/api/graphql/mutations/environments/canary_ingress/update_spec.rb @@ -11,8 +11,8 @@ RSpec.describe 'Update Environment Canary Ingress', :clean_gitlab_redis_cache, f let_it_be(:service) { create(:cluster_platform_kubernetes, :configured, cluster: cluster) } let_it_be(:environment) { create(:environment, project: project) } let_it_be(:deployment) { create(:deployment, :success, environment: environment, project: project) } - let_it_be(:maintainer) { create(:user) } - let_it_be(:developer) { create(:user) } + let_it_be(:maintainer) { create(:user, maintainer_of: project) } + let_it_be(:developer) { create(:user, developer_of: project) } let(:environment_id) { environment.to_global_id.to_s } let(:weight) { 25 } @@ -22,11 +22,6 @@ RSpec.describe 'Update Environment Canary Ingress', :clean_gitlab_redis_cache, f graphql_mutation(:environments_canary_ingress_update, id: environment_id, weight: weight) end - before_all do - project.add_maintainer(maintainer) - project.add_developer(developer) - end - before do stub_kubeclient_ingresses(environment.deployment_namespace, response: kube_ingresses_response(with_canary: true)) end diff --git a/spec/requests/api/graphql/mutations/issues/set_escalation_status_spec.rb b/spec/requests/api/graphql/mutations/issues/set_escalation_status_spec.rb index 8fc3ad4236d..de1cffafd13 100644 --- a/spec/requests/api/graphql/mutations/issues/set_escalation_status_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_escalation_status_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'Setting the escalation status of an incident', feature_category: let_it_be(:project) { create(:project) } let_it_be(:issue) { create(:incident, project: project) } let_it_be(:escalation_status) { create(:incident_management_issuable_escalation_status, issue: issue) } - let_it_be(:user) { create(:user) } + let_it_be(:user) { create(:user, developer_of: project) } let(:status) { 'ACKNOWLEDGED' } let(:input) { { project_path: project.full_path, iid: issue.iid.to_s, status: status } } @@ -29,10 +29,6 @@ RSpec.describe 'Setting the escalation status of an incident', feature_category: let(:mutation_response) { graphql_mutation_response(:issue_set_escalation_status) } - before_all do - project.add_developer(user) - end - context 'when user does not have permission to edit the escalation status' do let(:current_user) { create(:user) } diff --git a/spec/requests/api/graphql/mutations/snippets/update_spec.rb b/spec/requests/api/graphql/mutations/snippets/update_spec.rb index b9dd7c562ab..0e60b047db4 100644 --- a/spec/requests/api/graphql/mutations/snippets/update_spec.rb +++ b/spec/requests/api/graphql/mutations/snippets/update_spec.rb @@ -197,7 +197,11 @@ RSpec.describe 'Updating a Snippet', feature_category: :source_code_management d context 'when not sessionless', :clean_gitlab_redis_sessions do before do - stub_session('warden.user.user.key' => [[current_user.id], current_user.authenticatable_salt]) + stub_session( + session_data: { + 'warden.user.user.key' => [[current_user.id], current_user.authenticatable_salt] + } + ) end it_behaves_like 'internal event tracking' do diff --git a/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb b/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb index 429aa06d9f1..9ad049fedc2 100644 --- a/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb +++ b/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'Marking all todos done', feature_category: :team_planning do let_it_be(:project) { create(:project) } let_it_be(:issue) { create(:issue, project: project) } - let_it_be(:current_user) { create(:user) } + let_it_be(:current_user) { create(:user, developer_of: project) } let_it_be(:author) { create(:user) } let_it_be(:other_user) { create(:user) } let_it_be(:other_user2) { create(:user) } @@ -32,10 +32,6 @@ RSpec.describe 'Marking all todos done', feature_category: :team_planning do ) end - before_all do - project.add_developer(current_user) - end - def mutation_response graphql_mutation_response(:todos_mark_all_done) end diff --git a/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb b/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb index c09f89ef567..620fff90af6 100644 --- a/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb +++ b/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'Marking todos done', feature_category: :team_planning do let_it_be(:project) { create(:project) } let_it_be(:issue) { create(:issue, project: project) } - let_it_be(:current_user) { create(:user) } + let_it_be(:current_user) { create(:user, developer_of: project) } let_it_be(:author) { create(:user) } let_it_be(:other_user) { create(:user) } @@ -33,10 +33,6 @@ RSpec.describe 'Marking todos done', feature_category: :team_planning do ) end - before_all do - project.add_developer(current_user) - end - def mutation_response graphql_mutation_response(:todo_mark_done) end diff --git a/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb b/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb index 4bbfc7b2f1d..6a0d622bae6 100644 --- a/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb +++ b/spec/requests/api/graphql/mutations/todos/restore_many_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'Restoring many Todos', feature_category: :team_planning do let_it_be(:project) { create(:project) } let_it_be(:issue) { create(:issue, project: project) } - let_it_be(:current_user) { create(:user) } + let_it_be(:current_user) { create(:user, developer_of: project) } let_it_be(:author) { create(:user) } let_it_be(:other_user) { create(:user) } @@ -34,10 +34,6 @@ RSpec.describe 'Restoring many Todos', feature_category: :team_planning do ) end - before_all do - project.add_developer(current_user) - end - def mutation_response graphql_mutation_response(:todo_restore_many) end diff --git a/spec/requests/api/graphql/mutations/todos/restore_spec.rb b/spec/requests/api/graphql/mutations/todos/restore_spec.rb index 1ebd04432be..d0504018e45 100644 --- a/spec/requests/api/graphql/mutations/todos/restore_spec.rb +++ b/spec/requests/api/graphql/mutations/todos/restore_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'Restoring Todos', feature_category: :team_planning do let_it_be(:project) { create(:project) } let_it_be(:issue) { create(:issue, project: project) } - let_it_be(:current_user) { create(:user) } + let_it_be(:current_user) { create(:user, developer_of: project) } let_it_be(:author) { create(:user) } let_it_be(:other_user) { create(:user) } @@ -33,10 +33,6 @@ RSpec.describe 'Restoring Todos', feature_category: :team_planning do ) end - before_all do - project.add_developer(current_user) - end - def mutation_response graphql_mutation_response(:todo_restore) end diff --git a/spec/requests/api/graphql/project/fork_targets_spec.rb b/spec/requests/api/graphql/project/fork_targets_spec.rb index 46c33666cfc..c5982fc9ed9 100644 --- a/spec/requests/api/graphql/project/fork_targets_spec.rb +++ b/spec/requests/api/graphql/project/fork_targets_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'getting a list of fork targets for a project', feature_category: let_it_be(:group) { create(:group) } let_it_be(:another_group) { create(:group) } let_it_be(:project) { create(:project, :private, group: group) } - let_it_be(:user) { create(:user, developer_of: project) } + let_it_be(:user) { create(:user, developer_of: project, owner_of: [group, another_group]) } let(:current_user) { user } let(:fields) do @@ -27,11 +27,6 @@ RSpec.describe 'getting a list of fork targets for a project', feature_category: ) end - before_all do - group.add_owner(user) - another_group.add_owner(user) - end - context 'when user has access to the project' do before do post_graphql(query, current_user: current_user) diff --git a/spec/requests/api/graphql/projects/projects_spec.rb b/spec/requests/api/graphql/projects/projects_spec.rb index 584f668ae86..9dcf4020ed0 100644 --- a/spec/requests/api/graphql/projects/projects_spec.rb +++ b/spec/requests/api/graphql/projects/projects_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'getting a collection of projects', feature_category: :source_cod include GraphqlHelpers let_it_be(:current_user) { create(:user) } - let_it_be(:group) { create(:group, name: 'public-group') } + let_it_be(:group) { create(:group, name: 'public-group', developers: current_user) } let_it_be(:projects) { create_list(:project, 5, :public, group: group) } let_it_be(:other_project) { create(:project, :public, group: group) } @@ -20,10 +20,6 @@ RSpec.describe 'getting a collection of projects', feature_category: :source_cod ) end - before_all do - group.add_developer(current_user) - end - context 'when providing full_paths filter' do let(:project_full_paths) { projects.map(&:full_path) } let(:filters) { { full_paths: project_full_paths } } diff --git a/spec/requests/api/graphql/user/user_achievements_query_spec.rb b/spec/requests/api/graphql/user/user_achievements_query_spec.rb index 2cdf7483d94..655386704ff 100644 --- a/spec/requests/api/graphql/user/user_achievements_query_spec.rb +++ b/spec/requests/api/graphql/user/user_achievements_query_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'UserAchievements', feature_category: :user_profile do include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:group) { create(:group, :private) } + let_it_be(:group) { create(:group, :private, guests: user) } let_it_be(:achievement) { create(:achievement, namespace: group) } let_it_be(:non_revoked_achievement) { create(:user_achievement, achievement: achievement, user: user) } let_it_be(:revoked_achievement) { create(:user_achievement, :revoked, achievement: achievement, user: user) } @@ -39,10 +39,6 @@ RSpec.describe 'UserAchievements', feature_category: :user_profile do let(:current_user) { user } - before_all do - group.add_guest(user) - end - before do post_graphql(query, current_user: current_user) end diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index a70bc2a850e..bcefc50ab91 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -11,18 +11,13 @@ RSpec.describe API::Groups, feature_category: :groups_and_projects do let_it_be(:user2) { create(:user) } let_it_be(:user3) { create(:user) } let_it_be(:admin) { create(:admin) } - let_it_be(:group1) { create(:group, path: 'some_path', avatar: File.open(uploaded_image_temp_path)) } - let_it_be(:group2) { create(:group, :private) } + let_it_be(:group1) { create(:group, path: 'some_path', avatar: File.open(uploaded_image_temp_path), owners: user1) } + let_it_be(:group2) { create(:group, :private, owners: user2) } let_it_be(:project1) { create(:project, namespace: group1) } let_it_be(:project2) { create(:project, namespace: group2, name: 'testing') } let_it_be(:project3) { create(:project, namespace: group1, path: 'test', visibility_level: Gitlab::VisibilityLevel::PRIVATE) } let_it_be(:archived_project) { create(:project, namespace: group1, archived: true) } - before_all do - group1.add_owner(user1) - group2.add_owner(user2) - end - shared_examples 'group avatar upload' do context 'when valid' do let(:file_path) { 'spec/fixtures/banana_sample.gif' } diff --git a/spec/requests/api/internal/kubernetes_spec.rb b/spec/requests/api/internal/kubernetes_spec.rb index a433686d5d9..f5894341e51 100644 --- a/spec/requests/api/internal/kubernetes_spec.rb +++ b/spec/requests/api/internal/kubernetes_spec.rb @@ -533,15 +533,19 @@ RSpec.describe API::Internal::Kubernetes, feature_category: :deployment_manageme def stub_user_session(user, csrf_token) stub_session( - 'warden.user.user.key' => [[user.id], user.authenticatable_salt], - '_csrf_token' => csrf_token + session_data: { + 'warden.user.user.key' => [[user.id], user.authenticatable_salt], + '_csrf_token' => csrf_token + } ) end def stub_user_session_with_no_user_id(user, csrf_token) stub_session( - 'warden.user.user.key' => [[nil], user.authenticatable_salt], - '_csrf_token' => csrf_token + session_data: { + 'warden.user.user.key' => [[nil], user.authenticatable_salt], + '_csrf_token' => csrf_token + } ) end diff --git a/spec/requests/api/issues/get_project_issues_spec.rb b/spec/requests/api/issues/get_project_issues_spec.rb index 7dabe517553..ca79547d584 100644 --- a/spec/requests/api/issues/get_project_issues_spec.rb +++ b/spec/requests/api/issues/get_project_issues_spec.rb @@ -4,16 +4,16 @@ require 'spec_helper' RSpec.describe API::Issues, feature_category: :team_planning do let_it_be(:user) { create(:user) } - let_it_be(:project, reload: true) { create(:project, :public, :repository, creator_id: user.id, namespace: user.namespace) } + let_it_be(:project, reload: true) { create(:project, :public, :repository, creator_id: user.id, namespace: user.namespace, reporters: user) } let_it_be(:private_mrs_project) do create(:project, :public, :repository, creator_id: user.id, namespace: user.namespace, merge_requests_access_level: ProjectFeature::PRIVATE) end - let_it_be(:group) { create(:group, :public) } + let_it_be(:group) { create(:group, :public, reporters: user) } let_it_be(:user2) { create(:user) } let_it_be(:non_member) { create(:user) } - let_it_be(:guest) { create(:user) } + let_it_be(:guest) { create(:user, guest_of: [group, project]) } let_it_be(:author) { create(:author) } let_it_be(:assignee) { create(:assignee) } let_it_be(:admin) { create(:user, :admin) } @@ -90,10 +90,6 @@ RSpec.describe API::Issues, feature_category: :team_planning do end before_all do - group.add_reporter(user) - group.add_guest(guest) - project.add_reporter(user) - project.add_guest(guest) private_mrs_project.add_reporter(user) private_mrs_project.add_guest(guest) end diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb index fb7f86a423d..45ac19c2f8a 100644 --- a/spec/requests/api/issues/issues_spec.rb +++ b/spec/requests/api/issues/issues_spec.rb @@ -6,14 +6,14 @@ RSpec.describe API::Issues, feature_category: :team_planning do using RSpec::Parameterized::TableSyntax let_it_be(:user) { create(:user) } - let_it_be(:project, reload: true) { create(:project, :public, :repository, creator_id: user.id, namespace: user.namespace) } + let_it_be(:project, reload: true) { create(:project, :public, :repository, creator_id: user.id, namespace: user.namespace, reporters: user) } let_it_be(:private_mrs_project) do create(:project, :public, :repository, creator_id: user.id, namespace: user.namespace, merge_requests_access_level: ProjectFeature::PRIVATE) end let_it_be(:user2) { create(:user) } let_it_be(:non_member) { create(:user) } - let_it_be(:guest) { create(:user) } + let_it_be(:guest) { create(:user, guest_of: project) } let_it_be(:author) { create(:author) } let_it_be(:assignee) { create(:assignee) } let_it_be(:admin) { create(:user, :admin) } @@ -73,8 +73,6 @@ RSpec.describe API::Issues, feature_category: :team_planning do let(:any_milestone_title) { 'Any' } before_all do - project.add_reporter(user) - project.add_guest(guest) private_mrs_project.add_reporter(user) private_mrs_project.add_guest(guest) end diff --git a/spec/requests/api/project_container_repositories_spec.rb b/spec/requests/api/project_container_repositories_spec.rb index 8ba05905596..bbeb56045d4 100644 --- a/spec/requests/api/project_container_repositories_spec.rb +++ b/spec/requests/api/project_container_repositories_spec.rb @@ -7,10 +7,10 @@ RSpec.describe API::ProjectContainerRepositories, feature_category: :container_r let_it_be(:project) { create(:project, :private) } let_it_be(:project2) { create(:project, :public) } - let_it_be(:maintainer) { create(:user) } - let_it_be(:developer) { create(:user) } - let_it_be(:reporter) { create(:user) } - let_it_be(:guest) { create(:user) } + let_it_be(:maintainer) { create(:user, maintainer_of: [project, project2]) } + let_it_be(:developer) { create(:user, developer_of: [project, project2]) } + let_it_be(:reporter) { create(:user, reporter_of: [project, project2]) } + let_it_be(:guest) { create(:user, guest_of: [project, project2]) } let(:root_repository) { create(:container_repository, :root, project: project) } let(:test_repository) { create(:container_repository, project: project) } @@ -38,18 +38,6 @@ RSpec.describe API::ProjectContainerRepositories, feature_category: :container_r property: 'i_package_container_user' } end - before_all do - project.add_maintainer(maintainer) - project.add_developer(developer) - project.add_reporter(reporter) - project.add_guest(guest) - - project2.add_maintainer(maintainer) - project2.add_developer(developer) - project2.add_reporter(reporter) - project2.add_guest(guest) - end - before do root_repository test_repository diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb index 098468b6a13..0395a12da8a 100644 --- a/spec/requests/api/project_hooks_spec.rb +++ b/spec/requests/api/project_hooks_spec.rb @@ -6,7 +6,10 @@ RSpec.describe API::ProjectHooks, 'ProjectHooks', feature_category: :webhooks do include StubRequests let_it_be(:user) { create(:user) } let_it_be(:user3) { create(:user) } - let_it_be_with_reload(:project) { create(:project, :repository, creator_id: user.id, namespace: user.namespace) } + let_it_be_with_reload(:project) do + create(:project, :repository, creator_id: user.id, namespace: user.namespace, maintainers: user, developers: user3) + end + let_it_be_with_refind(:hook) do create( :project_hook, @@ -18,11 +21,6 @@ RSpec.describe API::ProjectHooks, 'ProjectHooks', feature_category: :webhooks do ) end - before_all do - project.add_maintainer(user) - project.add_developer(user3) - end - it_behaves_like 'web-hook API endpoints', '/projects/:id' do let(:unauthorized_user) { user3 } diff --git a/spec/requests/api/project_milestones_spec.rb b/spec/requests/api/project_milestones_spec.rb index e4b579b96cc..30e0ccdd1f3 100644 --- a/spec/requests/api/project_milestones_spec.rb +++ b/spec/requests/api/project_milestones_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe API::ProjectMilestones, feature_category: :team_planning do let_it_be(:user) { create(:user) } - let_it_be_with_reload(:project) { create(:project, namespace: user.namespace) } + let_it_be_with_reload(:project) { create(:project, namespace: user.namespace, reporters: user) } let_it_be(:closed_milestone) { create(:closed_milestone, project: project, title: 'version1', description: 'closed milestone') } let_it_be(:route) { "/projects/#{project.id}/milestones" } let_it_be(:milestone) do @@ -13,10 +13,6 @@ RSpec.describe API::ProjectMilestones, feature_category: :team_planning do let(:params) { {} } - before_all do - project.add_reporter(user) - end - it_behaves_like 'group and project milestones', "/projects/:id/milestones" shared_examples 'listing all milestones' do diff --git a/spec/requests/api/protected_branches_spec.rb b/spec/requests/api/protected_branches_spec.rb index b79cff5a905..ece5cad08e1 100644 --- a/spec/requests/api/protected_branches_spec.rb +++ b/spec/requests/api/protected_branches_spec.rb @@ -4,9 +4,9 @@ require 'spec_helper' RSpec.describe API::ProtectedBranches, feature_category: :source_code_management do let_it_be_with_reload(:project) { create(:project, :repository) } - let_it_be(:maintainer) { create(:user) } - let_it_be(:developer) { create(:user) } - let_it_be(:guest) { create(:user) } + let_it_be(:maintainer) { create(:user, maintainer_of: project) } + let_it_be(:developer) { create(:user, developer_of: project) } + let_it_be(:guest) { create(:user, guest_of: project) } let(:protected_name) { 'feature' } let(:branch_name) { protected_name } @@ -15,12 +15,6 @@ RSpec.describe API::ProtectedBranches, feature_category: :source_code_management create(:protected_branch, project: project, name: protected_name) end - before_all do - project.add_maintainer(maintainer) - project.add_developer(developer) - project.add_guest(guest) - end - describe "GET /projects/:id/protected_branches" do let(:params) { {} } let(:route) { "/projects/#{project.id}/protected_branches" } diff --git a/spec/requests/api/todos_spec.rb b/spec/requests/api/todos_spec.rb index c9e62a430e0..a356736cc1e 100644 --- a/spec/requests/api/todos_spec.rb +++ b/spec/requests/api/todos_spec.rb @@ -11,7 +11,7 @@ RSpec.describe API::Todos, feature_category: :source_code_management do let_it_be(:project_2) { create(:project) } let_it_be(:author_1) { create(:user) } let_it_be(:author_2) { create(:user) } - let_it_be(:john_doe) { create(:user, username: 'john_doe') } + let_it_be(:john_doe) { create(:user, username: 'john_doe', developer_of: [project_1, project_2]) } let_it_be(:issue) { create(:issue, project: project_1) } let_it_be(:work_item) { create(:work_item, :task, project: project_1) } let_it_be(:merge_request) { create(:merge_request, source_project: project_1) } @@ -30,11 +30,6 @@ RSpec.describe API::Todos, feature_category: :source_code_management do let_it_be(:award_emoji_2) { create(:award_emoji, awardable: pending_1.target, user: author_1, name: 'thumbsup') } let_it_be(:award_emoji_3) { create(:award_emoji, awardable: pending_2.target, user: author_2, name: 'thumbsdown') } - before_all do - project_1.add_developer(john_doe) - project_2.add_developer(john_doe) - end - describe 'GET /todos' do context 'when unauthenticated' do it 'returns authentication error' do diff --git a/spec/requests/groups/autocomplete_sources_spec.rb b/spec/requests/groups/autocomplete_sources_spec.rb index 5d190074534..2169254fcd1 100644 --- a/spec/requests/groups/autocomplete_sources_spec.rb +++ b/spec/requests/groups/autocomplete_sources_spec.rb @@ -4,11 +4,7 @@ require 'spec_helper' RSpec.describe 'groups autocomplete', feature_category: :groups_and_projects do let_it_be(:user) { create(:user) } - let_it_be_with_reload(:group) { create(:group, :private) } - - before_all do - group.add_developer(user) - end + let_it_be_with_reload(:group) { create(:group, :private, developers: user) } before do sign_in(user) diff --git a/spec/requests/groups/settings/access_tokens_controller_spec.rb b/spec/requests/groups/settings/access_tokens_controller_spec.rb index a09feeea786..b38c40515be 100644 --- a/spec/requests/groups/settings/access_tokens_controller_spec.rb +++ b/spec/requests/groups/settings/access_tokens_controller_spec.rb @@ -4,13 +4,8 @@ require 'spec_helper' RSpec.describe Groups::Settings::AccessTokensController, feature_category: :system_access do let_it_be(:user) { create(:user) } - let_it_be(:resource) { create(:group) } - let_it_be(:access_token_user) { create(:user, :project_bot) } - - before_all do - resource.add_owner(user) - resource.add_maintainer(access_token_user) - end + let_it_be(:resource) { create(:group, owners: user) } + let_it_be(:access_token_user) { create(:user, :project_bot, maintainer_of: resource) } before do sign_in(user) diff --git a/spec/requests/groups/settings/slacks_controller_spec.rb b/spec/requests/groups/settings/slacks_controller_spec.rb index a705d8ba9ea..97c2180a6d7 100644 --- a/spec/requests/groups/settings/slacks_controller_spec.rb +++ b/spec/requests/groups/settings/slacks_controller_spec.rb @@ -4,11 +4,7 @@ require 'spec_helper' RSpec.describe Groups::Settings::SlacksController, feature_category: :integrations do let_it_be(:group) { create(:group) } - let_it_be(:user) { create(:user) } - - before_all do - group.add_owner(user) - end + let_it_be(:user) { create(:user, owner_of: group) } before do sign_in(user) diff --git a/spec/requests/projects/alert_management_controller_spec.rb b/spec/requests/projects/alert_management_controller_spec.rb index 698087bf761..4cc8beb0b2d 100644 --- a/spec/requests/projects/alert_management_controller_spec.rb +++ b/spec/requests/projects/alert_management_controller_spec.rb @@ -4,15 +4,10 @@ require 'spec_helper' RSpec.describe Projects::AlertManagementController, feature_category: :incident_management do let_it_be(:project) { create(:project) } - let_it_be(:developer) { create(:user) } - let_it_be(:reporter) { create(:user) } + let_it_be(:developer) { create(:user, developer_of: project) } + let_it_be(:reporter) { create(:user, reporter_of: project) } let_it_be(:id) { 1 } - before_all do - project.add_developer(developer) - project.add_reporter(reporter) - end - before do sign_in(user) end diff --git a/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb b/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb index 427eff8cd76..936774b866f 100644 --- a/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb +++ b/spec/requests/projects/google_cloud/revoke_oauth_controller_spec.rb @@ -14,7 +14,7 @@ RSpec.describe Projects::GoogleCloud::RevokeOauthController, feature_category: : before do sign_in(user) - stub_session(GoogleApi::CloudPlatform::Client.session_key_for_token => 'token') + stub_session(session_data: { GoogleApi::CloudPlatform::Client.session_key_for_token => 'token' }) allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client| allow(client).to receive(:validate_token).and_return(true) diff --git a/spec/requests/projects/redirect_controller_spec.rb b/spec/requests/projects/redirect_controller_spec.rb index 962d8062161..46b233b353c 100644 --- a/spec/requests/projects/redirect_controller_spec.rb +++ b/spec/requests/projects/redirect_controller_spec.rb @@ -7,11 +7,7 @@ RSpec.describe "Projects::RedirectController requests", feature_category: :group let_it_be(:private_project) { create(:project, :private) } let_it_be(:public_project) { create(:project, :public) } - let_it_be(:user) { create(:user) } - - before_all do - private_project.add_developer(user) - end + let_it_be(:user) { create(:user, developer_of: private_project) } describe 'GET redirect_from_id' do where(:authenticated, :project, :is_found) do diff --git a/spec/requests/projects/settings/access_tokens_controller_spec.rb b/spec/requests/projects/settings/access_tokens_controller_spec.rb index 8e0d3fed3d3..a354e3a42bd 100644 --- a/spec/requests/projects/settings/access_tokens_controller_spec.rb +++ b/spec/requests/projects/settings/access_tokens_controller_spec.rb @@ -5,13 +5,8 @@ require 'spec_helper' RSpec.describe Projects::Settings::AccessTokensController, feature_category: :system_access do let_it_be(:user) { create(:user) } let_it_be(:group) { create(:group) } - let_it_be(:resource) { create(:project, group: group) } - let_it_be(:access_token_user) { create(:user, :project_bot) } - - before_all do - resource.add_maintainer(user) - resource.add_maintainer(access_token_user) - end + let_it_be(:resource) { create(:project, group: group, maintainers: user) } + let_it_be(:access_token_user) { create(:user, :project_bot, maintainer_of: resource) } before do sign_in(user) diff --git a/spec/requests/projects/settings/slacks_controller_spec.rb b/spec/requests/projects/settings/slacks_controller_spec.rb index 6690b6af6f4..6cd22d90cec 100644 --- a/spec/requests/projects/settings/slacks_controller_spec.rb +++ b/spec/requests/projects/settings/slacks_controller_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe Projects::Settings::SlacksController, feature_category: :integrations do let_it_be(:project) { create(:project) } - let_it_be(:user) { create(:user) } + let_it_be(:user) { create(:user, maintainer_of: project) } let(:redirect_url) do edit_project_settings_integration_path( @@ -13,10 +13,6 @@ RSpec.describe Projects::Settings::SlacksController, feature_category: :integrat ) end - before_all do - project.add_maintainer(user) - end - before do sign_in(user) end diff --git a/spec/requests/verifies_with_email_spec.rb b/spec/requests/verifies_with_email_spec.rb index c8a0c0975a3..15d85ae82eb 100644 --- a/spec/requests/verifies_with_email_spec.rb +++ b/spec/requests/verifies_with_email_spec.rb @@ -147,7 +147,7 @@ RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_ before do encrypted_token = Devise.token_generator.digest(User, user.email, 'token') user.update!(locked_at: Time.current, unlock_token: encrypted_token) - stub_session(verification_user_id: user.id) + stub_session(session_data: { verification_user_id: user.id }) end context 'when rate limited and a verification_token param exists' do @@ -305,7 +305,7 @@ RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_ context 'when a verification_user_id session variable exists' do before do - stub_session(verification_user_id: user.id) + stub_session(session_data: { verification_user_id: user.id }) perform_enqueued_jobs do post(users_resend_verification_code_path) @@ -319,7 +319,7 @@ RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_ before do allow(Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(true) - stub_session(verification_user_id: user.id) + stub_session(session_data: { verification_user_id: user.id }) perform_enqueued_jobs do post(users_resend_verification_code_path) @@ -355,7 +355,7 @@ RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_ context 'when a verification_user_id session variable exists' do before do - stub_session(verification_user_id: user.id) + stub_session(session_data: { verification_user_id: user.id }) end it 'locks the user' do @@ -397,7 +397,7 @@ RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_ end before do - stub_session(verification_user_id: user.id) + stub_session(session_data: { verification_user_id: user.id }) end it 'calls the UpdateEmailService and returns an error response' do @@ -419,7 +419,7 @@ RSpec.describe 'VerifiesWithEmail', :clean_gitlab_redis_sessions, :clean_gitlab_ end it 'renders the template and removes the verification_user_id session variable' do - stub_session(verification_user_id: user.id) + stub_session(session_data: { verification_user_id: user.id }) get(users_successful_verification_path) diff --git a/spec/routing/user_routing_spec.rb b/spec/routing/user_routing_spec.rb index b155560c9f0..7aa6a8c731c 100644 --- a/spec/routing/user_routing_spec.rb +++ b/spec/routing/user_routing_spec.rb @@ -11,7 +11,7 @@ RSpec.describe 'user routing', :clean_gitlab_redis_sessions, feature_category: : context 'when GitHub OAuth on sign in is cancelled' do before do - stub_session(auth_on_failure_path: '/projects/new#import_project') + stub_session(session_data: { auth_on_failure_path: '/projects/new#import_project' }) end context 'when all required parameters are present' do diff --git a/spec/support/helpers/session_helpers.rb b/spec/support/helpers/session_helpers.rb index ead9087d7a8..359bc5039dc 100644 --- a/spec/support/helpers/session_helpers.rb +++ b/spec/support/helpers/session_helpers.rb @@ -3,7 +3,7 @@ module SessionHelpers # Stub a session in Redis, for use in request specs where we can't mock the session directly. # This also needs the :clean_gitlab_redis_sessions tag on the spec. - def stub_session(user_id: nil, **session_hash) + def stub_session(session_data:, user_id: nil) unless RSpec.current_example.metadata[:clean_gitlab_redis_sessions] raise 'Add :clean_gitlab_redis_sessions to your spec!' end @@ -11,7 +11,7 @@ module SessionHelpers session_id = Rack::Session::SessionId.new(SecureRandom.hex) Gitlab::Redis::Sessions.with do |redis| - redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash)) + redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_data)) redis.sadd("session:lookup:user:gitlab:#{user_id}", [session_id.private_id]) if user_id end diff --git a/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb index 8ed3464b009..82a2c0dd7cb 100644 --- a/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb @@ -22,7 +22,11 @@ RSpec.shared_examples 'snippet edit usage data counters' do context 'when user is not sessionless', :clean_gitlab_redis_sessions do before do - stub_session('warden.user.user.key' => [[current_user.id], current_user.authenticatable_salt]) + stub_session( + session_data: { + 'warden.user.user.key' => [[current_user.id], current_user.authenticatable_salt] + } + ) end subject do diff --git a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb index ca6c2ec4f29..89ae165f3fa 100644 --- a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb +++ b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb @@ -683,7 +683,7 @@ RSpec.shared_examples 'rate-limited frontend API requests' do "#{throttle_setting_prefix}_deprecated_api_enabled" => true ) - stub_session(**csrf_session) + stub_session(session_data: csrf_session) end context 'with a CSRF token' do @@ -703,7 +703,7 @@ RSpec.shared_examples 'rate-limited frontend API requests' do end context 'without a CSRF session' do - let(:csrf_session) { {} } + let(:csrf_session) { nil } it 'always uses the rate limit for API requests' do requests_per_period.times { get_api csrf: true }