Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
c48bbe6650
commit
bc7374e612
194 changed files with 763 additions and 241 deletions
6
Gemfile
6
Gemfile
|
@ -11,7 +11,7 @@ gem 'responders', '~> 3.0'
|
|||
|
||||
gem 'sprockets', '~> 3.7.0'
|
||||
|
||||
gem 'view_component', '~> 2.61'
|
||||
gem 'view_component', '~> 2.69.0'
|
||||
|
||||
# Default values for AR models
|
||||
gem 'default_value_for', '~> 3.4.0'
|
||||
|
@ -272,7 +272,9 @@ gem 'babosa', '~> 1.0.4'
|
|||
gem 'loofah', '~> 2.18.0'
|
||||
|
||||
# Working with license
|
||||
gem 'licensee', '~> 9.14.1'
|
||||
# Detects the open source license the repository includes
|
||||
# This version needs to be in sync with gitlab-org/gitaly
|
||||
gem 'licensee', '~> 9.15'
|
||||
|
||||
# Detect and convert string character encoding
|
||||
gem 'charlock_holmes', '~> 0.7.7'
|
||||
|
|
11
Gemfile.lock
11
Gemfile.lock
|
@ -773,9 +773,9 @@ GEM
|
|||
tomlrb (>= 1.3, < 2.1)
|
||||
with_env (= 1.1.0)
|
||||
xml-simple (~> 1.1.9)
|
||||
licensee (9.14.1)
|
||||
licensee (9.15.2)
|
||||
dotenv (~> 2.0)
|
||||
octokit (~> 4.17)
|
||||
octokit (~> 4.20)
|
||||
reverse_markdown (~> 1.0)
|
||||
rugged (>= 0.24, < 2.0)
|
||||
thor (>= 0.19, < 2.0)
|
||||
|
@ -1440,8 +1440,9 @@ GEM
|
|||
activesupport (>= 3.0)
|
||||
version_gem (1.0.0)
|
||||
version_sorter (2.2.4)
|
||||
view_component (2.61.0)
|
||||
view_component (2.69.0)
|
||||
activesupport (>= 5.0.0, < 8.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
method_source (~> 1.0)
|
||||
vmstat (2.3.0)
|
||||
warden (1.2.8)
|
||||
|
@ -1631,7 +1632,7 @@ DEPENDENCIES
|
|||
lefthook (~> 1.1.0)
|
||||
letter_opener_web (~> 2.0.0)
|
||||
license_finder (~> 7.0)
|
||||
licensee (~> 9.14.1)
|
||||
licensee (~> 9.15)
|
||||
lockbox (~> 0.6.2)
|
||||
lograge (~> 0.5)
|
||||
loofah (~> 2.18.0)
|
||||
|
@ -1771,7 +1772,7 @@ DEPENDENCIES
|
|||
valid_email (~> 0.1)
|
||||
validates_hostname (~> 1.0.11)
|
||||
version_sorter (~> 2.2.4)
|
||||
view_component (~> 2.61)
|
||||
view_component (~> 2.69.0)
|
||||
vmstat (~> 2.3.0)
|
||||
warning (~> 1.3.0)
|
||||
webauthn (~> 2.3)
|
||||
|
|
|
@ -16,6 +16,16 @@ export default {
|
|||
import('ee_component/access_tokens/components/max_expiration_date_message.vue'),
|
||||
},
|
||||
props: {
|
||||
defaultDateOffset: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 30,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
inputAttrs: {
|
||||
type: Object,
|
||||
required: false,
|
||||
|
@ -33,9 +43,15 @@ export default {
|
|||
},
|
||||
},
|
||||
computed: {
|
||||
in30Days() {
|
||||
const today = new Date();
|
||||
return getDateInFuture(today, 30);
|
||||
defaultDate() {
|
||||
const defaultDate = getDateInFuture(new Date(), this.defaultDateOffset);
|
||||
// The maximum date can be set by admins. If the maximum date is sooner
|
||||
// than the default expiration date we use the maximum date as default
|
||||
// expiration date.
|
||||
if (this.maxDate && this.maxDate < defaultDate) {
|
||||
return this.maxDate;
|
||||
}
|
||||
return defaultDate;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -47,7 +63,7 @@ export default {
|
|||
:target="null"
|
||||
:min-date="minDate"
|
||||
:max-date="maxDate"
|
||||
:default-date="in30Days"
|
||||
:default-date="defaultDate"
|
||||
show-clear-button
|
||||
:input-name="inputAttrs.name"
|
||||
:input-id="inputAttrs.id"
|
||||
|
@ -55,7 +71,10 @@ export default {
|
|||
data-qa-selector="expiry_date_field"
|
||||
/>
|
||||
<template #description>
|
||||
<max-expiration-date-message :max-date="maxDate" />
|
||||
<template v-if="description">
|
||||
{{ description }}
|
||||
</template>
|
||||
<max-expiration-date-message v-else :max-date="maxDate" />
|
||||
</template>
|
||||
</gl-form-group>
|
||||
</template>
|
||||
|
|
|
@ -61,7 +61,7 @@ export const initExpiresAtField = () => {
|
|||
}
|
||||
|
||||
const { expiresAt: inputAttrs } = parseRailsFormFields(el);
|
||||
const { minDate, maxDate } = el.dataset;
|
||||
const { minDate, maxDate, defaultDateOffset, description } = el.dataset;
|
||||
|
||||
return new Vue({
|
||||
el,
|
||||
|
@ -71,6 +71,8 @@ export const initExpiresAtField = () => {
|
|||
inputAttrs,
|
||||
minDate: minDate ? new Date(minDate) : undefined,
|
||||
maxDate: maxDate ? new Date(maxDate) : undefined,
|
||||
defaultDateOffset: defaultDateOffset ? Number(defaultDateOffset) : undefined,
|
||||
description,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
|
|
@ -71,15 +71,12 @@ export const DIFF_FILE_MANUAL_COLLAPSE = 'manual';
|
|||
export const STATE_IDLING = 'idle';
|
||||
export const STATE_LOADING = 'loading';
|
||||
export const STATE_ERRORED = 'errored';
|
||||
export const STATE_PENDING_REVIEW = 'pending_comments';
|
||||
|
||||
// State machine transitions
|
||||
export const TRANSITION_LOAD_START = 'LOAD_START';
|
||||
export const TRANSITION_LOAD_ERROR = 'LOAD_ERROR';
|
||||
export const TRANSITION_LOAD_SUCCEED = 'LOAD_SUCCEED';
|
||||
export const TRANSITION_ACKNOWLEDGE_ERROR = 'ACKNOWLEDGE_ERROR';
|
||||
export const TRANSITION_HAS_PENDING_REVIEW = 'PENDING_REVIEW';
|
||||
export const TRANSITION_NO_REVIEW = 'NO_REVIEW';
|
||||
|
||||
export const RENAMED_DIFF_TRANSITIONS = {
|
||||
[`${STATE_IDLING}:${TRANSITION_LOAD_START}`]: STATE_LOADING,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import initConfirmModal from '~/confirm_modal';
|
||||
import AddSshKeyValidation from '~/profile/add_ssh_key_validation';
|
||||
import { initExpiresAtField } from '~/access_tokens/index';
|
||||
|
||||
initConfirmModal();
|
||||
|
||||
|
@ -23,3 +24,5 @@ function initSshKeyValidation() {
|
|||
}
|
||||
|
||||
initSshKeyValidation();
|
||||
|
||||
initExpiresAtField();
|
||||
|
|
|
@ -148,6 +148,7 @@ export default {
|
|||
:class="{ open: showDescription }"
|
||||
:title="__('Toggle commit description')"
|
||||
:aria-label="__('Toggle commit description')"
|
||||
:selected="showDescription"
|
||||
class="text-expander gl-vertical-align-bottom!"
|
||||
icon="ellipsis_h"
|
||||
@click="toggleShowDescription"
|
||||
|
|
27
app/finders/database/batched_background_migrations_finder.rb
Normal file
27
app/finders/database/batched_background_migrations_finder.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Database
|
||||
class BatchedBackgroundMigrationsFinder
|
||||
RETURNED_MIGRATIONS = 20
|
||||
|
||||
def initialize(connection:)
|
||||
@connection = connection
|
||||
end
|
||||
|
||||
def execute
|
||||
batched_migration_class.ordered_by_created_at_desc.for_gitlab_schema(schema).limit(RETURNED_MIGRATIONS)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_accessor :connection
|
||||
|
||||
def batched_migration_class
|
||||
Gitlab::Database::BackgroundMigration::BatchedMigration
|
||||
end
|
||||
|
||||
def schema
|
||||
Gitlab::Database.gitlab_schemas_for_connection(connection)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -53,7 +53,7 @@ module ProfilesHelper
|
|||
|
||||
# Overridden in EE::ProfilesHelper#ssh_key_expires_field_description
|
||||
def ssh_key_expires_field_description
|
||||
s_('Profiles|Key becomes invalid on this date.')
|
||||
s_('Profiles|Optional but recommended. If set, key becomes invalid on the specified date.')
|
||||
end
|
||||
|
||||
# Overridden in EE::ProfilesHelper#ssh_key_expiration_policy_enabled?
|
||||
|
|
|
@ -61,7 +61,7 @@ module SystemNotes
|
|||
def change_assignee(assignee)
|
||||
body = assignee.nil? ? 'removed assignee' : "assigned to #{assignee.to_reference}"
|
||||
|
||||
issue_activity_counter.track_issue_assignee_changed_action(author: author) if noteable.is_a?(Issue)
|
||||
issue_activity_counter.track_issue_assignee_changed_action(author: author, project: project) if noteable.is_a?(Issue)
|
||||
|
||||
create_note(NoteSummary.new(noteable, project, author, body, action: 'assignee'))
|
||||
end
|
||||
|
@ -93,7 +93,7 @@ module SystemNotes
|
|||
|
||||
body = text_parts.join(' and ')
|
||||
|
||||
issue_activity_counter.track_issue_assignee_changed_action(author: author) if noteable.is_a?(Issue)
|
||||
issue_activity_counter.track_issue_assignee_changed_action(author: author, project: project) if noteable.is_a?(Issue)
|
||||
|
||||
create_note(NoteSummary.new(noteable, project, author, body, action: 'assignee'))
|
||||
end
|
||||
|
@ -172,7 +172,7 @@ module SystemNotes
|
|||
|
||||
body = "changed title from **#{marked_old_title}** to **#{marked_new_title}**"
|
||||
|
||||
issue_activity_counter.track_issue_title_changed_action(author: author) if noteable.is_a?(Issue)
|
||||
issue_activity_counter.track_issue_title_changed_action(author: author, project: project) if noteable.is_a?(Issue)
|
||||
work_item_activity_counter.track_work_item_title_changed_action(author: author) if noteable.is_a?(WorkItem)
|
||||
|
||||
create_note(NoteSummary.new(noteable, project, author, body, action: 'title'))
|
||||
|
@ -210,7 +210,7 @@ module SystemNotes
|
|||
def change_description
|
||||
body = 'changed the description'
|
||||
|
||||
issue_activity_counter.track_issue_description_changed_action(author: author) if noteable.is_a?(Issue)
|
||||
issue_activity_counter.track_issue_description_changed_action(author: author, project: project) if noteable.is_a?(Issue)
|
||||
|
||||
create_note(NoteSummary.new(noteable, project, author, body, action: 'description'))
|
||||
end
|
||||
|
@ -280,7 +280,7 @@ module SystemNotes
|
|||
status_label = new_task.complete? ? Taskable::COMPLETED : Taskable::INCOMPLETE
|
||||
body = "marked the checklist item **#{new_task.source}** as #{status_label}"
|
||||
|
||||
issue_activity_counter.track_issue_description_changed_action(author: author) if noteable.is_a?(Issue)
|
||||
issue_activity_counter.track_issue_description_changed_action(author: author, project: project) if noteable.is_a?(Issue)
|
||||
|
||||
create_note(NoteSummary.new(noteable, project, author, body, action: 'task'))
|
||||
end
|
||||
|
@ -346,12 +346,12 @@ module SystemNotes
|
|||
body = 'made the issue confidential'
|
||||
action = 'confidential'
|
||||
|
||||
issue_activity_counter.track_issue_made_confidential_action(author: author) if noteable.is_a?(Issue)
|
||||
issue_activity_counter.track_issue_made_confidential_action(author: author, project: project) if noteable.is_a?(Issue)
|
||||
else
|
||||
body = 'made the issue visible to everyone'
|
||||
action = 'visible'
|
||||
|
||||
issue_activity_counter.track_issue_made_visible_action(author: author) if noteable.is_a?(Issue)
|
||||
issue_activity_counter.track_issue_made_visible_action(author: author, project: project) if noteable.is_a?(Issue)
|
||||
end
|
||||
|
||||
create_note(NoteSummary.new(noteable, project, author, body, action: action))
|
||||
|
|
|
@ -13,10 +13,12 @@
|
|||
= f.text_field :title, class: "form-control gl-form-input input-lg qa-key-title-field", required: true, placeholder: s_('Profiles|Example: MacBook key')
|
||||
%p.form-text.text-muted= s_('Profiles|Key titles are publicly visible.')
|
||||
|
||||
.form-row
|
||||
.col.form-group
|
||||
= f.label :expires_at, s_('Profiles|Expiration date'), class: 'label-bold'
|
||||
= f.date_field :expires_at, class: "form-control input-lg", min: Date.tomorrow, max: max_date, data: { qa_selector: 'key_expiry_date_field' }
|
||||
%p.form-text.text-muted{ data: { qa_selector: 'key_expiry_date_field_description' } }= ssh_key_expires_field_description
|
||||
.js-access-tokens-expires-at{ data: {min_date: Date.tomorrow, max_date: max_date, default_date_offset: 365, description: ssh_key_expires_field_description } }
|
||||
= f.label :expires_at, s_('Profiles|Expiration date'), class: 'label-bold'
|
||||
= f.text_field :expires_at, class: "gl-datepicker-input form-control gl-form-input", placeholder: 'YYYY-MM-DD', min: Date.tomorrow, max: max_date, data: { js_name: 'expiresAt' }
|
||||
%p.form-text.text-muted= ssh_key_expires_field_description
|
||||
|
||||
.js-add-ssh-key-validation-warning.hide
|
||||
.bs-callout.bs-callout-warning{ role: 'alert', aria_live: 'assertive' }
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ScheduleDestroyInvalidGroupMembers < Gitlab::Database::Migration[2.0]
|
||||
MIGRATION = 'DestroyInvalidGroupMembers'
|
||||
DELAY_INTERVAL = 2.minutes
|
||||
BATCH_SIZE = 1_000
|
||||
MAX_BATCH_SIZE = 2_000
|
||||
SUB_BATCH_SIZE = 50
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
queue_batched_background_migration(
|
||||
MIGRATION,
|
||||
:members,
|
||||
:id,
|
||||
job_interval: DELAY_INTERVAL,
|
||||
batch_size: BATCH_SIZE,
|
||||
max_batch_size: MAX_BATCH_SIZE,
|
||||
sub_batch_size: SUB_BATCH_SIZE,
|
||||
gitlab_schema: :gitlab_main
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
delete_batched_background_migration(MIGRATION, :members, :id, [])
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class DropUuidAndIdIndexFromSecurityFindings < Gitlab::Database::Migration[2.0]
|
||||
INDEX_NAME = :index_on_security_findings_uuid_and_id_order_desc
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
remove_concurrent_index_by_name :security_findings, name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_index :security_findings, [:uuid, :id], order: { id: :desc }, name: INDEX_NAME
|
||||
end
|
||||
end
|
1
db/schema_migrations/20220809002011
Normal file
1
db/schema_migrations/20220809002011
Normal file
|
@ -0,0 +1 @@
|
|||
12bc6c4a89c4362024d66a21690412f8946b8f6eaf9dc09cccaf8d54b7f45b17
|
1
db/schema_migrations/20220816075638
Normal file
1
db/schema_migrations/20220816075638
Normal file
|
@ -0,0 +1 @@
|
|||
78e03575edb66cfaeea75f2ff653efc77156ca9e0b1ea0fa989172c3caa0b195
|
|
@ -29312,8 +29312,6 @@ CREATE INDEX index_on_projects_path ON projects USING btree (path);
|
|||
|
||||
CREATE INDEX index_on_routes_lower_path ON routes USING btree (lower((path)::text));
|
||||
|
||||
CREATE INDEX index_on_security_findings_uuid_and_id_order_desc ON security_findings USING btree (uuid, id DESC);
|
||||
|
||||
CREATE INDEX index_on_users_lower_email ON users USING btree (lower((email)::text));
|
||||
|
||||
CREATE INDEX index_on_users_lower_username ON users USING btree (lower((username)::text));
|
||||
|
|
|
@ -17,6 +17,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
> - Custom HTTP headers UI [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/361630) in GitLab 15.2 [with a flag](feature_flags.md) named `custom_headers_streaming_audit_events_ui`. Disabled by default.
|
||||
> - Custom HTTP headers UI [made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/365259) in GitLab 15.3. [Feature flag `custom_headers_streaming_audit_events_ui`](https://gitlab.com/gitlab-org/gitlab/-/issues/365259) removed.
|
||||
> - [Improved user experience](https://gitlab.com/gitlab-org/gitlab/-/issues/367963) in GitLab 15.3.
|
||||
> - User-specified verification token API support [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/360813) in GitLab 15.4.
|
||||
|
||||
Users can set a streaming destination for a top-level group to receive all audit events about the group, its subgroups, and
|
||||
projects as structured JSON.
|
||||
|
@ -71,6 +72,25 @@ mutation {
|
|||
}
|
||||
```
|
||||
|
||||
Group owners can also optionally specify their own verification token (instead of the default GitLab-generated one) using the GraphQL `auditEventsStreamingHeadersCreate`
|
||||
mutation. Verification token length must be within 16 to 24 characters and trailing whitespace are not trimmed. GitLab recommends setting a cryptographically random and unique value. For example:
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
externalAuditEventDestinationCreate(input: { destinationUrl: "https://mydomain.io/endpoint/ingest", groupPath: "my-group", verificationToken: "unique-random-verification-token-here" } ) {
|
||||
errors
|
||||
externalAuditEventDestination {
|
||||
id
|
||||
destinationUrl
|
||||
verificationToken
|
||||
group {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Event streaming is enabled if:
|
||||
|
||||
- The returned `errors` object is empty.
|
||||
|
@ -248,9 +268,9 @@ The header is deleted if the returned `errors` object is empty.
|
|||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345424) in GitLab 14.8.
|
||||
|
||||
Each streaming destination has a unique verification token (`verificationToken`) that can be used to verify the authenticity of the event. This
|
||||
token is generated when the event destination is created and cannot be changed.
|
||||
token is either specified by the Owner or generated automatically when the event destination is created and cannot be changed.
|
||||
|
||||
Each streamed event contains a random alphanumeric identifier for the `X-Gitlab-Event-Streaming-Token` HTTP header that can be verified against
|
||||
Each streamed event contains the verification token in the `X-Gitlab-Event-Streaming-Token` HTTP header that can be verified against
|
||||
the destination's value when [listing streaming destinations](#list-streaming-destinations).
|
||||
|
||||
### Use the GitLab UI
|
||||
|
|
|
@ -2790,6 +2790,7 @@ Input type: `ExternalAuditEventDestinationCreateInput`
|
|||
| <a id="mutationexternalauditeventdestinationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationexternalauditeventdestinationcreatedestinationurl"></a>`destinationUrl` | [`String!`](#string) | Destination URL. |
|
||||
| <a id="mutationexternalauditeventdestinationcreategrouppath"></a>`groupPath` | [`ID!`](#id) | Group path. |
|
||||
| <a id="mutationexternalauditeventdestinationcreateverificationtoken"></a>`verificationToken` | [`String`](#string) | Verification token. |
|
||||
|
||||
#### Fields
|
||||
|
||||
|
@ -4579,6 +4580,26 @@ Input type: `ScanExecutionPolicyCommitInput`
|
|||
| <a id="mutationscanexecutionpolicycommitclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationscanexecutionpolicycommiterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
|
||||
### `Mutation.securityFindingCreateIssue`
|
||||
|
||||
Input type: `SecurityFindingCreateIssueInput`
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationsecurityfindingcreateissueclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationsecurityfindingcreateissueproject"></a>`project` | [`ProjectID!`](#projectid) | ID of the project to attach the issue to. |
|
||||
| <a id="mutationsecurityfindingcreateissueuuid"></a>`uuid` | [`String!`](#string) | UUID of the security finding to be used to create an issue. |
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationsecurityfindingcreateissueclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationsecurityfindingcreateissueerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
| <a id="mutationsecurityfindingcreateissueissue"></a>`issue` | [`Issue`](#issue) | Issue created after mutation. |
|
||||
|
||||
### `Mutation.securityPolicyProjectAssign`
|
||||
|
||||
Assigns the specified project(`security_policy_project_id`) as security policy project for the given project(`full_path`). If the project already has a security policy project, this reassigns the project's security policy project with the given `security_policy_project_id`.
|
||||
|
|
|
@ -422,7 +422,7 @@ Use the coverage reports to ensure your tests cover 100% of your code.
|
|||
### System / Feature tests
|
||||
|
||||
NOTE:
|
||||
Before writing a new system test,
|
||||
Before writing a new system test,
|
||||
[please consider **not** writing one](testing_levels.md#consider-not-writing-a-system-test)!
|
||||
|
||||
- Feature specs should be named `ROLE_ACTION_spec.rb`, such as
|
||||
|
@ -711,6 +711,7 @@ should either:
|
|||
- Add `require_dependency 're2'` to files in your library that need `re2` gem,
|
||||
to make this requirement explicit. This approach is preferred.
|
||||
- Add it to the spec itself.
|
||||
- Use `rubocop_spec_helper` for RuboCop related specs.
|
||||
|
||||
It takes around one second to load tests that are using `fast_spec_helper`
|
||||
instead of 30+ seconds in case of a regular `spec_helper`.
|
||||
|
@ -909,7 +910,7 @@ By default, Sidekiq jobs are enqueued into a jobs array and aren't processed.
|
|||
If a test queues Sidekiq jobs and need them to be processed, the
|
||||
`:sidekiq_inline` trait can be used.
|
||||
|
||||
The `:sidekiq_might_not_need_inline` trait was added when
|
||||
The `:sidekiq_might_not_need_inline` trait was added when
|
||||
[Sidekiq inline mode was changed to fake mode](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15479)
|
||||
to all the tests that needed Sidekiq to actually process jobs. Tests with
|
||||
this trait should be either fixed to not rely on Sidekiq processing jobs, or their
|
||||
|
|
|
@ -36,7 +36,7 @@ Here are some problems with current issues usage and why we are looking into wor
|
|||
differences in common interactions that the user needs to hold a complicated mental
|
||||
model of how they each behave.
|
||||
- Issues are not extensible enough to support all of the emerging jobs they need to facilitate.
|
||||
- Codebase maintainability and feature development becomes a bigger challenge as we grow the Issue type.
|
||||
- Codebase maintainability and feature development becomes a bigger challenge as we grow the Issue type
|
||||
beyond its core role of issue tracking into supporting the different work item types and handling
|
||||
logic and structure differences.
|
||||
- New functionality is typically implemented with first class objects that import behavior from issues via
|
||||
|
|
|
@ -492,9 +492,11 @@ You can only upgrade one minor release at a time.
|
|||
The order of steps is important. While following these steps, make
|
||||
sure you follow them in the right order, on the correct node.
|
||||
|
||||
### Update the Geo primary site
|
||||
|
||||
Log in to your **primary** node, executing the following:
|
||||
|
||||
1. Create an empty file at `/etc/gitlab/skip-auto-reconfigure`. This prevents upgrades from running `gitlab-ctl reconfigure`, which by default automatically stops GitLab, runs all database migrations, and restarts GitLab.
|
||||
1. Create an empty file at `/etc/gitlab/skip-auto-reconfigure`. This prevents upgrades from running `gitlab-ctl reconfigure`, which by default automatically stops GitLab, runs all database migrations, and restarts GitLab:
|
||||
|
||||
```shell
|
||||
sudo touch /etc/gitlab/skip-auto-reconfigure
|
||||
|
@ -512,7 +514,7 @@ Log in to your **primary** node, executing the following:
|
|||
sudo gitlab-ctl reconfigure
|
||||
```
|
||||
|
||||
1. Update the GitLab package
|
||||
1. Update the GitLab package:
|
||||
|
||||
```shell
|
||||
# Debian/Ubuntu
|
||||
|
@ -522,18 +524,13 @@ Log in to your **primary** node, executing the following:
|
|||
sudo yum install gitlab-ee
|
||||
```
|
||||
|
||||
1. To get the database migrations and latest code in place, run
|
||||
1. To get the database migrations and latest code in place, run:
|
||||
|
||||
```shell
|
||||
sudo SKIP_POST_DEPLOYMENT_MIGRATIONS=true gitlab-ctl reconfigure
|
||||
```
|
||||
|
||||
1. Hot reload `puma` and `sidekiq` services
|
||||
|
||||
```shell
|
||||
sudo gitlab-ctl hup puma
|
||||
sudo gitlab-ctl restart sidekiq
|
||||
```
|
||||
### Update the Geo secondary site
|
||||
|
||||
On each **secondary** node, executing the following:
|
||||
|
||||
|
@ -555,7 +552,7 @@ On each **secondary** node, executing the following:
|
|||
sudo gitlab-ctl reconfigure
|
||||
```
|
||||
|
||||
1. Update the GitLab package
|
||||
1. Update the GitLab package:
|
||||
|
||||
```shell
|
||||
# Debian/Ubuntu
|
||||
|
@ -565,26 +562,20 @@ On each **secondary** node, executing the following:
|
|||
sudo yum install gitlab-ee
|
||||
```
|
||||
|
||||
1. To get the database migrations and latest code in place, run
|
||||
1. To get the database migrations and latest code in place, run:
|
||||
|
||||
```shell
|
||||
sudo SKIP_POST_DEPLOYMENT_MIGRATIONS=true gitlab-ctl reconfigure
|
||||
```
|
||||
|
||||
1. Hot reload `puma`, `sidekiq` and restart `geo-logcursor` services
|
||||
|
||||
```shell
|
||||
sudo gitlab-ctl hup puma
|
||||
sudo gitlab-ctl restart sidekiq
|
||||
sudo gitlab-ctl restart geo-logcursor
|
||||
```
|
||||
|
||||
1. Run post-deployment database migrations, specific to the Geo database
|
||||
1. Run post-deployment database migrations, specific to the Geo database:
|
||||
|
||||
```shell
|
||||
sudo gitlab-rake db:migrate:geo
|
||||
```
|
||||
|
||||
### Finalize the update
|
||||
|
||||
After all **secondary** nodes are updated, finalize
|
||||
the update on the **primary** node:
|
||||
|
||||
|
@ -594,6 +585,16 @@ the update on the **primary** node:
|
|||
sudo gitlab-rake db:migrate
|
||||
```
|
||||
|
||||
- After the update is finalized on the primary node, hot reload `puma` and
|
||||
restart `sidekiq` and `geo-logcursor` services on **all primary and secondary**
|
||||
nodes:
|
||||
|
||||
```shell
|
||||
sudo gitlab-ctl hup puma
|
||||
sudo gitlab-ctl restart sidekiq
|
||||
sudo gitlab-ctl restart geo-logcursor
|
||||
```
|
||||
|
||||
After updating all nodes (both **primary** and all **secondaries**), check their status:
|
||||
|
||||
- Verify Geo configuration and dependencies
|
||||
|
|
|
@ -110,7 +110,7 @@ gitGraph
|
|||
```
|
||||
|
||||
This method is equivalent to `git merge --ff <source-branch>` for regular merges, and to
|
||||
`git merge -squash <source-branch>` for squash merges.
|
||||
`git merge --squash <source-branch>` for squash merges.
|
||||
|
||||
When the fast-forward merge
|
||||
([`--ff-only`](https://git-scm.com/docs/git-merge#git-merge---ff-only)) setting
|
||||
|
|
|
@ -254,6 +254,8 @@ A public and private key are generated.
|
|||
|
||||
## Add an SSH key to your GitLab account
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/271239) in GitLab 15.3, default expiration date suggested in UI.
|
||||
|
||||
To use SSH with GitLab, copy your public key to your GitLab account:
|
||||
|
||||
1. Copy the contents of your public key file. You can do this manually or use a script.
|
||||
|
@ -289,7 +291,7 @@ To use SSH with GitLab, copy your public key to your GitLab account:
|
|||
`ssh-ed25519`, `sk-ecdsa-sha2-nistp256@openssh.com`, or `sk-ssh-ed25519@openssh.com`, and may end with a comment.
|
||||
1. In the **Title** box, type a description, like `Work Laptop` or
|
||||
`Home Workstation`.
|
||||
1. Optional. In the **Expires at** box, select an expiration date. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36243) in GitLab 12.9.)
|
||||
1. Optional. Update **Expiration date** to modify the default expiration date.
|
||||
In:
|
||||
- GitLab 13.12 and earlier, the expiration date is informational only. It doesn't prevent
|
||||
you from using the key. Administrators can view expiration dates and use them for
|
||||
|
|
45
lib/api/admin/batched_background_migrations.rb
Normal file
45
lib/api/admin/batched_background_migrations.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module API
|
||||
module Admin
|
||||
class BatchedBackgroundMigrations < ::API::Base
|
||||
feature_category :database
|
||||
urgency :low
|
||||
|
||||
before do
|
||||
authenticated_as_admin!
|
||||
end
|
||||
|
||||
namespace 'admin' do
|
||||
resources 'batched_background_migrations' do
|
||||
desc 'Get the list of the batched background migrations'
|
||||
params do
|
||||
optional :database,
|
||||
type: String,
|
||||
values: Gitlab::Database.all_database_names,
|
||||
desc: 'The name of the database, the default `main`',
|
||||
default: 'main'
|
||||
end
|
||||
get do
|
||||
Gitlab::Database::SharedModel.using_connection(base_model.connection) do
|
||||
migrations = Database::BatchedBackgroundMigrationsFinder.new(connection: base_model.connection).execute
|
||||
present_entity(migrations)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
helpers do
|
||||
def base_model
|
||||
database = params[:database] || Gitlab::Database::MAIN_DATABASE_NAME
|
||||
@base_model ||= Gitlab::Database.database_base_models[database]
|
||||
end
|
||||
|
||||
def present_entity(result)
|
||||
present result,
|
||||
with: ::API::Entities::BatchedBackgroundMigration
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -167,6 +167,7 @@ module API
|
|||
|
||||
# Keep in alphabetical order
|
||||
mount ::API::AccessRequests
|
||||
mount ::API::Admin::BatchedBackgroundMigrations
|
||||
mount ::API::Admin::Ci::Variables
|
||||
mount ::API::Admin::InstanceClusters
|
||||
mount ::API::Admin::PlanLimits
|
||||
|
|
14
lib/api/entities/batched_background_migration.rb
Normal file
14
lib/api/entities/batched_background_migration.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module API
|
||||
module Entities
|
||||
class BatchedBackgroundMigration < Grape::Entity
|
||||
expose :id
|
||||
expose :job_class_name
|
||||
expose :table_name
|
||||
expose :status, &:status_name
|
||||
expose :progress
|
||||
expose :created_at
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module BackgroundMigration
|
||||
class DestroyInvalidGroupMembers < Gitlab::BackgroundMigration::BatchedMigrationJob # rubocop:disable Style/Documentation
|
||||
scope_to ->(relation) do
|
||||
relation.where(source_type: 'Namespace')
|
||||
.joins('LEFT OUTER JOIN namespaces ON members.source_id = namespaces.id')
|
||||
.where(namespaces: { id: nil })
|
||||
end
|
||||
|
||||
def perform
|
||||
each_sub_batch(operation_name: :delete_all) do |sub_batch|
|
||||
invalid_ids = sub_batch.map(&:id)
|
||||
Gitlab::AppLogger.info({ message: 'Removing invalid group member records',
|
||||
deleted_count: invalid_ids.size, ids: invalid_ids })
|
||||
|
||||
sub_batch.delete_all
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -24,6 +24,7 @@ module Gitlab
|
|||
|
||||
scope :queue_order, -> { order(id: :asc) }
|
||||
scope :queued, -> { with_statuses(:active, :paused) }
|
||||
scope :ordered_by_created_at_desc, -> { order(created_at: :desc) }
|
||||
|
||||
# on_hold_until is a temporary runtime status which puts execution "on hold"
|
||||
scope :executable, -> { with_status(:active).where('on_hold_until IS NULL OR on_hold_until < NOW()') }
|
||||
|
|
|
@ -40,23 +40,28 @@ module Gitlab
|
|||
track_unique_action(ISSUE_CREATED, author)
|
||||
end
|
||||
|
||||
def track_issue_title_changed_action(author:)
|
||||
def track_issue_title_changed_action(author:, project:)
|
||||
track_snowplow_action(ISSUE_TITLE_CHANGED, author, project)
|
||||
track_unique_action(ISSUE_TITLE_CHANGED, author)
|
||||
end
|
||||
|
||||
def track_issue_description_changed_action(author:)
|
||||
def track_issue_description_changed_action(author:, project:)
|
||||
track_snowplow_action(ISSUE_DESCRIPTION_CHANGED, author, project)
|
||||
track_unique_action(ISSUE_DESCRIPTION_CHANGED, author)
|
||||
end
|
||||
|
||||
def track_issue_assignee_changed_action(author:)
|
||||
def track_issue_assignee_changed_action(author:, project:)
|
||||
track_snowplow_action(ISSUE_ASSIGNEE_CHANGED, author, project)
|
||||
track_unique_action(ISSUE_ASSIGNEE_CHANGED, author)
|
||||
end
|
||||
|
||||
def track_issue_made_confidential_action(author:)
|
||||
def track_issue_made_confidential_action(author:, project:)
|
||||
track_snowplow_action(ISSUE_MADE_CONFIDENTIAL, author, project)
|
||||
track_unique_action(ISSUE_MADE_CONFIDENTIAL, author)
|
||||
end
|
||||
|
||||
def track_issue_made_visible_action(author:)
|
||||
def track_issue_made_visible_action(author:, project:)
|
||||
track_snowplow_action(ISSUE_MADE_VISIBLE, author, project)
|
||||
track_unique_action(ISSUE_MADE_VISIBLE, author)
|
||||
end
|
||||
|
||||
|
|
|
@ -30075,9 +30075,6 @@ msgstr ""
|
|||
msgid "Profiles|Key"
|
||||
msgstr ""
|
||||
|
||||
msgid "Profiles|Key becomes invalid on this date."
|
||||
msgstr ""
|
||||
|
||||
msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
|
||||
msgstr ""
|
||||
|
||||
|
@ -30108,6 +30105,9 @@ msgstr ""
|
|||
msgid "Profiles|Notification email"
|
||||
msgstr ""
|
||||
|
||||
msgid "Profiles|Optional but recommended. If set, key becomes invalid on the specified date."
|
||||
msgstr ""
|
||||
|
||||
msgid "Profiles|Organization"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -5,12 +5,15 @@ module QA
|
|||
module Profile
|
||||
class SSHKeys < Page::Base
|
||||
view 'app/views/profiles/keys/_form.html.haml' do
|
||||
element :key_expiry_date_field
|
||||
element :key_title_field
|
||||
element :key_public_key_field
|
||||
element :add_key_button
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/access_tokens/components/expires_at_field.vue' do
|
||||
element :expiry_date_field
|
||||
end
|
||||
|
||||
view 'app/helpers/ssh_keys_helper.rb' do
|
||||
element :delete_ssh_key_button
|
||||
element :ssh_key_delete_modal
|
||||
|
@ -25,19 +28,21 @@ module QA
|
|||
fill_element(:key_title_field, title)
|
||||
# Expire in 2 days just in case the key is created just before midnight
|
||||
fill_expiry_date(Date.today + 2)
|
||||
# Close the datepicker
|
||||
find_element(:expiry_date_field).find('input').send_keys(:enter)
|
||||
|
||||
click_element(:add_key_button)
|
||||
end
|
||||
|
||||
def fill_expiry_date(date)
|
||||
date = date.strftime('%m/%d/%Y') if date.is_a?(Date)
|
||||
date = date.strftime('%Y-%m-%d') if date.is_a?(Date)
|
||||
begin
|
||||
Date.strptime(date, '%m/%d/%Y')
|
||||
Date.strptime(date, '%Y-%m-%d')
|
||||
rescue ArgumentError
|
||||
raise "Expiry date must be in mm/dd/yyyy format"
|
||||
raise "Expiry date must be in YYYY-MM-DD format"
|
||||
end
|
||||
|
||||
fill_element(:key_expiry_date_field, date)
|
||||
fill_element(:expiry_date_field, date)
|
||||
end
|
||||
|
||||
def remove_key(title)
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Database::BatchedBackgroundMigrationsFinder do
|
||||
let!(:migration_1) { create(:batched_background_migration, created_at: Time.now - 2) }
|
||||
let!(:migration_2) { create(:batched_background_migration, created_at: Time.now - 1) }
|
||||
let!(:migration_3) { create(:batched_background_migration, created_at: Time.now - 3) }
|
||||
|
||||
let(:finder) { described_class.new(connection: connection) }
|
||||
|
||||
describe '#execute' do
|
||||
let(:connection) { ApplicationRecord.connection }
|
||||
|
||||
subject { finder.execute }
|
||||
|
||||
it 'returns migrations order by created_at (DESC)' do
|
||||
is_expected.to eq([migration_2, migration_1, migration_3])
|
||||
end
|
||||
|
||||
it 'limits the number of returned migrations' do
|
||||
stub_const('Database::BatchedBackgroundMigrationsFinder::RETURNED_MIGRATIONS', 2)
|
||||
|
||||
is_expected.to eq([migration_2, migration_1])
|
||||
end
|
||||
end
|
||||
end
|
|
@ -58,4 +58,20 @@ describe('~/access_tokens/components/expires_at_field', () => {
|
|||
|
||||
expect(findDatepicker().props('defaultDate')).toStrictEqual(future);
|
||||
});
|
||||
|
||||
it('should set the default expiration date to be 365 days', () => {
|
||||
const offset = 365;
|
||||
const today = new Date();
|
||||
const future = getDateInFuture(today, offset);
|
||||
createComponent({ defaultDateOffset: offset });
|
||||
|
||||
expect(findDatepicker().props('defaultDate')).toStrictEqual(future);
|
||||
});
|
||||
|
||||
it('should set the default expiration date to maxDate, ignoring defaultDateOffset', () => {
|
||||
const maxDate = new Date();
|
||||
createComponent({ maxDate, defaultDateOffset: 2 });
|
||||
|
||||
expect(findDatepicker().props('defaultDate')).toStrictEqual(maxDate);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -48,7 +48,7 @@ describe('ContentEditor', () => {
|
|||
it('triggers initialized event and provides contentEditor instance as event data', () => {
|
||||
createWrapper();
|
||||
|
||||
expect(contentEditor).not.toBeFalsy();
|
||||
expect(contentEditor).not.toBe(false);
|
||||
});
|
||||
|
||||
it('renders EditorContent component and provides tiptapEditor instance', () => {
|
||||
|
|
|
@ -72,7 +72,7 @@ describe('duplicate dashboard modal', () => {
|
|||
|
||||
await waitForPromises();
|
||||
expect(okEvent.preventDefault).toHaveBeenCalled();
|
||||
expect(wrapper.emitted().dashboardDuplicated).toBeTruthy();
|
||||
expect(wrapper.emitted('dashboardDuplicated')).toHaveLength(1);
|
||||
expect(wrapper.emitted().dashboardDuplicated[0]).toEqual([dashboardGitResponse[0]]);
|
||||
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
|
||||
expect(wrapper.vm.$refs.duplicateDashboardModal.hide).toHaveBeenCalled();
|
||||
|
|
|
@ -51,7 +51,7 @@ describe('add request form', () => {
|
|||
});
|
||||
|
||||
it('emits an event to add the request', () => {
|
||||
expect(wrapper.emitted()['add-request']).toBeTruthy();
|
||||
expect(wrapper.emitted()['add-request']).toHaveLength(1);
|
||||
expect(wrapper.emitted()['add-request'][0]).toEqual([
|
||||
'http://gitlab.example.com/users/root/calendar.json',
|
||||
]);
|
||||
|
|
|
@ -190,11 +190,16 @@ describe('Repository last commit component', () => {
|
|||
});
|
||||
|
||||
it('expands commit description when clicking expander', async () => {
|
||||
expect(findCommitRowDescription().classes('d-block')).toBe(false);
|
||||
expect(findTextExpander().classes('open')).toBe(false);
|
||||
expect(findTextExpander().props('selected')).toBe(false);
|
||||
|
||||
findTextExpander().vm.$emit('click');
|
||||
await nextTick();
|
||||
|
||||
expect(findCommitRowDescription().isVisible()).toBe(true);
|
||||
expect(findTextExpander().classes()).toContain('open');
|
||||
expect(findCommitRowDescription().classes('d-block')).toBe(true);
|
||||
expect(findTextExpander().classes('open')).toBe(true);
|
||||
expect(findTextExpander().props('selected')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ describe('MRWidgetSuggestPipeline', () => {
|
|||
it('emits dismiss upon dismissal button click', () => {
|
||||
findDismissContainer().vm.$emit('dismiss');
|
||||
|
||||
expect(wrapper.emitted().dismiss).toBeTruthy();
|
||||
expect(wrapper.emitted().dismiss).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -113,7 +113,7 @@ describe('WorkItemDetailModal component', () => {
|
|||
createComponent();
|
||||
findModal().vm.$emit('hide');
|
||||
|
||||
expect(wrapper.emitted('close')).toBeTruthy();
|
||||
expect(wrapper.emitted('close')).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('hides the modal when WorkItemDetail emits `close` event', () => {
|
||||
|
|
|
@ -99,7 +99,7 @@ RSpec.describe ProfilesHelper do
|
|||
describe "#ssh_key_expires_field_description" do
|
||||
subject { helper.ssh_key_expires_field_description }
|
||||
|
||||
it { is_expected.to eq('Key becomes invalid on this date.') }
|
||||
it { is_expected.to eq(s_('Profiles|Optional but recommended. If set, key becomes invalid on the specified date.')) }
|
||||
end
|
||||
|
||||
describe '#middle_dot_divider_classes' do
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'net/http'
|
||||
|
||||
require_relative '../../config/initializers/net_http_patch'
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::BackgroundMigration::DestroyInvalidGroupMembers, :migration, schema: 20220809002011 do
|
||||
# rubocop: disable Layout/LineLength
|
||||
# rubocop: disable RSpec/ScatteredLet
|
||||
let!(:migration_attrs) do
|
||||
{
|
||||
start_id: 1,
|
||||
end_id: 1000,
|
||||
batch_table: :members,
|
||||
batch_column: :id,
|
||||
sub_batch_size: 100,
|
||||
pause_ms: 0,
|
||||
connection: ApplicationRecord.connection
|
||||
}
|
||||
end
|
||||
|
||||
let!(:migration) { described_class.new(**migration_attrs) }
|
||||
|
||||
subject(:perform_migration) { migration.perform }
|
||||
|
||||
let(:users_table) { table(:users) }
|
||||
let(:namespaces_table) { table(:namespaces) }
|
||||
let(:members_table) { table(:members) }
|
||||
let(:projects_table) { table(:projects) }
|
||||
|
||||
let(:user1) { users_table.create!(name: 'user1', email: 'user1@example.com', projects_limit: 5) }
|
||||
let(:user2) { users_table.create!(name: 'user2', email: 'user2@example.com', projects_limit: 5) }
|
||||
let(:user3) { users_table.create!(name: 'user3', email: 'user3@example.com', projects_limit: 5) }
|
||||
let(:user4) { users_table.create!(name: 'user4', email: 'user4@example.com', projects_limit: 5) }
|
||||
let(:user5) { users_table.create!(name: 'user5', email: 'user5@example.com', projects_limit: 5) }
|
||||
let(:user6) { users_table.create!(name: 'user6', email: 'user6@example.com', projects_limit: 5) }
|
||||
|
||||
let!(:group1) { namespaces_table.create!(name: 'marvellous group 1', path: 'group-path-1', type: 'Group') }
|
||||
|
||||
let!(:group2) { namespaces_table.create!(name: 'outstanding group 2', path: 'group-path-2', type: 'Group') }
|
||||
|
||||
# create group member records, a mix of both valid and invalid
|
||||
# project members will have already been filtered out.
|
||||
let!(:group_member1) { create_invalid_group_member(id: 1, user_id: user1.id) }
|
||||
|
||||
let!(:group_member4) { create_valid_group_member(id: 4, user_id: user2.id, group_id: group1.id) }
|
||||
|
||||
let!(:group_member5) { create_valid_group_member(id: 5, user_id: user3.id, group_id: group2.id) }
|
||||
|
||||
let!(:group_member6) { create_invalid_group_member(id: 6, user_id: user4.id) }
|
||||
|
||||
let!(:group_member7) { create_valid_group_member(id: 7, user_id: user5.id, group_id: group1.id) }
|
||||
|
||||
let!(:group_member8) { create_invalid_group_member(id: 8, user_id: user6.id) }
|
||||
|
||||
it 'removes invalid memberships but keeps valid ones', :aggregate_failures do
|
||||
expect(members_table.where(type: 'GroupMember').count).to eq 6
|
||||
|
||||
queries = ActiveRecord::QueryRecorder.new do
|
||||
perform_migration
|
||||
end
|
||||
|
||||
expect(queries.count).to eq(4)
|
||||
expect(members_table.where(type: 'GroupMember').pluck(:id)).to match_array([group_member4, group_member5, group_member7].map(&:id))
|
||||
end
|
||||
|
||||
it 'tracks timings of queries' do
|
||||
expect(migration.batch_metrics.timings).to be_empty
|
||||
|
||||
expect { perform_migration }.to change { migration.batch_metrics.timings }
|
||||
end
|
||||
|
||||
it 'logs IDs of deleted records' do
|
||||
expect(Gitlab::AppLogger).to receive(:info).with({ message: 'Removing invalid group member records',
|
||||
deleted_count: 3, ids: [group_member1, group_member6, group_member8].map(&:id) })
|
||||
|
||||
perform_migration
|
||||
end
|
||||
|
||||
def create_invalid_group_member(id:, user_id:)
|
||||
members_table.create!(id: id, user_id: user_id, source_id: non_existing_record_id, access_level: Gitlab::Access::MAINTAINER,
|
||||
type: "GroupMember", source_type: "Namespace", notification_level: 3, member_namespace_id: nil)
|
||||
end
|
||||
|
||||
def create_valid_group_member(id:, user_id:, group_id:)
|
||||
members_table.create!(id: id, user_id: user_id, source_id: group_id, access_level: Gitlab::Access::MAINTAINER,
|
||||
type: "GroupMember", source_type: "Namespace", member_namespace_id: group_id, notification_level: 3)
|
||||
end
|
||||
# rubocop: enable Layout/LineLength
|
||||
# rubocop: enable RSpec/ScatteredLet
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'tempfile'
|
||||
|
||||
RSpec.describe Gitlab::Bullet::Exclusions do
|
||||
let(:config_file) do
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
require 'fast_spec_helper'
|
||||
require 'rspec-parameterized'
|
||||
require 'tsort'
|
||||
|
||||
RSpec.describe Gitlab::Ci::Variables::Collection::Sort do
|
||||
describe '#initialize with non-Collection value' do
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'tsort'
|
||||
|
||||
RSpec.describe Gitlab::Ci::YamlProcessor::Dag do
|
||||
let(:nodes) { {} }
|
||||
|
|
|
@ -77,6 +77,16 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
|
|||
end
|
||||
end
|
||||
|
||||
describe '.ordered_by_created_at_desc' do
|
||||
let!(:migration_1) { create(:batched_background_migration, created_at: Time.zone.now - 2) }
|
||||
let!(:migration_2) { create(:batched_background_migration, created_at: Time.zone.now - 1) }
|
||||
let!(:migration_3) { create(:batched_background_migration, created_at: Time.zone.now - 3) }
|
||||
|
||||
it 'returns batched migrations ordered by created_at (DESC)' do
|
||||
expect(described_class.ordered_by_created_at_desc).to eq([migration_2, migration_1, migration_3])
|
||||
end
|
||||
end
|
||||
|
||||
describe '.active_migration' do
|
||||
let(:connection) { Gitlab::Database.database_base_models[:main].connection }
|
||||
let!(:migration1) { create(:batched_background_migration, :finished) }
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'tmpdir'
|
||||
|
||||
RSpec.describe Gitlab::Memory::Jemalloc do
|
||||
let(:outdir) { Dir.mktmpdir }
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
require 'fast_spec_helper'
|
||||
require 'rack'
|
||||
require 'tempfile'
|
||||
|
||||
RSpec.describe Gitlab::Middleware::RackMultipartTempfileFactory do
|
||||
let(:app) do
|
||||
|
|
|
@ -15,7 +15,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
|
|||
let(:time) { Time.zone.now }
|
||||
|
||||
context 'for Issue title edit actions' do
|
||||
it_behaves_like 'a daily tracked issuable event' do
|
||||
it_behaves_like 'daily tracked issuable snowplow and service ping events with project' do
|
||||
let(:action) { described_class::ISSUE_TITLE_CHANGED }
|
||||
|
||||
def track_action(params)
|
||||
|
@ -25,7 +25,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
|
|||
end
|
||||
|
||||
context 'for Issue description edit actions' do
|
||||
it_behaves_like 'a daily tracked issuable event' do
|
||||
it_behaves_like 'daily tracked issuable snowplow and service ping events with project' do
|
||||
let(:action) { described_class::ISSUE_DESCRIPTION_CHANGED }
|
||||
|
||||
def track_action(params)
|
||||
|
@ -35,7 +35,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
|
|||
end
|
||||
|
||||
context 'for Issue assignee edit actions' do
|
||||
it_behaves_like 'a daily tracked issuable event' do
|
||||
it_behaves_like 'daily tracked issuable snowplow and service ping events with project' do
|
||||
let(:action) { described_class::ISSUE_ASSIGNEE_CHANGED }
|
||||
|
||||
def track_action(params)
|
||||
|
@ -45,7 +45,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
|
|||
end
|
||||
|
||||
context 'for Issue make confidential actions' do
|
||||
it_behaves_like 'a daily tracked issuable event' do
|
||||
it_behaves_like 'daily tracked issuable snowplow and service ping events with project' do
|
||||
let(:action) { described_class::ISSUE_MADE_CONFIDENTIAL }
|
||||
|
||||
def track_action(params)
|
||||
|
@ -55,7 +55,7 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
|
|||
end
|
||||
|
||||
context 'for Issue make visible actions' do
|
||||
it_behaves_like 'a daily tracked issuable event' do
|
||||
it_behaves_like 'daily tracked issuable snowplow and service ping events with project' do
|
||||
let(:action) { described_class::ISSUE_MADE_VISIBLE }
|
||||
|
||||
def track_action(params)
|
||||
|
@ -285,15 +285,15 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
|
|||
end
|
||||
|
||||
it 'can return the count of actions per user deduplicated', :aggregate_failures do
|
||||
described_class.track_issue_title_changed_action(author: user1)
|
||||
described_class.track_issue_description_changed_action(author: user1)
|
||||
described_class.track_issue_assignee_changed_action(author: user1)
|
||||
described_class.track_issue_title_changed_action(author: user1, project: project)
|
||||
described_class.track_issue_description_changed_action(author: user1, project: project)
|
||||
described_class.track_issue_assignee_changed_action(author: user1, project: project)
|
||||
|
||||
travel_to(2.days.ago) do
|
||||
described_class.track_issue_title_changed_action(author: user2)
|
||||
described_class.track_issue_title_changed_action(author: user3)
|
||||
described_class.track_issue_description_changed_action(author: user3)
|
||||
described_class.track_issue_assignee_changed_action(author: user3)
|
||||
described_class.track_issue_title_changed_action(author: user2, project: project)
|
||||
described_class.track_issue_title_changed_action(author: user3, project: project)
|
||||
described_class.track_issue_description_changed_action(author: user3, project: project)
|
||||
described_class.track_issue_assignee_changed_action(author: user3, project: project)
|
||||
end
|
||||
|
||||
events = Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category(described_class::ISSUE_CATEGORY)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'tmpdir'
|
||||
|
||||
RSpec.describe Prometheus::CleanupMultiprocDirService do
|
||||
describe '#execute' do
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe ScheduleDestroyInvalidGroupMembers, :migration do
|
||||
let_it_be(:migration) { described_class::MIGRATION }
|
||||
|
||||
describe '#up' do
|
||||
it 'schedules background jobs for each batch of members' do
|
||||
migrate!
|
||||
|
||||
expect(migration).to have_scheduled_batched_migration(
|
||||
table_name: :members,
|
||||
column_name: :id,
|
||||
interval: described_class::DELAY_INTERVAL,
|
||||
batch_size: described_class::BATCH_SIZE,
|
||||
max_batch_size: described_class::MAX_BATCH_SIZE
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#down' do
|
||||
it 'deletes all batched migration records' do
|
||||
migrate!
|
||||
schema_migrate_down!
|
||||
|
||||
expect(migration).not_to have_scheduled_batched_migration
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,78 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe API::Admin::BatchedBackgroundMigrations do
|
||||
let(:admin) { create(:admin) }
|
||||
let(:unauthorized_user) { create(:user) }
|
||||
|
||||
describe 'GET /admin/batched_background_migrations' do
|
||||
let!(:migration) { create(:batched_background_migration) }
|
||||
|
||||
context 'when is an admin user' do
|
||||
it 'returns batched background migrations' do
|
||||
get api('/admin/batched_background_migrations', admin)
|
||||
|
||||
aggregate_failures "testing response" do
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response.count).to eq(1)
|
||||
expect(json_response.first['id']).to eq(migration.id)
|
||||
expect(json_response.first['job_class_name']).to eq(migration.job_class_name)
|
||||
expect(json_response.first['table_name']).to eq(migration.table_name)
|
||||
expect(json_response.first['status']).to eq(migration.status_name.to_s)
|
||||
expect(json_response.first['progress']).to be_zero
|
||||
end
|
||||
end
|
||||
|
||||
context 'when multiple database is enabled', :add_ci_connection do
|
||||
let(:database) { :ci }
|
||||
let(:schema) { :gitlab_ci }
|
||||
let(:ci_model) { Ci::ApplicationRecord }
|
||||
|
||||
context 'when CI database is provided' do
|
||||
let(:db_config) { instance_double(ActiveRecord::DatabaseConfigurations::HashConfig, name: 'fake_db') }
|
||||
let(:default_model) { ActiveRecord::Base }
|
||||
let(:base_models) { { 'fake_db' => default_model, 'ci' => ci_model }.with_indifferent_access }
|
||||
|
||||
it "uses CI database connection" do
|
||||
allow(Gitlab::Database).to receive(:db_config_for_connection).and_return(db_config)
|
||||
allow(Gitlab::Database).to receive(:database_base_models).and_return(base_models)
|
||||
|
||||
expect(Gitlab::Database::SharedModel).to receive(:using_connection).with(ci_model.connection).and_yield
|
||||
|
||||
get api('/admin/batched_background_migrations', admin), params: { database: :ci }
|
||||
end
|
||||
|
||||
it 'returns CI database records' do
|
||||
# If we only have one DB we'll see both migrations
|
||||
skip_if_multiple_databases_not_setup
|
||||
|
||||
ci_database_migration = Gitlab::Database::SharedModel.using_connection(ci_model.connection) do
|
||||
create(:batched_background_migration, :active, gitlab_schema: schema)
|
||||
end
|
||||
|
||||
get api('/admin/batched_background_migrations', admin), params: { database: :ci }
|
||||
|
||||
aggregate_failures "testing response" do
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response.count).to eq(1)
|
||||
expect(json_response.first['id']).to eq(ci_database_migration.id)
|
||||
expect(json_response.first['job_class_name']).to eq(ci_database_migration.job_class_name)
|
||||
expect(json_response.first['table_name']).to eq(ci_database_migration.table_name)
|
||||
expect(json_response.first['status']).to eq(ci_database_migration.status_name.to_s)
|
||||
expect(json_response.first['progress']).to be_zero
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when authenticated as a non-admin user' do
|
||||
it 'returns 403' do
|
||||
get api('/admin/batched_background_migrations', unauthorized_user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require 'parser/current'
|
||||
require_relative '../../rubocop/code_reuse_helpers'
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../rubocop/cop/active_model_errors_direct_manipulation'
|
||||
|
||||
RSpec.describe RuboCop::Cop::ActiveModelErrorsDirectManipulation do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../rubocop/cop/active_record_association_reload'
|
||||
|
||||
RSpec.describe RuboCop::Cop::ActiveRecordAssociationReload do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/api/base'
|
||||
|
||||
RSpec.describe RuboCop::Cop::API::Base do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/api/grape_array_missing_coerce'
|
||||
|
||||
RSpec.describe RuboCop::Cop::API::GrapeArrayMissingCoerce do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../rubocop/cop/avoid_becomes'
|
||||
|
||||
RSpec.describe RuboCop::Cop::AvoidBecomes do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../rubocop/cop/avoid_break_from_strong_memoize'
|
||||
|
||||
RSpec.describe RuboCop::Cop::AvoidBreakFromStrongMemoize do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers'
|
||||
|
||||
RSpec.describe RuboCop::Cop::AvoidKeywordArgumentsInSidekiqWorkers do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../rubocop/cop/avoid_return_from_blocks'
|
||||
|
||||
RSpec.describe RuboCop::Cop::AvoidReturnFromBlocks do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../rubocop/cop/avoid_route_redirect_leading_slash'
|
||||
|
||||
RSpec.describe RuboCop::Cop::AvoidRouteRedirectLeadingSlash do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
|
||||
require_relative '../../../rubocop/cop/ban_catch_throw'
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/code_reuse/finder'
|
||||
|
||||
RSpec.describe RuboCop::Cop::CodeReuse::Finder do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/code_reuse/presenter'
|
||||
|
||||
RSpec.describe RuboCop::Cop::CodeReuse::Presenter do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/code_reuse/serializer'
|
||||
|
||||
RSpec.describe RuboCop::Cop::CodeReuse::Serializer do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/code_reuse/service_class'
|
||||
|
||||
RSpec.describe RuboCop::Cop::CodeReuse::ServiceClass do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/code_reuse/worker'
|
||||
|
||||
RSpec.describe RuboCop::Cop::CodeReuse::Worker do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/database/disable_referential_integrity'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Database::DisableReferentialIntegrity do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/database/establish_connection'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Database::EstablishConnection do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/database/multiple_databases'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Database::MultipleDatabases do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/database/rescue_query_canceled'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Database::RescueQueryCanceled do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/database/rescue_statement_timeout'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Database::RescueStatementTimeout do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../rubocop/cop/default_scope'
|
||||
|
||||
RSpec.describe RuboCop::Cop::DefaultScope do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../rubocop/cop/destroy_all'
|
||||
|
||||
RSpec.describe RuboCop::Cop::DestroyAll do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../rubocop/cop/file_decompression'
|
||||
|
||||
RSpec.describe RuboCop::Cop::FileDecompression do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require 'rubocop/rspec/support'
|
||||
require_relative '../../../rubocop/cop/filename_length'
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gemspec/avoid_executing_git'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gemspec::AvoidExecutingGit do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/avoid_feature_category_not_owned'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::AvoidFeatureCategoryNotOwned do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/avoid_uploaded_file_from_params'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::AvoidUploadedFileFromParams do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/bulk_insert'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::BulkInsert do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/change_timezone'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::ChangeTimezone do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/const_get_inherit_false'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::ConstGetInheritFalse do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/delegate_predicate_methods'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::DelegatePredicateMethods do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/deprecate_track_redis_hll_event'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::DeprecateTrackRedisHLLEvent do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
|
||||
require_relative '../../../../rubocop/cop/gitlab/duplicate_spec_location'
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
|
||||
require_relative '../../../../rubocop/cop/gitlab/event_store_subscriber'
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/except'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::Except do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require 'rubocop'
|
||||
require 'rubocop/rspec/support'
|
||||
require_relative '../../../../rubocop/cop/gitlab/feature_available_usage'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
|
||||
require_relative '../../../../rubocop/cop/gitlab/finder_with_find_by'
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/httparty'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::HTTParty do # rubocop:disable RSpec/FilePath
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/intersect'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::Intersect do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/json'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::Json do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require 'rubocop'
|
||||
require 'rubocop/rspec/support'
|
||||
require_relative '../../../../rubocop/cop/gitlab/mark_used_feature_flags'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/module_with_instance_variables'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::ModuleWithInstanceVariables do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/namespaced_class'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::NamespacedClass do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/policy_rule_boolean'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::PolicyRuleBoolean do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/predicate_memoization'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::PredicateMemoization do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/rails_logger'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::RailsLogger do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/gitlab/union'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Gitlab::Union do
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue