Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
3456ec38df
commit
9ee836ec2b
2
Gemfile
2
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
|
||||
|
|
|
|||
|
|
@ -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"},
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ export default {
|
|||
:id="computedJobId"
|
||||
class="ci-job-group-dropdown"
|
||||
block
|
||||
fluid-width
|
||||
placement="right-start"
|
||||
data-testid="job-dropdown-container"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1493,6 +1493,31 @@ Input type: `AiAgentCreateInput`
|
|||
| <a id="mutationaiagentcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationaiagentcreateerrors"></a>`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 |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationaiagentdestroyagentid"></a>`agentId` | [`AiAgentID!`](#aiagentid) | Global ID of the AI Agent to be deleted. |
|
||||
| <a id="mutationaiagentdestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationaiagentdestroyprojectpath"></a>`projectPath` | [`ID!`](#id) | Project to which the agent belongs. |
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationaiagentdestroyagent"></a>`agent` | [`AiAgent`](#aiagent) | Agent after mutation. |
|
||||
| <a id="mutationaiagentdestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationaiagentdestroyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
| <a id="mutationaiagentdestroymessage"></a>`message` | [`String`](#string) | AI Agent deletion result message. |
|
||||
|
||||
### `Mutation.aiAgentUpdate`
|
||||
|
||||
DETAILS:
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
<!-- vale gitlab.Spelling = NO -->
|
||||
|
||||
An easy list of classes can also be [seen on Unpkg](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss).
|
||||
|
||||
<!-- vale gitlab.Spelling = YES -->
|
||||
|
||||
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;
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
|
||||
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).
|
||||
<!-- Video published on 2024-05-15 -->
|
||||
|
||||
## 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).
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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 ""
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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 " \
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 } }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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' }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
Loading…
Reference in New Issue