Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-01-07 21:30:32 +00:00
parent a69cdf3002
commit 2fe1040e46
49 changed files with 1601 additions and 908 deletions

View File

@ -2,7 +2,6 @@
# Cop supports --autocorrect.
Layout/ClassStructure:
Exclude:
- 'app/finders/clusters/knative_services_finder.rb'
- 'app/finders/group_members_finder.rb'
- 'app/finders/groups/environment_scopes_finder.rb'
- 'app/finders/issuable_finder.rb'

View File

@ -3350,7 +3350,6 @@ RSpec/FeatureCategory:
- 'spec/models/dependency_proxy/image_ttl_group_policy_spec.rb'
- 'spec/models/dependency_proxy/manifest_spec.rb'
- 'spec/models/dependency_proxy/registry_spec.rb'
- 'spec/models/deploy_key_spec.rb'
- 'spec/models/deploy_keys_project_spec.rb'
- 'spec/models/deployment_cluster_spec.rb'
- 'spec/models/deployment_merge_request_spec.rb'

View File

@ -718,7 +718,7 @@
{"name":"term-ansicolor","version":"1.7.1","platform":"ruby","checksum":"92339ffec77c4bddc786a29385c91601dd52fc68feda23609bba0491229b05f7"},
{"name":"terminal-table","version":"3.0.2","platform":"ruby","checksum":"f951b6af5f3e00203fb290a669e0a85c5dd5b051b3b023392ccfd67ba5abae91"},
{"name":"terser","version":"1.0.2","platform":"ruby","checksum":"80c2e0bc7e2db4e12e8529658f9e0820e13d685ae67d745bf981f269743bb28e"},
{"name":"test-prof","version":"1.4.3","platform":"ruby","checksum":"85bd2a3ebcfcb95d4af748517db8cd837e9f23f5e01b5e39dc9e26f928f87718"},
{"name":"test-prof","version":"1.4.4","platform":"ruby","checksum":"1a59513ed9d33a1f5ca17c0b89da4e70f60a91c83ec62e9a873dbb99141353ef"},
{"name":"test_file_finder","version":"0.3.1","platform":"ruby","checksum":"83fb0588a06b2784b51892910b9bfd06609f8d31f2d851a98d976f644d177199"},
{"name":"text","version":"1.3.1","platform":"ruby","checksum":"2fbbbc82c1ce79c4195b13018a87cbb00d762bda39241bb3cdc32792759dd3f4"},
{"name":"thor","version":"1.3.1","platform":"ruby","checksum":"fa7e3471d4f6a27138e3d9c9b0d4daac9c3d7383927667ae83e9ab42ae7401ef"},

View File

@ -1831,7 +1831,7 @@ GEM
unicode-display_width (>= 1.1.1, < 3)
terser (1.0.2)
execjs (>= 0.3.0, < 3)
test-prof (1.4.3)
test-prof (1.4.4)
test_file_finder (0.3.1)
faraday (>= 1.0, < 3.0, != 2.0.0)
text (1.3.1)

View File

@ -731,7 +731,7 @@
{"name":"term-ansicolor","version":"1.7.1","platform":"ruby","checksum":"92339ffec77c4bddc786a29385c91601dd52fc68feda23609bba0491229b05f7"},
{"name":"terminal-table","version":"3.0.2","platform":"ruby","checksum":"f951b6af5f3e00203fb290a669e0a85c5dd5b051b3b023392ccfd67ba5abae91"},
{"name":"terser","version":"1.0.2","platform":"ruby","checksum":"80c2e0bc7e2db4e12e8529658f9e0820e13d685ae67d745bf981f269743bb28e"},
{"name":"test-prof","version":"1.4.3","platform":"ruby","checksum":"85bd2a3ebcfcb95d4af748517db8cd837e9f23f5e01b5e39dc9e26f928f87718"},
{"name":"test-prof","version":"1.4.4","platform":"ruby","checksum":"1a59513ed9d33a1f5ca17c0b89da4e70f60a91c83ec62e9a873dbb99141353ef"},
{"name":"test_file_finder","version":"0.3.1","platform":"ruby","checksum":"83fb0588a06b2784b51892910b9bfd06609f8d31f2d851a98d976f644d177199"},
{"name":"text","version":"1.3.1","platform":"ruby","checksum":"2fbbbc82c1ce79c4195b13018a87cbb00d762bda39241bb3cdc32792759dd3f4"},
{"name":"thor","version":"1.3.1","platform":"ruby","checksum":"fa7e3471d4f6a27138e3d9c9b0d4daac9c3d7383927667ae83e9ab42ae7401ef"},

View File

@ -1863,7 +1863,7 @@ GEM
unicode-display_width (>= 1.1.1, < 3)
terser (1.0.2)
execjs (>= 0.3.0, < 3)
test-prof (1.4.3)
test-prof (1.4.4)
test_file_finder (0.3.1)
faraday (>= 1.0, < 3.0, != 2.0.0)
text (1.3.1)

View File

@ -1,10 +1,17 @@
<script>
import { GlIcon, GlLoadingIcon, GlPagination } from '@gitlab/ui';
import {
GlIcon,
GlLoadingIcon,
GlPagination,
GlFilteredSearch,
GlFilteredSearchToken,
} from '@gitlab/ui';
import { createAlert } from '~/alert';
import { s__ } from '~/locale';
import { captureException } from '~/sentry/sentry_browser_wrapper';
import pageInfoQuery from '~/graphql_shared/client/page_info.query.graphql';
import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
import { OPERATORS_IS } from '~/vue_shared/components/filtered_search_bar/constants';
import deployKeysQuery from '../graphql/queries/deploy_keys.query.graphql';
import currentPageQuery from '../graphql/queries/current_page.query.graphql';
import currentScopeQuery from '../graphql/queries/current_scope.query.graphql';
@ -16,6 +23,21 @@ import disableKeyMutation from '../graphql/mutations/disable_key.mutation.graphq
import ConfirmModal from './confirm_modal.vue';
import KeysPanel from './keys_panel.vue';
const titleToken = {
title: s__('DeployKeys|Name'),
type: 'title',
operators: OPERATORS_IS,
token: GlFilteredSearchToken,
unique: true,
};
const keyToken = {
title: s__('DeployKeys|SHA'),
type: 'key',
operators: OPERATORS_IS,
token: GlFilteredSearchToken,
unique: true,
};
export default {
components: {
ConfirmModal,
@ -24,6 +46,7 @@ export default {
GlIcon,
GlLoadingIcon,
GlPagination,
GlFilteredSearch,
},
props: {
projectId: {
@ -43,6 +66,7 @@ export default {
projectPath: this.projectPath,
scope: this.currentScope,
page: this.currentPage,
search: this.searchObject,
};
},
update(data) {
@ -62,7 +86,9 @@ export default {
pageInfo: {
query: pageInfoQuery,
variables() {
return { input: { page: this.currentPage, scope: this.currentScope } };
return {
input: { page: this.currentPage, scope: this.currentScope, search: this.searchObject },
};
},
update({ pageInfo }) {
return pageInfo || {};
@ -85,6 +111,9 @@ export default {
currentPage: null,
currentScope: null,
deployKeyToRemove: null,
searchObject: null,
searchValue: [],
availableTokens: [titleToken, keyToken],
};
},
scopes: {
@ -108,9 +137,18 @@ export default {
confirmModalVisible() {
return Boolean(this.deployKeyToRemove);
},
hasSearch() {
return Boolean(this.searchObject?.search);
},
loading() {
return this.$apollo.queries.deployKeys.loading;
},
},
methods: {
onChangeTab(scope) {
this.searchObject = null;
this.searchValue = [];
return this.$apollo
.mutate({
mutation: updateCurrentScopeMutation,
@ -164,6 +202,43 @@ export default {
variables: { id: null },
});
},
updateSearch(search = []) {
const currentSearch = search[0];
const defaultTokens = [titleToken, keyToken];
if (!currentSearch?.value?.data) {
this.availableTokens = defaultTokens;
return;
}
const tokenTypeMap = {
title: [titleToken],
key: [keyToken],
};
this.availableTokens = tokenTypeMap[currentSearch.type] || [];
},
handleSearch(search = []) {
if (!search.length) {
this.searchObject = null;
return;
}
const currentSearch = search[0];
this.searchObject = this.buildSearchObject(currentSearch);
},
buildSearchObject(searchItem) {
if (typeof searchItem === 'string') {
return {
search: searchItem,
in: '',
};
}
return {
search: searchItem.value?.data,
in: searchItem.type,
};
},
},
};
</script>
@ -188,16 +263,25 @@ export default {
/>
</div>
</div>
<gl-loading-icon
v-if="$apollo.queries.deployKeys.loading"
:label="$options.i18n.loading"
size="md"
class="gl-m-5"
/>
<div class="gl-mt-4 gl-px-4">
<gl-filtered-search
v-model="searchValue"
:placeholder="__('Search deploy keys')"
:available-tokens="availableTokens"
:view-only="loading"
@clear="handleSearch"
@input="updateSearch"
@submit="handleSearch"
/>
</div>
<gl-loading-icon v-if="loading" :label="$options.i18n.loading" size="md" class="gl-m-5" />
<template v-else>
<keys-panel
:project-id="projectId"
:keys="deployKeys"
:has-search="hasSearch"
data-testid="project-deploy-keys-container"
/>
<gl-pagination

View File

@ -15,6 +15,11 @@ export default {
required: false,
default: null,
},
hasSearch: {
type: Boolean,
required: false,
default: false,
},
},
};
</script>
@ -44,7 +49,10 @@ export default {
/>
</template>
<div v-else class="gl-bg-gray-10 gl-p-5 gl-text-subtle" data-testid="empty-state">
{{ s__('DeployKeys|No deploy keys found, start by adding a new one above.') }}
<span v-if="hasSearch">{{ s__('DeployKeys|No search results found.') }}</span>
<span v-else>{{
s__('DeployKeys|No deploy keys found, start by adding a new one above.')
}}</span>
</div>
</div>
</template>

View File

@ -1,7 +1,12 @@
query getDeployKeys($projectPath: ID!, $scope: DeployKeysScope, $page: Integer) {
query getDeployKeys(
$projectPath: ID!
$scope: DeployKeysScope
$page: Integer
$search: DeployKeysSearch
) {
project(fullPath: $projectPath) {
id
deployKeys(scope: $scope, page: $page) @client {
deployKeys(scope: $scope, page: $page, search: $search) @client {
id
title
fingerprintSha256

View File

@ -19,7 +19,7 @@ const DEFAULT_PAGE_SIZE = 5;
export const resolvers = (endpoints) => ({
Project: {
deployKeys(_, { scope, page }, { client }) {
deployKeys(_, { scope, page, search }, { client }) {
const key = `${scope}Endpoint`;
let { [key]: endpoint } = endpoints;
@ -28,7 +28,7 @@ export const resolvers = (endpoints) => ({
}
return axios
.get(endpoint, { params: { page, per_page: DEFAULT_PAGE_SIZE } })
.get(endpoint, { params: { page, per_page: DEFAULT_PAGE_SIZE, ...search } })
.then(({ headers, data }) => {
const normalizedHeaders = normalizeHeaders(headers);
const pageInfo = {
@ -37,7 +37,7 @@ export const resolvers = (endpoints) => ({
};
client.writeQuery({
query: pageInfoQuery,
variables: { input: { page, scope } },
variables: { input: { page, scope, search } },
data: { pageInfo },
});
return data?.keys?.map(mapDeployKey) || [];

View File

@ -11,6 +11,16 @@ enum LocalDeployKeyActions {
disable
}
enum DeployKeysInOption {
title
key
}
type DeployKeysSearch {
search: String
in: DeployKeysInOption
}
type LocalProject {
id: ID!
fullPath: String

View File

@ -192,12 +192,7 @@ export default {
const modalOpen = urlParams.has('show');
if (this.previewNote && !this.previewNoteLoadedInList && !modalOpen) {
const preview = {
notes: {
nodes: [this.previewNote],
},
};
visibleNotes = [...visibleNotes, preview];
visibleNotes = [...visibleNotes, this.previewNote];
}
if (this.sortOrder === DESC) {
@ -251,7 +246,7 @@ export default {
};
},
update(data) {
return data?.note;
return data?.note?.discussion;
},
result(result) {
if (result?.errors?.length > 0) {

View File

@ -2,6 +2,14 @@
query workItemNote($id: NoteID!) {
note(id: $id) {
...WorkItemNote
id
discussion {
id
notes {
nodes {
...WorkItemNote
}
}
}
}
}

View File

@ -137,9 +137,14 @@ class Projects::DeployKeysController < Projects::ApplicationController
redirect_to_repository_settings(@project, anchor: 'js-deploy-keys-settings')
end
def find_keys(params)
DeployKeys::DeployKeysFinder.new(@project, current_user, params)
.execute
def find_keys(filter:)
finder_params = {
filter: filter,
search: params[:search],
in: params[:in]
}.compact
DeployKeys::DeployKeysFinder.new(project, current_user, finder_params).execute
end
def serialize(keys)

View File

@ -16,6 +16,13 @@ module Clusters
attr_reader :cluster, :environment
def self.from_cache(cluster_id, environment_id)
cluster = Clusters::Cluster.find(cluster_id)
environment = Environment.find(environment_id)
new(cluster, environment)
end
def initialize(cluster, environment)
@cluster = cluster
@environment = environment
@ -31,13 +38,6 @@ module Clusters
clear_reactive_cache!(*cache_args)
end
def self.from_cache(cluster_id, environment_id)
cluster = Clusters::Cluster.find(cluster_id)
environment = Environment.find(environment_id)
new(cluster, environment)
end
def calculate_reactive_cache(*)
# read_services calls knative_client.discover implicitily. If we stop
# detecting services but still want to detect knative, we'll need to

View File

@ -13,16 +13,18 @@ module DeployKeys
def execute
return empty unless can_admin_project?
case params[:filter]
when :enabled_keys
enabled_keys
when :available_project_keys
available_project_keys
when :available_public_keys
available_public_keys
else
empty
end
keys = case params[:filter]
when :enabled_keys
enabled_keys
when :available_project_keys
available_project_keys
when :available_public_keys
available_public_keys
else
empty
end
search_keys(keys)
end
private
@ -46,5 +48,11 @@ module DeployKeys
def can_admin_project?
current_user.can?(:admin_project, project)
end
def search_keys(keys)
return keys unless params[:search].present?
keys.search(params[:search], params[:in])
end
end
end

View File

@ -27,6 +27,16 @@ class DeployKey < Key
scope :including_projects_with_readonly_access, -> { includes(:projects_with_readonly_access) }
scope :not_in, ->(keys) { where.not(id: keys.select(:id)) }
scope :search_by_title, ->(term) {
sanitized_term = sanitize_sql_like(term.downcase)
where("title ILIKE :term", term: "%#{sanitized_term}%")
}
scope :search_by_key, ->(term) {
sanitized_term = sanitize_sql_like(term)
where("encode(fingerprint_sha256, 'base64') ILIKE :term", term: "%#{sanitized_term}%")
}
accepts_nested_attributes_for :deploy_keys_projects, reject_if: :reject_deploy_keys_projects?
def private?
@ -86,4 +96,17 @@ class DeployKey < Key
def reject_deploy_keys_projects?
!self.valid?
end
def self.search(term, field = nil)
return all unless term.present?
case field&.to_s
when 'title'
search_by_title(term)
when 'key'
search_by_key(term)
else
search_by_title(term).or(search_by_key(term))
end
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
module ServicePing
class NonSqlServicePing < ApplicationRecord
REPORTING_CADENCE = RawUsageData::REPORTING_CADENCE
belongs_to :organization, class_name: 'Organizations::Organization'
attribute :payload, Gitlab::Database::Type::JsonPgSafe.new
validates :payload, presence: true
validates :recorded_at, presence: true, uniqueness: true
scope :for_current_reporting_cycle, -> do
where(created_at: RawUsageData::REPORTING_CADENCE.ago.beginning_of_day..)
.order(created_at: :desc)
end
end
end

View File

@ -2,6 +2,7 @@
class GitlabServicePingWorker # rubocop:disable Scalability/IdempotentWorker
LEASE_KEY = 'gitlab_service_ping_worker:ping'
NON_SQL_LEASE_KEY = 'gitlab_service_ping_worker:ping'
LEASE_TIMEOUT = 86400
include ApplicationWorker
@ -16,6 +17,10 @@ class GitlabServicePingWorker # rubocop:disable Scalability/IdempotentWorker
sidekiq_retry_in { |count| (count + 1) * 8.hours.to_i }
def perform(options = {})
day_lock(NON_SQL_LEASE_KEY) do
save_non_sql_data
end
# Sidekiq does not support keyword arguments, so the args need to be
# passed the old pre-Ruby 2.0 way.
#
@ -26,11 +31,7 @@ class GitlabServicePingWorker # rubocop:disable Scalability/IdempotentWorker
# See https://gitlab.com/gitlab-org/gitlab/-/issues/292929 for details
return if Gitlab.com? && triggered_from_cron
# Multiple Sidekiq workers could run this. We should only do this at most once a day.
in_lock(LEASE_KEY, ttl: LEASE_TIMEOUT) do
# Splay the request over a minute to avoid thundering herd problems.
sleep(rand(0.0..60.0).round(3))
day_lock(LEASE_KEY) do
ServicePing::SubmitService.new(payload: usage_data).execute
end
end
@ -51,6 +52,34 @@ class GitlabServicePingWorker # rubocop:disable Scalability/IdempotentWorker
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(err)
nil
end
private
def day_lock(key)
# Multiple Sidekiq workers could run this. We should only do this at most once a day.
in_lock(key, ttl: LEASE_TIMEOUT) do
# Splay the request over a minute to avoid thundering herd problems.
sleep(rand(0.0..60.0).round(3))
yield
end
end
def save_non_sql_data
payload = Gitlab::Usage::ServicePingReport.for(output: :non_sql_metrics_values)
record = {
recorded_at: payload[:recorded_at],
payload: payload,
created_at: Time.current,
updated_at: Time.current,
organization_id: Organizations::Organization.first.id
}
ServicePing::NonSqlServicePing.upsert(record, unique_by: :recorded_at)
rescue StandardError => err
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(err)
nil
end
end
GitlabServicePingWorker.prepend_mod

View File

@ -1,11 +1,10 @@
---
migration_job_name: MigrateOsSbomOccurrencesToComponentsWithoutPrefix
description: >-
Migrates sbom occurrences that belong to a sbom component
which could not be migrated previously because it would
conflict with a corrected component that already exists.
description: Migrates sbom occurrences that belong to a sbom component which could
not be migrated previously because it would conflict with a corrected component
that already exists.
feature_category: software_composition_analysis
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/152585'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/152585
milestone: '17.2'
queued_migration_version: 20240507152320
finalized_by:
finalized_by: '20241226131806'

View File

@ -0,0 +1,13 @@
---
table_name: non_sql_service_pings
classes:
- ServicePing::NonSqlServicePing
feature_categories:
- service_ping
description: Service Ping payload including only its non-database metrics
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/176659
milestone: '17.8'
gitlab_schema: gitlab_main_cell
sharding_key:
organization_id: organizations
table_size: small

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class CreateNonSqlServicePing < Gitlab::Database::Migration[2.2]
milestone '17.8'
def change
create_table :non_sql_service_pings do |t|
t.timestamps_with_timezone null: false
t.datetime_with_timezone :recorded_at, null: false
t.jsonb :payload, null: false
t.belongs_to :organization, null: false, foreign_key: { on_delete: :cascade }
t.index [:recorded_at], unique: true
end
end
end

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
class FinalizeMigrateOsSbomOccurrencesToComponentsWithoutPrefix < Gitlab::Database::Migration[2.2]
milestone '17.8'
disable_ddl_transaction!
restrict_gitlab_migration gitlab_schema: :gitlab_main
def up
ensure_batched_background_migration_is_finished(
job_class_name: 'MigrateOsSbomOccurrencesToComponentsWithoutPrefix',
table_name: :sbom_components,
column_name: :id,
job_arguments: [],
finalize: true
)
end
def down; end
end

View File

@ -0,0 +1 @@
4420f9c3516041d4c9a1733ec1c82133e8b02360276ca4cccaf1cb7eee857919

View File

@ -0,0 +1 @@
0803b818dd265abc32237bb3b9b683e08614c65b17ee3326c34d4e44d6ba64e0

View File

@ -15854,6 +15854,24 @@ CREATE SEQUENCE namespaces_sync_events_id_seq
ALTER SEQUENCE namespaces_sync_events_id_seq OWNED BY namespaces_sync_events.id;
CREATE TABLE non_sql_service_pings (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
recorded_at timestamp with time zone NOT NULL,
payload jsonb NOT NULL,
organization_id bigint NOT NULL
);
CREATE SEQUENCE non_sql_service_pings_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE non_sql_service_pings_id_seq OWNED BY non_sql_service_pings.id;
CREATE TABLE note_diff_files (
id bigint NOT NULL,
diff text NOT NULL,
@ -24190,6 +24208,8 @@ ALTER TABLE ONLY namespaces_storage_limit_exclusions ALTER COLUMN id SET DEFAULT
ALTER TABLE ONLY namespaces_sync_events ALTER COLUMN id SET DEFAULT nextval('namespaces_sync_events_id_seq'::regclass);
ALTER TABLE ONLY non_sql_service_pings ALTER COLUMN id SET DEFAULT nextval('non_sql_service_pings_id_seq'::regclass);
ALTER TABLE ONLY note_diff_files ALTER COLUMN id SET DEFAULT nextval('note_diff_files_id_seq'::regclass);
ALTER TABLE ONLY note_metadata ALTER COLUMN note_id SET DEFAULT nextval('note_metadata_note_id_seq'::regclass);
@ -26660,6 +26680,9 @@ ALTER TABLE ONLY namespaces_storage_limit_exclusions
ALTER TABLE ONLY namespaces_sync_events
ADD CONSTRAINT namespaces_sync_events_pkey PRIMARY KEY (id);
ALTER TABLE ONLY non_sql_service_pings
ADD CONSTRAINT non_sql_service_pings_pkey PRIMARY KEY (id);
ALTER TABLE ONLY note_diff_files
ADD CONSTRAINT note_diff_files_pkey PRIMARY KEY (id);
@ -31901,6 +31924,10 @@ CREATE INDEX index_namespaces_sync_events_on_namespace_id ON namespaces_sync_eve
CREATE INDEX index_non_requested_project_members_on_source_id_and_type ON members USING btree (source_id, source_type) WHERE ((requested_at IS NULL) AND ((type)::text = 'ProjectMember'::text));
CREATE INDEX index_non_sql_service_pings_on_organization_id ON non_sql_service_pings USING btree (organization_id);
CREATE UNIQUE INDEX index_non_sql_service_pings_on_recorded_at ON non_sql_service_pings USING btree (recorded_at);
CREATE UNIQUE INDEX index_note_diff_files_on_diff_note_id ON note_diff_files USING btree (diff_note_id);
CREATE INDEX index_note_metadata_on_note_id ON note_metadata USING btree (note_id);
@ -38926,6 +38953,9 @@ ALTER TABLE ONLY approval_group_rules
ALTER TABLE ONLY jira_imports
ADD CONSTRAINT fk_rails_675d38c03b FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE SET NULL;
ALTER TABLE ONLY non_sql_service_pings
ADD CONSTRAINT fk_rails_67cc36015b FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
ALTER TABLE ONLY vulnerability_findings_remediations
ADD CONSTRAINT fk_rails_681c85ae0f FOREIGN KEY (vulnerability_remediation_id) REFERENCES vulnerability_remediations(id) ON DELETE CASCADE;

View File

@ -15,7 +15,7 @@ Multiple types of pipelines can run in a project, including:
- Branch pipelines
- Tag pipelines
- Merge request pipelines
- Merge result pipelines
- Merged results pipelines
- Merge trains
These types of pipelines all appear on the **Pipelines** tab of a merge request.
@ -72,7 +72,7 @@ A *merged results pipeline* runs on the result of the source and target branches
It's a type of merge request pipeline.
These pipelines do not run by default. You must configure the jobs in the `.gitlab-ci.yml` file
to run as a merge request pipeline, and enable merge request pipelines.
to run as a merge request pipeline, and enable merged results pipelines.
These pipelines display a `merged results` label in pipeline lists.
@ -89,7 +89,7 @@ ensure the changes work with the content in the default branch,
but not content that others are merging at the same time.
These pipelines do not run by default. You must configure the jobs in the `.gitlab-ci.yml` file
to run as a merge request pipeline, enable merge request pipelines, and enable merge trains.
to run as a merge request pipeline, enable merged results pipelines, and enable merge trains.
These pipelines display a `merge train` label in pipeline lists.

View File

@ -63,6 +63,11 @@ to ignore the column and subsequently remove the column ignore (which would resu
In this example, the change to ignore the column went into release `12.5`.
NOTE:
Ignoring and dropping columns should not occur simultaneously in the same release. Dropping a column before proper ignoring it in the model can cause problems with zero-downtime migrations,
where the running instances can fail trying to look up for the removed column until the Rails schema cache expires. This can be an issue for self-managed customers whom attempt to follow zero-downtime upgrades,
forcing them to explicit restart all running GitLab instances to re-load the updated schema. To avoid this scenario, first, ignore the column (release M), then, drop it in the next release (release M+1).
### Dropping the column (release M+1)
Continuing our example, dropping the column goes into a _post-deployment_ migration in release `12.6`:

View File

@ -248,6 +248,67 @@ export default {
```
### Testing Vue router
When testing a full non-mocked `vue-router@4` there are a few caveats to keep in consideration for compatibility with Vue 2.
#### Window location
`vue-router@4` will not detect changes in window location, so setting a current URL with helpers such as `setWindowLocation` will not have an effect.
Instead, set an initial route or navigate to another route manually.
#### Initial route
When setting an initial route for your tests, `vue-router@4` will default to a `/` route. If the router configuration doesn't define a route for `/` path the test will error out by default. In this case, it is important to navigate to one of the defined routes before a component is created.
```javascript
router = createRouter();
await router.push({ name: 'tab', params: { tabId }})
```
Note the `await` is necessary, since [all navigations are always asynchronous](https://router.vuejs.org/guide/migration/#All-navigations-are-now-always-asynchronous).
#### Navigating to another route
To navigate to another route on an already mounted component, it is necessary to `await` calls to `push` or `replace` on the router.
```javascript
createComponent()
await router.push('/different-route')
```
When access to the `push` method is not available, for example in cases where we are triggering a `push` _inside the component's code_ through an event, `await waitForPromises` will be sufficient.
Consider the following component:
```html
<script>
export default {
methods: {
nextPage() {
this.$router.push({
path: 'some path'
})
}
}
}
</script>
<template>
<gl-keyset-pagination @push="nextPage" />
</template>
```
If we want to be able to test that the `$router.push` call is made, we must trigger the navigation through the `next` even on the `gl-keyset-pagination` component.
```javascript
wrapper.findComponent(GlKeysetNavigation).vm.$emit('push');
// $router.push is triggered in the component
await waitForPromises()
```
## Quarantine list
The `scripts/frontend/quarantined_vue3_specs.txt` file is built up of all the known failing Vue 3 test files.

View File

@ -227,6 +227,18 @@ The Owner role and custom roles with the `manage_security_policy_link` permissio
| Subgroup | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No |
| Project | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
#### Required permissions
To create and manage security policies:
- For policies enforced on groups: You must have at least the Maintainer role for the group.
- For policies enforced on projects:
- You must be the project owner.
- You must be a group member with permissions to create projects in the group.
NOTE:
If you're not a group member, you may face limitations in adding or editing policies for your project. The ability to create and manage policies requires permissions to create projects in the group. Make sure you have the required permissions in the group, even when working with project-level policies.
## Policy implementation
Implementation options for security policy projects differ slightly between GitLab.com, GitLab
@ -453,5 +465,8 @@ When working with security policies, consider these troubleshooting tips:
- When creating a merge request approval policy, neither the array `severity_levels` nor the array
`vulnerability_states` in the [`scan_finding` rule](../policies/merge_request_approval_policies.md#scan_finding-rule-type)
can be left empty. For a working rule, at least one entry must exist for each array.
- The owner of a project can enforce policies for that project, provided they also have permissions to create projects in the group.
Project owners who are not group members may face limitations in adding or editing policies. If you're unable to manage policies for your project,
contact your group administrator to ensure you have the necessary permissions in the group.
If you are still experiencing issues, you can [view recent reported bugs](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=popularity&state=opened&label_name%5B%5D=group%3A%3Asecurity%20policies&label_name%5B%5D=type%3A%3Abug&first_page_size=20) and raise new unreported issues.

View File

@ -619,3 +619,14 @@ Search in the following files:
Common failure reasons:
- Scanner removed by MR: Merge request approval policy expects that the scanners defined in the policy are present and that they successfully produce an artifact for comparison.
### Inconsistent approvals from merge request approval policies
If you notice any inconsistencies in your merge request approval rules, you can take either of the following steps to resynchronize your policies:
- Unassign and then reassign the security policy project to the affected group or project.
- Alternatively, you can update a policy to trigger that policy to resynchronize for the affected group or project.
These actions help ensure that your merge request approval policies are correctly applied and consistent across all merge requests.
If you continue to experience issues with merge request approval policies after taking these steps, contact GitLab support for assistance.

View File

@ -23,9 +23,7 @@ module API
end
get 'non_sql_metrics' do
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/325534')
data = Gitlab::Usage::ServicePingReport.for(output: :non_sql_metrics_values)
data = ::ServicePing::NonSqlServicePing.for_current_reporting_cycle.pick(:payload) || {}
present data
end

View File

@ -50,7 +50,6 @@ module Gitlab
end
end
end
strong_memoize_attr :predefined_pipeline_variables
def predefined_commit_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|

View File

@ -2287,7 +2287,7 @@ msgstr ""
msgid "AIPoweredSM|Enable %{link_start}AI-powered features%{link_end} for this instance."
msgstr ""
msgid "AISummary|Generates a summary of all comments"
msgid "AISummary|Generates a summary of this issue"
msgstr ""
msgid "AISummary|View summary"
@ -9477,6 +9477,9 @@ msgstr ""
msgid "Billing|Unlimited members during your trial"
msgstr ""
msgid "Billing|User successfully scheduled for removal. This process might take some time. Refresh the page to see the changes."
msgstr ""
msgid "Billing|User was successfully removed"
msgstr ""
@ -17899,6 +17902,9 @@ msgstr ""
msgid "DastProfiles|Choose a scan method"
msgstr ""
msgid "DastProfiles|Comma-separated list of check identifiers to use for the scan. For identifiers, see %{linkStart}vulnerability checks.%{linkEnd}"
msgstr ""
msgid "DastProfiles|Could not create the scanner profile. Please try again."
msgstr ""
@ -19198,9 +19204,15 @@ msgstr ""
msgid "DeployKeys|Loading deploy keys"
msgstr ""
msgid "DeployKeys|Name"
msgstr ""
msgid "DeployKeys|No deploy keys found, start by adding a new one above."
msgstr ""
msgid "DeployKeys|No search results found."
msgstr ""
msgid "DeployKeys|Privately accessible deploy keys"
msgstr ""
@ -19213,6 +19225,9 @@ msgstr ""
msgid "DeployKeys|Read access only"
msgstr ""
msgid "DeployKeys|SHA"
msgstr ""
msgid "DeployTokens|Active deploy tokens"
msgstr ""
@ -49776,6 +49791,9 @@ msgstr ""
msgid "Search comment templates"
msgstr ""
msgid "Search deploy keys"
msgstr ""
msgid "Search files"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@ -1,293 +1,300 @@
{
"qa/specs/features/api/10_govern/group_access_token_spec.rb": 21.292825408,
"qa/specs/features/api/10_govern/project_access_token_spec.rb": 58.77345614,
"qa/specs/features/api/12_systems/gitaly/automatic_failover_and_recovery_spec.rb": 106.38666092700001,
"qa/specs/features/api/12_systems/gitaly/backend_node_recovery_spec.rb": 110.26373077,
"qa/specs/features/api/12_systems/gitaly/distributed_reads_spec.rb": 114.791398187,
"qa/specs/features/api/12_systems/gitaly/gitaly_mtls_spec.rb": 14.619017919,
"qa/specs/features/api/1_manage/import/import_github_repo_spec.rb": 99.342150632,
"qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb": 59.597007777,
"qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb": 61.867845029,
"qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb": 231.55766656999998,
"qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb": 103.315897811,
"qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb": 105.398550145,
"qa/specs/features/api/1_manage/rate_limits_spec.rb": 13.541849982,
"qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb": 22.46068172,
"qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb": 33.713225105,
"qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb": 18.393188567,
"qa/specs/features/api/3_create/merge_request/push_options_remove_source_branch_spec.rb": 40.168960188,
"qa/specs/features/api/3_create/merge_request/push_options_target_branch_spec.rb": 30.185151323,
"qa/specs/features/api/3_create/merge_request/push_options_title_description_spec.rb": 36.321915457,
"qa/specs/features/api/3_create/merge_request/view_merge_requests_spec.rb": 2.164663043,
"qa/specs/features/api/3_create/repository/add_list_delete_branches_spec.rb": 14.383655059,
"qa/specs/features/api/3_create/repository/commit_to_templated_project_spec.rb": 30.210800012,
"qa/specs/features/api/3_create/repository/default_branch_name_setting_spec.rb": 11.776323319,
"qa/specs/features/api/3_create/repository/files_spec.rb": 6.781143476,
"qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb": 9.868924243,
"qa/specs/features/api/3_create/repository/push_postreceive_idempotent_spec.rb": 32.50872775,
"qa/specs/features/api/3_create/repository/storage_size_spec.rb": 17.641925405,
"qa/specs/features/api/3_create/repository/tag_revision_trigger_prereceive_hook_spec.rb": 9.352787971,
"qa/specs/features/api/4_verify/api_variable_inheritance_with_forward_pipeline_variables_spec.rb": 74.590883802,
"qa/specs/features/api/4_verify/cancel_pipeline_when_block_user_spec.rb": 18.506513406,
"qa/specs/features/api/4_verify/file_variable_spec.rb": 42.153242281,
"qa/specs/features/api/4_verify/job_downloads_artifacts_spec.rb": 26.801359395,
"qa/specs/features/api/8_monitor/metrics_spec.rb": 4.150760377,
"qa/specs/features/api/9_data_stores/user_inherited_access_spec.rb": 94.54301901900001,
"qa/specs/features/api/9_data_stores/users_spec.rb": 5.0050631690000005,
"qa/specs/features/browser_ui/10_govern/group/group_access_token_spec.rb": 11.916970668,
"qa/specs/features/browser_ui/10_govern/login/2fa_recovery_spec.rb": 52.949378718,
"qa/specs/features/browser_ui/10_govern/login/2fa_ssh_recovery_spec.rb": 52.627335929,
"qa/specs/features/browser_ui/10_govern/login/log_in_spec.rb": 8.597219459,
"qa/specs/features/browser_ui/10_govern/login/log_in_with_2fa_spec.rb": 91.526492906,
"qa/specs/features/browser_ui/10_govern/login/log_into_gitlab_via_ldap_spec.rb": 3.858622198,
"qa/specs/features/browser_ui/10_govern/login/log_into_mattermost_via_gitlab_spec.rb": 29.044190128,
"qa/specs/features/browser_ui/10_govern/login/login_via_instance_wide_saml_sso_spec.rb": 16.549776694,
"qa/specs/features/browser_ui/10_govern/login/login_via_oauth_and_oidc_with_gitlab_as_idp_spec.rb": 549.001422735,
"qa/specs/features/browser_ui/10_govern/login/oauth_login_with_github_spec.rb": 39.957757582,
"qa/specs/features/browser_ui/10_govern/login/register_spec.rb": 158.068057297,
"qa/specs/features/browser_ui/10_govern/project/project_access_token_spec.rb": 17.960214517,
"qa/specs/features/browser_ui/10_govern/user/impersonation_token_spec.rb": 34.629349245,
"qa/specs/features/browser_ui/10_govern/user/user_access_termination_spec.rb": 56.19628031999999,
"qa/specs/features/browser_ui/14_analytics/performance_bar_spec.rb": 25.383690228,
"qa/specs/features/browser_ui/14_analytics/service_ping_default_enabled_spec.rb": 13.290171652,
"qa/specs/features/browser_ui/14_analytics/service_ping_disabled_spec.rb": 11.376754271,
"qa/specs/features/browser_ui/1_manage/integrations/jenkins/jenkins_build_status_spec.rb": 75.864379245,
"qa/specs/features/browser_ui/1_manage/integrations/jira/jira_basic_integration_spec.rb": 61.02447549600001,
"qa/specs/features/browser_ui/1_manage/integrations/jira/jira_issue_import_spec.rb": 36.792636561,
"qa/specs/features/browser_ui/1_manage/integrations/pipeline_status_emails_spec.rb": 68.622276451,
"qa/specs/features/browser_ui/1_manage/migration/gitlab_migration_group_spec.rb": 56.948429524,
"qa/specs/features/browser_ui/2_plan/design_management/add_design_content_spec.rb": 21.492519455,
"qa/specs/features/browser_ui/2_plan/design_management/archive_design_content_spec.rb": 30.335954674,
"qa/specs/features/browser_ui/2_plan/design_management/modify_design_content_spec.rb": 24.634931267,
"qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb": 10.80053397,
"qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb": 23.451307294,
"qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb": 23.530986217,
"qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb": 14.429990983,
"qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb": 40.470417724,
"qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb": 15.204585262,
"qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb": 16.424393137,
"qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb": 18.820865025,
"qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb": 13.735862218,
"qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb": 26.321543017,
"qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb": 15.450427143,
"qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb": 8.925181976,
"qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_spec.rb": 62.258667012000004,
"qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb": 14.178468578,
"qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb": 15.834637519,
"qa/specs/features/browser_ui/2_plan/project_wiki/project_based_content_creation_spec.rb": 71.037104535,
"qa/specs/features/browser_ui/2_plan/project_wiki/project_based_content_manipulation_spec.rb": 34.906604229,
"qa/specs/features/browser_ui/2_plan/project_wiki/project_based_directory_management_spec.rb": 14.263791212,
"qa/specs/features/browser_ui/2_plan/project_wiki/project_based_file_upload_spec.rb": 37.031858901,
"qa/specs/features/browser_ui/2_plan/project_wiki/project_based_list_spec.rb": 48.581356301,
"qa/specs/features/browser_ui/2_plan/project_wiki/project_based_page_deletion_spec.rb": 33.846381059,
"qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb": 12.371016309,
"qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_a_merge_spec.rb": 63.547941282,
"qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb": 23.4687869,
"qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb": 60.969709685,
"qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb": 32.271106195,
"qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb": 45.875101275,
"qa/specs/features/browser_ui/3_create/merge_request/merge_request_set_to_auto_merge_spec.rb": 78.129887869,
"qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb": 60.016714891,
"qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb": 30.763812259,
"qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb": 50.698660882,
"qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb": 41.076940585,
"qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb": 52.09487054,
"qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb": 60.366353886,
"qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb": 111.018211886,
"qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb": 66.92301645399999,
"qa/specs/features/browser_ui/3_create/repository/add_new_branch_rule_spec.rb": 20.976146523,
"qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb": 14.747170313,
"qa/specs/features/browser_ui/3_create/repository/clone_spec.rb": 21.616592722,
"qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb": 16.613888421,
"qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb": 15.676393279,
"qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb": 16.657529998,
"qa/specs/features/browser_ui/3_create/repository/file/file_with_unusual_name_spec.rb": 24.222458953,
"qa/specs/features/browser_ui/3_create/repository/license_detection_spec.rb": 36.142900288,
"qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb": 91.26960423,
"qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb": 22.651644435,
"qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb": 19.731780507,
"qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb": 18.524353881,
"qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb": 44.297400618,
"qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb": 51.238033209,
"qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb": 51.806164437,
"qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb": 36.996673379,
"qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb": 26.898065129,
"qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb": 13.687256633,
"qa/specs/features/browser_ui/3_create/repository/ssh_key_support_create_spec.rb": 15.52431686,
"qa/specs/features/browser_ui/3_create/repository/ssh_key_support_delete_spec.rb": 11.172781194,
"qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb": 34.053905435000004,
"qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb": 40.85286376,
"qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb": 26.426332332999998,
"qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb": 54.995337821999996,
"qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb": 57.673889031,
"qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb": 23.806625001,
"qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb": 7.202874913,
"qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb": 9.552476166,
"qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb": 13.488124133,
"qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_with_multiple_files_spec.rb": 19.42985945,
"qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb": 27.697845423,
"qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb": 19.185116236,
"qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb": 58.205537418999995,
"qa/specs/features/browser_ui/3_create/source_editor/source_editor_toolbar_spec.rb": 21.152038543,
"qa/specs/features/browser_ui/3_create/web_ide/add_first_file_in_web_ide_spec.rb": 39.733794594,
"qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb": 70.73101525,
"qa/specs/features/browser_ui/3_create/web_ide/closing_web_ide_with_unsaved_changes_spec.rb": 21.146160918,
"qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb": 120.828693709,
"qa/specs/features/browser_ui/4_verify/ci_components_catalog/ci_catalog_sorting_spec.rb": 77.72783598699999,
"qa/specs/features/browser_ui/4_verify/ci_components_catalog/run_component_in_project_pipeline_spec.rb": 35.714132863,
"qa/specs/features/browser_ui/4_verify/ci_job_artifacts/expose_job_artifacts_in_mr_spec.rb": 48.942937448,
"qa/specs/features/browser_ui/4_verify/ci_job_artifacts/job_artifacts_access_keyword_spec.rb": 244.924054751,
"qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_pipelines_spec.rb": 307.650354975,
"qa/specs/features/browser_ui/4_verify/ci_project_artifacts/user_can_bulk_delete_artifacts_spec.rb": 58.722410572,
"qa/specs/features/browser_ui/4_verify/ci_variable/custom_variable_spec.rb": 45.938311353,
"qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb": 92.17030909100001,
"qa/specs/features/browser_ui/4_verify/ci_variable/prefill_variables_spec.rb": 43.533821681,
"qa/specs/features/browser_ui/4_verify/ci_variable/raw_variables_defined_in_yaml_spec.rb": 27.447639078,
"qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_inheritable_when_forward_pipeline_variables_true_spec.rb": 83.762091453,
"qa/specs/features/browser_ui/4_verify/pipeline/include_local_config_file_paths_with_wildcard_spec.rb": 44.808915579,
"qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb": 72.257350596,
"qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_multiple_projects_spec.rb": 63.554626878,
"qa/specs/features/browser_ui/4_verify/pipeline/parent_child_pipelines_independent_relationship_spec.rb": 81.506064036,
"qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb": 57.635359456,
"qa/specs/features/browser_ui/4_verify/pipeline/pipeline_with_image_pull_policy_spec.rb": 172.862974224,
"qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_with_manual_jobs_spec.rb": 75.172058017,
"qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb": 52.790153865,
"qa/specs/features/browser_ui/4_verify/pipeline/trigger_matrix_spec.rb": 39.728655647,
"qa/specs/features/browser_ui/4_verify/pipeline/update_ci_file_with_pipeline_editor_spec.rb": 27.622377828,
"qa/specs/features/browser_ui/4_verify/runner/deprecated_registration_token_spec.rb": 12.655460869,
"qa/specs/features/browser_ui/4_verify/runner/fleet_visibility/group_runner_counts_spec.rb": 10.626388294,
"qa/specs/features/browser_ui/4_verify/runner/fleet_visibility/group_runner_status_counts_spec.rb": 13.825469005,
"qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb": 12.218864953,
"qa/specs/features/browser_ui/4_verify/runner/register_project_runner_spec.rb": 26.485737728,
"qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb": 50.056001098,
"qa/specs/features/browser_ui/5_package/container_registry/self_managed/container_registry_spec.rb": 336.432383929,
"qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb": 188.18153665,
"qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb": 68.09599809,
"qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb": 43.950574153,
"qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb": 78.143713432,
"qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb": 46.665423323,
"qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb": 244.792452985,
"qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb": 467.171727175,
"qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb": 183.739297293,
"qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb": 254.05064440100003,
"qa/specs/features/browser_ui/5_package/package_registry/npm/npm_group_level_spec.rb": 297.344137831,
"qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb": 278.056128247,
"qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb": 85.848878087,
"qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb": 18.383921387,
"qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb": 135.045576229,
"qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb": 12.125774728,
"qa/specs/features/browser_ui/8_monitor/alert_management/alert_settings_create_new_alerts_spec.rb": 35.195861934,
"qa/specs/features/browser_ui/8_monitor/alert_management/automatically_creates_incident_for_alert_spec.rb": 54.548798577,
"qa/specs/features/browser_ui/8_monitor/alert_management/create_alert_using_authorization_key_spec.rb": 35.07802645,
"qa/specs/features/browser_ui/8_monitor/alert_management/email_notification_for_alert_spec.rb": 70.45604070499999,
"qa/specs/features/browser_ui/8_monitor/alert_management/recovery_alert_resolves_correct_alert_spec.rb": 22.901610338,
"qa/specs/features/browser_ui/9_data_stores/group/create_group_with_mattermost_team_spec.rb": 7.735296021,
"qa/specs/features/browser_ui/9_data_stores/group/group_member_access_request_spec.rb": 61.254421224,
"qa/specs/features/browser_ui/9_data_stores/group/transfer_project_spec.rb": 25.051882327,
"qa/specs/features/browser_ui/9_data_stores/project/add_project_member_spec.rb": 17.365077304,
"qa/specs/features/browser_ui/9_data_stores/project/create_project_badge_spec.rb": 14.37479645,
"qa/specs/features/browser_ui/9_data_stores/project/create_project_spec.rb": 34.096985218,
"qa/specs/features/browser_ui/9_data_stores/project/dashboard_images_spec.rb": 11.620770705,
"qa/specs/features/browser_ui/9_data_stores/project/invite_group_to_project_spec.rb": 54.864527041,
"qa/specs/features/browser_ui/9_data_stores/project/project_owner_permissions_spec.rb": 56.810086960999996,
"qa/specs/features/browser_ui/9_data_stores/project/view_project_activity_spec.rb": 16.112615475,
"qa/specs/features/browser_ui/9_data_stores/user/follow_user_activity_spec.rb": 19.937401716,
"qa/specs/features/browser_ui/9_data_stores/user/parent_group_access_termination_spec.rb": 24.204681337,
"qa/specs/features/browser_ui/9_data_stores/user/user_inherited_access_spec.rb": 31.201705633,
"qa/specs/features/ee/api/10_govern/compliance_pipeline_spec.rb": 23.570860778,
"qa/specs/features/ee/api/10_govern/instance_audit_event_streaming_spec.rb": 19.944387178,
"qa/specs/features/ee/api/10_govern/user/minimal_access_user_spec.rb": 53.003006898,
"qa/specs/features/ee/api/1_manage/import/import_github_repo_spec.rb": 120.85971464,
"qa/specs/features/ee/api/1_manage/integrations/group_webhook_events_spec.rb": 6.740380055,
"qa/specs/features/ee/api/1_manage/migration/gitlab_migration_group_spec.rb": 87.791085634,
"qa/specs/features/ee/api/2_plan/epics_milestone_dates_spec.rb": 48.221363068,
"qa/specs/features/ee/api/3_create/code_suggestions_spec.rb": 18.536343695,
"qa/specs/features/ee/api/9_data_stores/elasticsearch/index_tests/user_index/user_index_spec.rb": 45.763265588,
"qa/specs/features/ee/api/9_data_stores/elasticsearch/nightly_elasticsearch_test_spec.rb": 22.988915057,
"qa/specs/features/ee/browser_ui/10_govern/change_vulnerability_status_spec.rb": 56.991994628,
"qa/specs/features/ee/browser_ui/10_govern/create_merge_request_with_secure_spec.rb": 84.180839076,
"qa/specs/features/ee/browser_ui/10_govern/dismissed_vulnerabilities_in_security_widget_spec.rb": 106.11828759,
"qa/specs/features/ee/browser_ui/10_govern/export_vulnerability_report_spec.rb": 23.175949007,
"qa/specs/features/ee/browser_ui/10_govern/fix_vulnerability_workflow_spec.rb": 150.971166682,
"qa/specs/features/ee/browser_ui/10_govern/group/group_audit_event_streaming_spec.rb": 67.95569473500001,
"qa/specs/features/ee/browser_ui/10_govern/group/group_audit_logs_1_spec.rb": 129.58922590900002,
"qa/specs/features/ee/browser_ui/10_govern/group/group_ldap_sync_spec.rb": 110.072735534,
"qa/specs/features/ee/browser_ui/10_govern/group/group_saml_enforced_sso_git_access_spec.rb": 20.203679238,
"qa/specs/features/ee/browser_ui/10_govern/group/group_saml_enforced_sso_new_account_spec.rb": 214.36029539100002,
"qa/specs/features/ee/browser_ui/10_govern/group/group_saml_non_enforced_sso_spec.rb": 67.333580497,
"qa/specs/features/ee/browser_ui/10_govern/group/restrict_by_ip_address_spec.rb": 105.37253660799999,
"qa/specs/features/ee/browser_ui/10_govern/group/saml_sso_merge_request_approve_spec.rb": 45.102574187,
"qa/specs/features/ee/browser_ui/10_govern/group_pipeline_execution_policy_spec.rb": 279.856075975,
"qa/specs/features/ee/browser_ui/10_govern/instance/instance_audit_logs_spec.rb": 109.81185797700002,
"qa/specs/features/ee/browser_ui/10_govern/project/project_audit_logs_spec.rb": 136.785917369,
"qa/specs/features/ee/browser_ui/10_govern/project_security_dashboard_spec.rb": 34.608999935,
"qa/specs/features/ee/browser_ui/10_govern/scan_execution_policy_vulnerabilities_spec.rb": 117.660890761,
"qa/specs/features/ee/browser_ui/10_govern/scan_result_policy_vulnerabilities_spec.rb": 106.606844787,
"qa/specs/features/ee/browser_ui/10_govern/security_policies_spec.rb": 67.067841205,
"qa/specs/features/ee/browser_ui/10_govern/security_reports_spec.rb": 295.312635643,
"qa/specs/features/ee/browser_ui/10_govern/user/minimal_access_user_spec.rb": 18.108336934,
"qa/specs/features/ee/browser_ui/10_govern/vulnerabilities_jira_integration_spec.rb": 23.199987596,
"qa/specs/features/ee/browser_ui/10_govern/vulnerability_management_spec.rb": 318.770283663,
"qa/specs/features/ee/browser_ui/10_govern/vulnerability_security_training_spec.rb": 133.534905354,
"qa/specs/features/ee/browser_ui/11_fulfillment/license/cloud_activation_spec.rb": 22.419658219,
"qa/specs/features/ee/browser_ui/11_fulfillment/license/license_spec.rb": 9.775632526,
"qa/specs/features/ee/browser_ui/11_fulfillment/utilization/user_registration_billing_spec.rb": 17.974371147,
"qa/specs/features/ee/browser_ui/13_secure/cvs_dependency_scanning_spec.rb": 54.117717953,
"qa/specs/features/ee/browser_ui/13_secure/enable_advanced_sast_spec.rb": 108.847443909,
"qa/specs/features/ee/browser_ui/13_secure/enable_scanning_from_configuration_spec.rb": 51.571517153,
"qa/specs/features/ee/browser_ui/13_secure/secret_push_protection_spec.rb": 34.219697106,
"qa/specs/features/ee/browser_ui/16_ai_powered/duo_chat/duo_chat_spec.rb": 23.757181817,
"qa/specs/features/ee/browser_ui/1_manage/integrations/jira_issues_list_spec.rb": 59.142817499,
"qa/specs/features/ee/browser_ui/2_plan/analytics/contribution_analytics_spec.rb": 28.117741728,
"qa/specs/features/ee/browser_ui/2_plan/analytics/mr_analytics_spec.rb": 37.20502943,
"qa/specs/features/ee/browser_ui/2_plan/analytics/value_stream_analytics_spec.rb": 29.179811063000002,
"qa/specs/features/ee/browser_ui/2_plan/burndown_chart/burndown_chart_spec.rb": 13.7261006,
"qa/specs/features/ee/browser_ui/2_plan/custom_email/custom_email_spec.rb": 11.128126458,
"qa/specs/features/ee/browser_ui/2_plan/epic/epics_management_spec.rb": 139.44998006600002,
"qa/specs/features/ee/browser_ui/2_plan/epic/promote_issue_to_epic_spec.rb": 23.014772418,
"qa/specs/features/ee/browser_ui/2_plan/epic/roadmap_spec.rb": 7.269843157,
"qa/specs/features/ee/browser_ui/2_plan/group_wiki/create_group_wiki_page_spec.rb": 25.583555508,
"qa/specs/features/ee/browser_ui/2_plan/group_wiki/delete_group_wiki_page_spec.rb": 12.123082334,
"qa/specs/features/ee/browser_ui/2_plan/group_wiki/file_upload_group_wiki_page_spec.rb": 32.424805646,
"qa/specs/features/ee/browser_ui/2_plan/insights/default_insights_spec.rb": 18.013317301,
"qa/specs/features/ee/browser_ui/2_plan/issue/default_issue_template_spec.rb": 25.952859244,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/configurable_issue_board_spec.rb": 9.187323346,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/configure_issue_board_by_label_spec.rb": 17.722947873,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/create_group_issue_board_spec.rb": 19.05606516,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/group_issue_boards_spec.rb": 16.229989849,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/project_issue_boards_spec.rb": 35.85179492899999,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/read_only_board_configuration_spec.rb": 18.345792104,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/sum_of_issues_weights_spec.rb": 13.761549874,
"qa/specs/features/ee/browser_ui/2_plan/issues_analytics/issues_analytics_spec.rb": 22.700323375,
"qa/specs/features/ee/browser_ui/2_plan/issues_weight/issue_weight_visualization_spec.rb": 24.70764068,
"qa/specs/features/ee/browser_ui/2_plan/iterations/assign_group_iteration_spec.rb": 25.305083698,
"qa/specs/features/ee/browser_ui/2_plan/iterations/create_group_iteration_spec.rb": 38.232783679,
"qa/specs/features/ee/browser_ui/2_plan/multiple_assignees_for_issues/four_assignees_spec.rb": 15.104652028,
"qa/specs/features/ee/browser_ui/2_plan/multiple_assignees_for_issues/more_than_four_assignees_spec.rb": 36.102762499,
"qa/specs/features/ee/browser_ui/2_plan/scoped_labels/editing_scoped_labels_spec.rb": 14.507732116,
"qa/specs/features/ee/browser_ui/3_create/merge_request/add_batch_comments_in_merge_request_spec.rb": 73.196643162,
"qa/specs/features/ee/browser_ui/3_create/merge_request/approval_rules_spec.rb": 79.735368842,
"qa/specs/features/ee/browser_ui/3_create/merge_request/default_merge_request_template_spec.rb": 31.563245676,
"qa/specs/features/ee/browser_ui/3_create/repository/assign_code_owners_spec.rb": 41.90123845,
"qa/specs/features/ee/browser_ui/3_create/repository/code_owners_spec.rb": 21.656330915,
"qa/specs/features/ee/browser_ui/3_create/repository/code_owners_with_protected_branch_and_squashed_commits_spec.rb": 35.744831713,
"qa/specs/features/ee/browser_ui/3_create/repository/file_locking_spec.rb": 208.134396601,
"qa/specs/features/ee/browser_ui/3_create/repository/group_file_template_spec.rb": 118.018548409,
"qa/specs/features/ee/browser_ui/3_create/repository/merge_with_code_owner_in_root_group_spec.rb": 128.18337795,
"qa/specs/features/ee/browser_ui/3_create/repository/merge_with_code_owner_in_subgroup_spec.rb": 139.017830253,
"qa/specs/features/ee/browser_ui/3_create/repository/project_templates_spec.rb": 83.65661239800001,
"qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_http_spec.rb": 29.391393683,
"qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_ssh_with_key_spec.rb": 41.57000241,
"qa/specs/features/ee/browser_ui/3_create/repository/push_rules_spec.rb": 326.84030566,
"qa/specs/features/ee/browser_ui/3_create/repository/restrict_push_protected_branch_spec.rb": 156.26337145,
"qa/specs/features/ee/browser_ui/3_create/web_ide/code_suggestions_in_web_ide_spec.rb": 97.74000057600001,
"qa/specs/features/ee/browser_ui/4_verify/multi-project_pipelines_spec.rb": 101.956097433,
"qa/specs/features/ee/browser_ui/4_verify/parent_child_pipelines_dependent_relationship_spec.rb": 146.75246170999998,
"qa/specs/features/ee/browser_ui/4_verify/pipeline_for_merged_result_spec.rb": 55.381786352,
"qa/specs/features/ee/browser_ui/4_verify/pipeline_subscription_with_group_owned_project_spec.rb": 37.774624194,
"qa/specs/features/ee/browser_ui/5_package/dependency_proxy_sso_spec.rb": 89.970848925,
"qa/specs/features/ee/browser_ui/8_monitor/incident_management/incident_quick_action_spec.rb": 20.717759859,
"qa/specs/features/ee/browser_ui/9_data_stores/elasticsearch/elasticsearch_reindexing_spec.rb": 274.44643549,
"qa/specs/features/ee/browser_ui/9_data_stores/group/prevent_forking_outside_group_spec.rb": 39.883363867,
"qa/specs/features/ee/browser_ui/9_data_stores/group/share_group_with_group_spec.rb": 28.106405587
"qa/specs/features/api/10_govern/group_access_token_spec.rb": 25.321874106000003,
"qa/specs/features/api/10_govern/project_access_token_spec.rb": 53.272323148,
"qa/specs/features/api/12_systems/gitaly/automatic_failover_and_recovery_spec.rb": 106.119128331,
"qa/specs/features/api/12_systems/gitaly/backend_node_recovery_spec.rb": 112.051829904,
"qa/specs/features/api/12_systems/gitaly/distributed_reads_spec.rb": 117.314365588,
"qa/specs/features/api/12_systems/gitaly/gitaly_mtls_spec.rb": 14.149886219,
"qa/specs/features/api/1_manage/import/import_github_repo_spec.rb": 102.330635577,
"qa/specs/features/api/1_manage/integrations/webhook_events_spec.rb": 47.933066109,
"qa/specs/features/api/1_manage/migration/gitlab_migration_group_spec.rb": 65.126115825,
"qa/specs/features/api/1_manage/migration/gitlab_migration_issue_spec.rb": 225.677627877,
"qa/specs/features/api/1_manage/migration/gitlab_migration_pipeline_spec.rb": 107.122100762,
"qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb": 107.79710926,
"qa/specs/features/api/1_manage/rate_limits_spec.rb": 20.016023334,
"qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb": 12.474641797,
"qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb": 29.122509395999998,
"qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb": 12.51509228,
"qa/specs/features/api/3_create/merge_request/push_options_remove_source_branch_spec.rb": 32.961384504,
"qa/specs/features/api/3_create/merge_request/push_options_target_branch_spec.rb": 30.255329724,
"qa/specs/features/api/3_create/merge_request/push_options_title_description_spec.rb": 24.073678634,
"qa/specs/features/api/3_create/merge_request/view_merge_requests_spec.rb": 2.385253283,
"qa/specs/features/api/3_create/repository/add_list_delete_branches_spec.rb": 12.338016978,
"qa/specs/features/api/3_create/repository/commit_to_templated_project_spec.rb": 10.476819228,
"qa/specs/features/api/3_create/repository/default_branch_name_setting_spec.rb": 8.653057031,
"qa/specs/features/api/3_create/repository/files_spec.rb": 5.917399502,
"qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb": 7.508614361,
"qa/specs/features/api/3_create/repository/push_postreceive_idempotent_spec.rb": 20.67537871,
"qa/specs/features/api/3_create/repository/storage_size_spec.rb": 21.347464394,
"qa/specs/features/api/3_create/repository/tag_revision_trigger_prereceive_hook_spec.rb": 3.922157381,
"qa/specs/features/api/4_verify/api_variable_inheritance_with_forward_pipeline_variables_spec.rb": 96.052391433,
"qa/specs/features/api/4_verify/cancel_pipeline_when_block_user_spec.rb": 11.050224778,
"qa/specs/features/api/4_verify/file_variable_spec.rb": 120.038631021,
"qa/specs/features/api/4_verify/job_downloads_artifacts_spec.rb": 31.798211852,
"qa/specs/features/api/8_monitor/metrics_spec.rb": 4.373886454,
"qa/specs/features/api/9_data_stores/user_inherited_access_spec.rb": 125.967211643,
"qa/specs/features/api/9_data_stores/users_spec.rb": 4.846089744,
"qa/specs/features/browser_ui/10_govern/group/group_access_token_spec.rb": 12.416878289,
"qa/specs/features/browser_ui/10_govern/login/2fa_recovery_spec.rb": 40.736411667,
"qa/specs/features/browser_ui/10_govern/login/2fa_ssh_recovery_spec.rb": 51.376411912,
"qa/specs/features/browser_ui/10_govern/login/log_in_spec.rb": 8.8816555,
"qa/specs/features/browser_ui/10_govern/login/log_in_with_2fa_spec.rb": 85.347962469,
"qa/specs/features/browser_ui/10_govern/login/log_into_gitlab_via_ldap_spec.rb": 4.003147163,
"qa/specs/features/browser_ui/10_govern/login/log_into_mattermost_via_gitlab_spec.rb": 29.797239924,
"qa/specs/features/browser_ui/10_govern/login/login_via_instance_wide_saml_sso_spec.rb": 15.177876306,
"qa/specs/features/browser_ui/10_govern/login/login_via_oauth_and_oidc_with_gitlab_as_idp_spec.rb": 551.851899519,
"qa/specs/features/browser_ui/10_govern/login/oauth_login_with_github_spec.rb": 40.76536544,
"qa/specs/features/browser_ui/10_govern/login/register_spec.rb": 176.948310975,
"qa/specs/features/browser_ui/10_govern/project/project_access_token_spec.rb": 15.303304661,
"qa/specs/features/browser_ui/10_govern/user/impersonation_token_spec.rb": 33.997621654,
"qa/specs/features/browser_ui/10_govern/user/user_access_termination_spec.rb": 42.511164506,
"qa/specs/features/browser_ui/14_analytics/performance_bar_spec.rb": 26.77910319,
"qa/specs/features/browser_ui/14_analytics/service_ping_default_enabled_spec.rb": 12.255416314,
"qa/specs/features/browser_ui/14_analytics/service_ping_disabled_spec.rb": 11.361895569,
"qa/specs/features/browser_ui/1_manage/integrations/jenkins/jenkins_build_status_spec.rb": 65.726797538,
"qa/specs/features/browser_ui/1_manage/integrations/jira/jira_basic_integration_spec.rb": 67.120292665,
"qa/specs/features/browser_ui/1_manage/integrations/jira/jira_issue_import_spec.rb": 43.419446193,
"qa/specs/features/browser_ui/1_manage/integrations/pipeline_status_emails_spec.rb": 62.895466196,
"qa/specs/features/browser_ui/1_manage/migration/gitlab_migration_group_spec.rb": 57.482644066,
"qa/specs/features/browser_ui/2_plan/design_management/add_design_content_spec.rb": 25.039281291,
"qa/specs/features/browser_ui/2_plan/design_management/archive_design_content_spec.rb": 28.397552321,
"qa/specs/features/browser_ui/2_plan/design_management/modify_design_content_spec.rb": 23.431742118,
"qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb": 18.455595225,
"qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb": 22.961950361,
"qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb": 14.910996904,
"qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb": 17.02861154,
"qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb": 41.502508664000004,
"qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb": 23.560925428,
"qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb": 16.308239893,
"qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb": 27.46052375,
"qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb": 22.085208752,
"qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb": 21.40727448,
"qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb": 15.363405811,
"qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb": 10.498062806,
"qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_spec.rb": 67.83671066100001,
"qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb": 14.331517296,
"qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb": 13.564887304,
"qa/specs/features/browser_ui/2_plan/project_wiki/project_based_content_creation_spec.rb": 71.041997501,
"qa/specs/features/browser_ui/2_plan/project_wiki/project_based_content_manipulation_spec.rb": 34.687098155,
"qa/specs/features/browser_ui/2_plan/project_wiki/project_based_directory_management_spec.rb": 13.655745329,
"qa/specs/features/browser_ui/2_plan/project_wiki/project_based_file_upload_spec.rb": 29.537264004,
"qa/specs/features/browser_ui/2_plan/project_wiki/project_based_list_spec.rb": 40.643522051000005,
"qa/specs/features/browser_ui/2_plan/project_wiki/project_based_page_deletion_spec.rb": 36.624872544,
"qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb": 15.167670986,
"qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_a_merge_spec.rb": 43.998671977,
"qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb": 20.156445747,
"qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb": 60.429294274,
"qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb": 36.888548532,
"qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb": 36.073039841,
"qa/specs/features/browser_ui/3_create/merge_request/merge_request_set_to_auto_merge_spec.rb": 81.490683494,
"qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb": 66.782334071,
"qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb": 18.123365623,
"qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb": 34.238904748,
"qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb": 40.373397418,
"qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb": 46.009233379,
"qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb": 61.84497496,
"qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb": 70.415826763,
"qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb": 64.98051042099999,
"qa/specs/features/browser_ui/3_create/repository/add_new_branch_rule_spec.rb": 22.797458782,
"qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb": 12.771647668,
"qa/specs/features/browser_ui/3_create/repository/clone_spec.rb": 27.838916339999997,
"qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb": 13.73193329,
"qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb": 18.015446706,
"qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb": 16.825568951,
"qa/specs/features/browser_ui/3_create/repository/file/file_with_unusual_name_spec.rb": 18.653128723,
"qa/specs/features/browser_ui/3_create/repository/license_detection_spec.rb": 34.200236963,
"qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb": 92.809953669,
"qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb": 13.716068485,
"qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb": 18.782703595,
"qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb": 17.981496533,
"qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb": 57.522529405,
"qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb": 64.869527379,
"qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb": 49.329504060000005,
"qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb": 23.926958931,
"qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb": 28.909467117,
"qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb": 15.449681658,
"qa/specs/features/browser_ui/3_create/repository/ssh_key_support_create_spec.rb": 12.695665577,
"qa/specs/features/browser_ui/3_create/repository/ssh_key_support_delete_spec.rb": 10.232346615,
"qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb": 32.820143859,
"qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb": 35.417800189000005,
"qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb": 25.607929067,
"qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb": 54.456431945999995,
"qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb": 59.859306526,
"qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb": 36.371432081,
"qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb": 8.641375561,
"qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb": 7.898147717,
"qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb": 17.080507738,
"qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_with_multiple_files_spec.rb": 16.332906831,
"qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb": 24.807498318,
"qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb": 16.989236085,
"qa/specs/features/browser_ui/3_create/snippet/snippet_index_page_spec.rb": 74.169690379,
"qa/specs/features/browser_ui/3_create/source_editor/source_editor_toolbar_spec.rb": 19.622818356,
"qa/specs/features/browser_ui/3_create/web_ide/add_first_file_in_web_ide_spec.rb": 37.910261868,
"qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb": 58.08326704,
"qa/specs/features/browser_ui/3_create/web_ide/closing_web_ide_with_unsaved_changes_spec.rb": 15.572654424,
"qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb": 121.412939857,
"qa/specs/features/browser_ui/4_verify/ci_components_catalog/ci_catalog_sorting_spec.rb": 80.092911794,
"qa/specs/features/browser_ui/4_verify/ci_components_catalog/run_component_in_project_pipeline_spec.rb": 65.015233412,
"qa/specs/features/browser_ui/4_verify/ci_job_artifacts/expose_job_artifacts_in_mr_spec.rb": 111.750492903,
"qa/specs/features/browser_ui/4_verify/ci_job_artifacts/job_artifacts_access_keyword_spec.rb": 239.18360505500002,
"qa/specs/features/browser_ui/4_verify/ci_job_artifacts/unlocking_job_artifacts_across_pipelines_spec.rb": 315.286782107,
"qa/specs/features/browser_ui/4_verify/ci_project_artifacts/user_can_bulk_delete_artifacts_spec.rb": 68.705297635,
"qa/specs/features/browser_ui/4_verify/ci_variable/custom_variable_spec.rb": 46.261082908,
"qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb": 83.497028109,
"qa/specs/features/browser_ui/4_verify/ci_variable/prefill_variables_spec.rb": 51.121617801,
"qa/specs/features/browser_ui/4_verify/ci_variable/raw_variables_defined_in_yaml_spec.rb": 27.536653283,
"qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_inheritable_when_forward_pipeline_variables_true_spec.rb": 143.5733503,
"qa/specs/features/browser_ui/4_verify/pipeline/include_local_config_file_paths_with_wildcard_spec.rb": 24.700889244,
"qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb": 95.166947911,
"qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_multiple_projects_spec.rb": 87.915811476,
"qa/specs/features/browser_ui/4_verify/pipeline/parent_child_pipelines_independent_relationship_spec.rb": 103.671662924,
"qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb": 50.463381996,
"qa/specs/features/browser_ui/4_verify/pipeline/pipeline_with_image_pull_policy_spec.rb": 168.983298436,
"qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_with_manual_jobs_spec.rb": 105.300517443,
"qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb": 56.252273656,
"qa/specs/features/browser_ui/4_verify/pipeline/trigger_matrix_spec.rb": 91.508600203,
"qa/specs/features/browser_ui/4_verify/pipeline/update_ci_file_with_pipeline_editor_spec.rb": 20.47493459,
"qa/specs/features/browser_ui/4_verify/runner/deprecated_registration_token_spec.rb": 20.872091666,
"qa/specs/features/browser_ui/4_verify/runner/fleet_visibility/group_runner_counts_spec.rb": 18.421560934,
"qa/specs/features/browser_ui/4_verify/runner/fleet_visibility/group_runner_status_counts_spec.rb": 11.169042066,
"qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb": 15.074528334,
"qa/specs/features/browser_ui/4_verify/runner/register_project_runner_spec.rb": 17.248016996,
"qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb": 51.115575213,
"qa/specs/features/browser_ui/5_package/container_registry/self_managed/container_registry_spec.rb": 361.477545479,
"qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb": 180.437498017,
"qa/specs/features/browser_ui/5_package/infrastructure_registry/terraform_module_registry_spec.rb": 53.378631253,
"qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb": 52.4162606,
"qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb": 73.935897642,
"qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb": 49.99864988,
"qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb": 243.987039106,
"qa/specs/features/browser_ui/5_package/package_registry/maven/maven_group_level_spec.rb": 542.297174559,
"qa/specs/features/browser_ui/5_package/package_registry/maven/maven_project_level_spec.rb": 177.869213726,
"qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb": 214.762330745,
"qa/specs/features/browser_ui/5_package/package_registry/npm/npm_group_level_spec.rb": 269.216774817,
"qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb": 298.812630805,
"qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb": 76.987724127,
"qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb": 19.926563849,
"qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb": 147.125223634,
"qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb": 9.628861216,
"qa/specs/features/browser_ui/8_monitor/alert_management/alert_settings_create_new_alerts_spec.rb": 28.58485985,
"qa/specs/features/browser_ui/8_monitor/alert_management/automatically_creates_incident_for_alert_spec.rb": 50.86118756,
"qa/specs/features/browser_ui/8_monitor/alert_management/create_alert_using_authorization_key_spec.rb": 25.567636665000002,
"qa/specs/features/browser_ui/8_monitor/alert_management/email_notification_for_alert_spec.rb": 66.62106211400001,
"qa/specs/features/browser_ui/8_monitor/alert_management/recovery_alert_resolves_correct_alert_spec.rb": 16.518447218,
"qa/specs/features/browser_ui/9_data_stores/group/create_group_with_mattermost_team_spec.rb": 5.702188147,
"qa/specs/features/browser_ui/9_data_stores/group/group_member_access_request_spec.rb": 56.911355493,
"qa/specs/features/browser_ui/9_data_stores/group/transfer_project_spec.rb": 27.228011152,
"qa/specs/features/browser_ui/9_data_stores/project/add_project_member_spec.rb": 13.892981501,
"qa/specs/features/browser_ui/9_data_stores/project/create_project_badge_spec.rb": 24.852015491,
"qa/specs/features/browser_ui/9_data_stores/project/create_project_spec.rb": 33.295320868000005,
"qa/specs/features/browser_ui/9_data_stores/project/dashboard_images_spec.rb": 14.122764927999999,
"qa/specs/features/browser_ui/9_data_stores/project/invite_group_to_project_spec.rb": 48.007433758999994,
"qa/specs/features/browser_ui/9_data_stores/project/project_owner_permissions_spec.rb": 58.001095949,
"qa/specs/features/browser_ui/9_data_stores/project/view_project_activity_spec.rb": 24.4958712,
"qa/specs/features/browser_ui/9_data_stores/user/follow_user_activity_spec.rb": 31.56632662,
"qa/specs/features/browser_ui/9_data_stores/user/parent_group_access_termination_spec.rb": 24.417873569,
"qa/specs/features/browser_ui/9_data_stores/user/user_inherited_access_spec.rb": 24.830640784,
"qa/specs/features/ee/api/10_govern/compliance_pipeline_spec.rb": 91.408097916,
"qa/specs/features/ee/api/10_govern/instance_audit_event_streaming_spec.rb": 30.775132579,
"qa/specs/features/ee/api/10_govern/user/minimal_access_user_spec.rb": 55.29301992,
"qa/specs/features/ee/api/1_manage/import/import_github_repo_spec.rb": 22.02101016,
"qa/specs/features/ee/api/1_manage/integrations/group_webhook_events_spec.rb": 11.371798369,
"qa/specs/features/ee/api/1_manage/migration/gitlab_migration_group_spec.rb": 80.830860381,
"qa/specs/features/ee/api/2_plan/epics_milestone_dates_spec.rb": 38.8713823,
"qa/specs/features/ee/api/3_create/code_suggestions_spec.rb": 19.515681835000002,
"qa/specs/features/ee/api/9_data_stores/elasticsearch/advanced_global_advanced_syntax_search_spec.rb": 131.708821695,
"qa/specs/features/ee/api/9_data_stores/elasticsearch/elasticsearch_api_spec.rb": 43.56199013,
"qa/specs/features/ee/api/9_data_stores/elasticsearch/index_tests/commit_index/commit_index_spec.rb": 20.436838562,
"qa/specs/features/ee/api/9_data_stores/elasticsearch/index_tests/issues_index/issue_index_spec.rb": 112.698578671,
"qa/specs/features/ee/api/9_data_stores/elasticsearch/index_tests/main_index/blob_index_spec.rb": 116.95935475,
"qa/specs/features/ee/api/9_data_stores/elasticsearch/index_tests/merge_request_index/merge_request_index_spec.rb": 84.57975007,
"qa/specs/features/ee/api/9_data_stores/elasticsearch/index_tests/notes_index/note_index_spec.rb": 72.037487499,
"qa/specs/features/ee/api/9_data_stores/elasticsearch/index_tests/user_index/user_index_spec.rb": 53.363283083,
"qa/specs/features/ee/api/9_data_stores/elasticsearch/nightly_elasticsearch_test_spec.rb": 21.279578581,
"qa/specs/features/ee/browser_ui/10_govern/change_vulnerability_status_spec.rb": 55.826575224,
"qa/specs/features/ee/browser_ui/10_govern/create_merge_request_with_secure_spec.rb": 87.78720763,
"qa/specs/features/ee/browser_ui/10_govern/dismissed_vulnerabilities_in_security_widget_spec.rb": 84.738124805,
"qa/specs/features/ee/browser_ui/10_govern/export_vulnerability_report_spec.rb": 25.630148318,
"qa/specs/features/ee/browser_ui/10_govern/fix_vulnerability_workflow_spec.rb": 156.142192263,
"qa/specs/features/ee/browser_ui/10_govern/group/group_audit_event_streaming_spec.rb": 62.48558863699999,
"qa/specs/features/ee/browser_ui/10_govern/group/group_audit_logs_1_spec.rb": 119.045828954,
"qa/specs/features/ee/browser_ui/10_govern/group/group_ldap_sync_spec.rb": 110.12435409,
"qa/specs/features/ee/browser_ui/10_govern/group/group_saml_enforced_sso_git_access_spec.rb": 21.054997339,
"qa/specs/features/ee/browser_ui/10_govern/group/group_saml_enforced_sso_new_account_spec.rb": 280.010375185,
"qa/specs/features/ee/browser_ui/10_govern/group/group_saml_non_enforced_sso_spec.rb": 88.080820792,
"qa/specs/features/ee/browser_ui/10_govern/group/restrict_by_ip_address_spec.rb": 130.602395648,
"qa/specs/features/ee/browser_ui/10_govern/group/saml_sso_merge_request_approve_spec.rb": 44.590280443,
"qa/specs/features/ee/browser_ui/10_govern/group_pipeline_execution_policy_spec.rb": 148.46834867299998,
"qa/specs/features/ee/browser_ui/10_govern/instance/instance_audit_logs_spec.rb": 117.932026834,
"qa/specs/features/ee/browser_ui/10_govern/project/project_audit_logs_spec.rb": 160.97976917100002,
"qa/specs/features/ee/browser_ui/10_govern/project_security_dashboard_spec.rb": 30.432568877999998,
"qa/specs/features/ee/browser_ui/10_govern/scan_execution_policy_vulnerabilities_spec.rb": 128.364999131,
"qa/specs/features/ee/browser_ui/10_govern/scan_result_policy_vulnerabilities_spec.rb": 152.033169711,
"qa/specs/features/ee/browser_ui/10_govern/security_policies_spec.rb": 57.192550637000004,
"qa/specs/features/ee/browser_ui/10_govern/security_reports_spec.rb": 319.784820019,
"qa/specs/features/ee/browser_ui/10_govern/user/minimal_access_user_spec.rb": 13.65424631,
"qa/specs/features/ee/browser_ui/10_govern/vulnerabilities_jira_integration_spec.rb": 21.985980373,
"qa/specs/features/ee/browser_ui/10_govern/vulnerability_management_spec.rb": 462.88021039299997,
"qa/specs/features/ee/browser_ui/10_govern/vulnerability_security_training_spec.rb": 112.489452097,
"qa/specs/features/ee/browser_ui/11_fulfillment/license/cloud_activation_spec.rb": 23.033360874,
"qa/specs/features/ee/browser_ui/11_fulfillment/license/license_spec.rb": 9.258090402,
"qa/specs/features/ee/browser_ui/11_fulfillment/utilization/user_registration_billing_spec.rb": 24.320754753,
"qa/specs/features/ee/browser_ui/13_secure/cvs_dependency_scanning_spec.rb": 55.586695068,
"qa/specs/features/ee/browser_ui/13_secure/enable_advanced_sast_spec.rb": 110.533872574,
"qa/specs/features/ee/browser_ui/13_secure/enable_scanning_from_configuration_spec.rb": 56.31243103600001,
"qa/specs/features/ee/browser_ui/13_secure/secret_push_protection_spec.rb": 36.157237672,
"qa/specs/features/ee/browser_ui/16_ai_powered/duo_chat/duo_chat_spec.rb": 16.153048131,
"qa/specs/features/ee/browser_ui/1_manage/integrations/jira_issues_list_spec.rb": 55.609796752,
"qa/specs/features/ee/browser_ui/2_plan/analytics/contribution_analytics_spec.rb": 36.357317959,
"qa/specs/features/ee/browser_ui/2_plan/analytics/mr_analytics_spec.rb": 37.851247768,
"qa/specs/features/ee/browser_ui/2_plan/analytics/value_stream_analytics_spec.rb": 33.441287267,
"qa/specs/features/ee/browser_ui/2_plan/burndown_chart/burndown_chart_spec.rb": 11.900661307,
"qa/specs/features/ee/browser_ui/2_plan/custom_email/custom_email_spec.rb": 12.035863813,
"qa/specs/features/ee/browser_ui/2_plan/epic/epics_management_spec.rb": 134.726780099,
"qa/specs/features/ee/browser_ui/2_plan/epic/promote_issue_to_epic_spec.rb": 25.482259537,
"qa/specs/features/ee/browser_ui/2_plan/epic/roadmap_spec.rb": 7.417660097,
"qa/specs/features/ee/browser_ui/2_plan/group_wiki/create_group_wiki_page_spec.rb": 31.331486092,
"qa/specs/features/ee/browser_ui/2_plan/group_wiki/delete_group_wiki_page_spec.rb": 12.498393654,
"qa/specs/features/ee/browser_ui/2_plan/group_wiki/file_upload_group_wiki_page_spec.rb": 25.792097108,
"qa/specs/features/ee/browser_ui/2_plan/insights/default_insights_spec.rb": 19.703109655,
"qa/specs/features/ee/browser_ui/2_plan/issue/default_issue_template_spec.rb": 27.176826196,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/configurable_issue_board_spec.rb": 12.616640759,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/configure_issue_board_by_label_spec.rb": 16.590467119,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/create_group_issue_board_spec.rb": 15.578085099,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/group_issue_boards_spec.rb": 16.370615114,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/project_issue_boards_spec.rb": 42.011776604000005,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/read_only_board_configuration_spec.rb": 18.027865619,
"qa/specs/features/ee/browser_ui/2_plan/issue_boards/sum_of_issues_weights_spec.rb": 11.210515684,
"qa/specs/features/ee/browser_ui/2_plan/issues_analytics/issues_analytics_spec.rb": 22.155055463,
"qa/specs/features/ee/browser_ui/2_plan/issues_weight/issue_weight_visualization_spec.rb": 26.085860783,
"qa/specs/features/ee/browser_ui/2_plan/iterations/assign_group_iteration_spec.rb": 27.575442404,
"qa/specs/features/ee/browser_ui/2_plan/iterations/create_group_iteration_spec.rb": 36.398105721,
"qa/specs/features/ee/browser_ui/2_plan/multiple_assignees_for_issues/four_assignees_spec.rb": 23.933429908,
"qa/specs/features/ee/browser_ui/2_plan/multiple_assignees_for_issues/more_than_four_assignees_spec.rb": 40.304484486,
"qa/specs/features/ee/browser_ui/2_plan/scoped_labels/editing_scoped_labels_spec.rb": 22.642775015,
"qa/specs/features/ee/browser_ui/3_create/merge_request/add_batch_comments_in_merge_request_spec.rb": 121.174922985,
"qa/specs/features/ee/browser_ui/3_create/merge_request/approval_rules_spec.rb": 95.498518169,
"qa/specs/features/ee/browser_ui/3_create/merge_request/default_merge_request_template_spec.rb": 34.085535716,
"qa/specs/features/ee/browser_ui/3_create/repository/assign_code_owners_spec.rb": 44.669053965,
"qa/specs/features/ee/browser_ui/3_create/repository/code_owners_spec.rb": 20.184605323,
"qa/specs/features/ee/browser_ui/3_create/repository/code_owners_with_protected_branch_and_squashed_commits_spec.rb": 35.641015328,
"qa/specs/features/ee/browser_ui/3_create/repository/file_locking_spec.rb": 205.308072645,
"qa/specs/features/ee/browser_ui/3_create/repository/group_file_template_spec.rb": 117.62582875999999,
"qa/specs/features/ee/browser_ui/3_create/repository/merge_with_code_owner_in_root_group_spec.rb": 140.61099606099998,
"qa/specs/features/ee/browser_ui/3_create/repository/merge_with_code_owner_in_subgroup_spec.rb": 218.719419923,
"qa/specs/features/ee/browser_ui/3_create/repository/project_templates_spec.rb": 79.96896029,
"qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_http_spec.rb": 29.625310171,
"qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_ssh_with_key_spec.rb": 36.525266247,
"qa/specs/features/ee/browser_ui/3_create/repository/push_rules_spec.rb": 324.35804462299996,
"qa/specs/features/ee/browser_ui/3_create/repository/restrict_push_protected_branch_spec.rb": 244.19500338999998,
"qa/specs/features/ee/browser_ui/3_create/web_ide/code_suggestions_in_web_ide_spec.rb": 97.382263936,
"qa/specs/features/ee/browser_ui/4_verify/multi-project_pipelines_spec.rb": 52.02810459,
"qa/specs/features/ee/browser_ui/4_verify/parent_child_pipelines_dependent_relationship_spec.rb": 139.42840636,
"qa/specs/features/ee/browser_ui/4_verify/pipeline_for_merged_result_spec.rb": 77.313383259,
"qa/specs/features/ee/browser_ui/4_verify/pipeline_subscription_with_group_owned_project_spec.rb": 36.514295309,
"qa/specs/features/ee/browser_ui/5_package/dependency_proxy_sso_spec.rb": 79.639476149,
"qa/specs/features/ee/browser_ui/8_monitor/incident_management/incident_quick_action_spec.rb": 13.79298522,
"qa/specs/features/ee/browser_ui/9_data_stores/elasticsearch/elasticsearch_reindexing_spec.rb": 156.446744321,
"qa/specs/features/ee/browser_ui/9_data_stores/group/prevent_forking_outside_group_spec.rb": 49.674002396999995,
"qa/specs/features/ee/browser_ui/9_data_stores/group/share_group_with_group_spec.rb": 22.494904961
}

View File

@ -103,6 +103,18 @@ RSpec.describe Projects::DeployKeysController, feature_category: :continuous_del
expect(json_response['keys'].pluck("id")).to match_array([deploy_key_public.id])
end
end
describe 'GET available_public_keys with search' do
let_it_be(:another_deploy_key_public) { create(:deploy_key, public: true, title: 'new-key') }
let(:params) do
{ namespace_id: project.namespace, project_id: project, search: 'key', in: 'title' }
end
it 'returns available public keys matching the search' do
get :available_public_keys, params: params.merge(format: :json)
expect(json_response['keys'].pluck("id")).to match_array([another_deploy_key_public.id])
end
end
end
describe 'POST create' do

View File

@ -449,6 +449,7 @@ RSpec.describe 'Database schema',
"Organizations::OrganizationSetting" => %w[settings], # Custom validations
"Packages::Composer::Metadatum" => %w[composer_json],
"RawUsageData" => %w[payload], # Usage data payload changes often, we cannot use one schema
"ServicePing::NonSqlServicePing" => %w[payload], # Usage data payload changes often, we cannot use one schema
"Releases::Evidence" => %w[summary],
"Vulnerabilities::Finding::Evidence" => %w[data], # Validation work in progress
"Ai::DuoWorkflows::Checkpoint" => %w[checkpoint metadata], # https://gitlab.com/gitlab-org/gitlab/-/issues/468632

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
FactoryBot.define do
factory :non_sql_service_ping, class: 'ServicePing::NonSqlServicePing' do
recorded_at { Time.current }
payload { { test: 'test' } }
association :organization, factory: :organization
end
end

View File

@ -13,6 +13,7 @@ RSpec.describe "User interacts with deploy keys", :js, feature_category: :contin
shared_examples 'attaches a key' do
it 'attaches key' do
visit(project_deploy_keys_path(project))
wait_for_requests
page.within('.deploy-keys') do
click_link(scope)
@ -23,6 +24,7 @@ RSpec.describe "User interacts with deploy keys", :js, feature_category: :contin
expect(page).to have_current_path(project_settings_repository_path(project), ignore_query: true)
click_link('Enabled deploy keys')
wait_for_requests
expect(page).to have_content(deploy_key.title)
end
@ -39,6 +41,7 @@ RSpec.describe "User interacts with deploy keys", :js, feature_category: :contin
it 'shows deploy keys' do
visit(project_deploy_keys_path(project))
wait_for_requests
page.within('.deploy-keys') do
expect(page).to have_content(deploy_key.title)
@ -54,6 +57,7 @@ RSpec.describe "User interacts with deploy keys", :js, feature_category: :contin
it 'shows pagination' do
visit(project_deploy_keys_path(project))
wait_for_requests
page.within('.deploy-keys') do
expect(page).to have_link('Next')
@ -73,6 +77,7 @@ RSpec.describe "User interacts with deploy keys", :js, feature_category: :contin
it 'shows deploy keys' do
visit(project_deploy_keys_path(project))
wait_for_requests
page.within('.deploy-keys') do
click_link('Privately accessible deploy keys')
@ -87,6 +92,7 @@ RSpec.describe "User interacts with deploy keys", :js, feature_category: :contin
it 'shows public deploy keys' do
visit(project_deploy_keys_path(project))
wait_for_requests
page.within('.deploy-keys') do
click_link('Publicly accessible deploy keys')
@ -100,6 +106,7 @@ RSpec.describe "User interacts with deploy keys", :js, feature_category: :contin
context 'adding deploy keys' do
before do
visit(project_deploy_keys_path(project))
wait_for_requests
end
it 'adds new key' do

View File

@ -62,6 +62,15 @@ RSpec.describe DeployKeys::DeployKeysFinder, feature_category: :continuous_deliv
end
end
context 'when has search' do
let_it_be(:another_deploy_key_public) { create(:deploy_key, public: true, title: 'new-key') }
let(:params) { { filter: :available_public_keys, search: 'key', in: 'title' } }
it 'returns the correct result' do
expect(result.map(&:id)).to match_array([another_deploy_key_public.id])
end
end
context 'when there are no set filters' do
it 'returns an empty collection' do
expect(result).to eq DeployKey.none

View File

@ -2,7 +2,7 @@ import VueApollo from 'vue-apollo';
import Vue, { nextTick } from 'vue';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { GlPagination } from '@gitlab/ui';
import { GlPagination, GlFilteredSearch } from '@gitlab/ui';
import enabledKeys from 'test_fixtures/deploy_keys/enabled_keys.json';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@ -12,6 +12,7 @@ import deployKeysQuery from '~/deploy_keys/graphql/queries/deploy_keys.query.gra
import deployKeysApp from '~/deploy_keys/components/app.vue';
import ConfirmModal from '~/deploy_keys/components/confirm_modal.vue';
import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
import KeysPanel from '~/deploy_keys/components/keys_panel.vue';
import axios from '~/lib/utils/axios_utils';
jest.mock('~/sentry/sentry_browser_wrapper');
@ -79,6 +80,8 @@ describe('Deploy keys app component', () => {
const findKeyPanels = () => wrapper.findAll('.deploy-keys .gl-tabs-nav li');
const findModal = () => wrapper.findComponent(ConfirmModal);
const findNavigationTabs = () => wrapper.findComponent(NavigationTabs);
const findFilteredSearch = () => wrapper.findComponent(GlFilteredSearch);
const findKeysPanel = () => wrapper.findComponent(KeysPanel);
it('renders loading icon while waiting for request', async () => {
currentScopeMock.mockResolvedValue('enabledKeys');
@ -280,4 +283,74 @@ describe('Deploy keys app component', () => {
);
});
});
describe('search functionality', () => {
beforeEach(async () => {
const deployKeys = enabledKeys.keys.map(mapDeployKey);
deployKeyMock.mockReturnValue({
data: {
project: { id: 1, deployKeys, __typename: 'Project' },
},
});
currentScopeMock.mockResolvedValue('enabledKeys');
currentPageMock.mockResolvedValue(1);
await mountComponent();
});
it('provides two token options by default', () => {
expect(findFilteredSearch().props('availableTokens')).toHaveLength(2);
expect(findFilteredSearch().props('availableTokens')[0].type).toBe('title');
expect(findFilteredSearch().props('availableTokens')[1].type).toBe('key');
});
it('updates available tokens to the type of search', async () => {
await findFilteredSearch().vm.$emit('input', [{ type: 'title', value: { data: 'test' } }]);
expect(findFilteredSearch().props('availableTokens')).toHaveLength(1);
expect(findFilteredSearch().props('availableTokens')[0].type).toBe('title');
});
it('removes available tokens on raw text type', async () => {
await findFilteredSearch().vm.$emit('input', [
{ id: 'token-28', type: 'filtered-search-term', value: { data: 'test' } },
]);
expect(findFilteredSearch().props('availableTokens')).toHaveLength(0);
});
it('handles search submission', async () => {
expect(deployKeyMock).toHaveBeenCalledTimes(1);
await findFilteredSearch().vm.$emit('submit', [{ type: 'key', value: { data: 'test' } }]);
expect(deployKeyMock).toHaveBeenCalledTimes(2);
expect(deployKeyMock).toHaveBeenNthCalledWith(2, {
page: 1,
projectPath: 'test/project',
scope: 'enabledKeys',
search: { in: 'key', search: 'test' },
});
});
it('renders as view-only when the query is loading', async () => {
await findFilteredSearch().vm.$emit('submit', [{ type: 'key', value: { data: 'test' } }]);
expect(findFilteredSearch().props('viewOnly')).toBe(true);
await waitForPromises();
expect(findFilteredSearch().props('viewOnly')).toBe(false);
});
it('clears search value when tab changes', async () => {
await findFilteredSearch().vm.$emit('submit', [{ type: 'title', value: { data: 'test' } }]);
await findNavigationTabs().vm.$emit('onChangeTab', 'enabled');
expect(findFilteredSearch().props('value')).toEqual([
{ id: expect.anything(), type: 'filtered-search-term', value: { data: '' } },
]);
});
it('passes hasSearch prop to KeysPanel', async () => {
await findFilteredSearch().vm.$emit('submit', [{ type: 'title', value: { data: 'test' } }]);
await waitForPromises();
expect(findKeysPanel().props('hasSearch')).toBe(true);
});
});
});

View File

@ -45,6 +45,12 @@ describe('Deploy keys panel', () => {
expect(findEmptyState().text()).toBe('No deploy keys found, start by adding a new one above.');
});
it('renders help box with empty search text if keys are empty on search', () => {
mountComponent({ keys: [], hasSearch: true });
expect(findEmptyState().exists()).toBe(true);
expect(findEmptyState().text()).toBe('No search results found.');
});
it('renders no table header if keys are empty', () => {
mountComponent({ keys: [] });
expect(findTableRowHeader().exists()).toBe(false);

View File

@ -74,6 +74,26 @@ describe('~/deploy_keys/graphql/resolvers', () => {
]);
});
it('should request the given search', async () => {
const scope = 'enabledKeys';
const search = { search: 'my-key', in: 'title' };
const page = 1;
mock
.onGet(ENDPOINTS.enabledKeysEndpoint, { params: { ...search, page, per_page: 5 } })
.reply(HTTP_STATUS_OK, { keys: [key] });
const keys = await mockResolvers.Project.deployKeys(
null,
{ scope, page, search },
{ client },
);
expect(keys).toEqual([
{ id: 1, title: 'hello', editPath: '/edit', __typename: 'LocalDeployKey' },
]);
});
it('should write pagination info to the cache', async () => {
const scope = 'enabledKeys';
const page = 1;

View File

@ -55,7 +55,12 @@ const firstSystemNodeId = mockNotesWidgetResponse.discussions.nodes[0].notes.nod
const mockDiscussions = mockWorkItemNotesWidgetResponseWithComments.discussions.nodes;
const mockWorkItemNoteResponse = {
data: { note: mockDiscussions[0].notes.nodes[0] },
data: {
note: {
id: mockDiscussions[0].notes.nodes[0].id,
discussion: { id: mockDiscussions[0].id, notes: mockDiscussions[0].notes },
},
},
};
describe('WorkItemNotes component', () => {
@ -190,9 +195,9 @@ describe('WorkItemNotes component', () => {
await waitForPromises();
expect(findWorkItemCommentNoteAtIndex(0).props('discussion')).toEqual([
mockWorkItemNoteResponse.data.note,
]);
expect(findWorkItemCommentNoteAtIndex(0).props('discussion')).toEqual(
mockWorkItemNoteResponse.data.note.discussion.notes.nodes,
);
});
});

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe DeployKey, :mailer do
RSpec.describe DeployKey, :mailer, feature_category: :continuous_delivery do
describe "Associations" do
it { is_expected.to have_many(:deploy_keys_projects) }
@ -171,4 +171,57 @@ RSpec.describe DeployKey, :mailer do
expect(subject.audit_details).to eq(subject.title)
end
end
describe 'search' do
let!(:deploy_key1) { create(:deploy_key, title: 'Production key') }
let!(:deploy_key2) { create(:deploy_key, title: 'Staging key') }
let!(:deploy_key3) { create(:deploy_key, title: 'Development key') }
describe '.search_by_title' do
it 'returns deploy keys with matching titles' do
expect(described_class.search_by_title('production')).to contain_exactly(deploy_key1)
expect(described_class.search_by_title('key')).to contain_exactly(deploy_key1, deploy_key2, deploy_key3)
end
it 'is case-insensitive' do
expect(described_class.search_by_title('PRODUCTION')).to contain_exactly(deploy_key1)
end
end
describe '.search_by_key' do
it 'returns deploy keys with matching sha' do
key = deploy_key1.fingerprint_sha256
expect(described_class.search_by_key(key)).to contain_exactly(deploy_key1)
end
end
describe '.search' do
context 'when searching by title' do
it 'returns deploy keys with matching titles' do
expect(described_class.search('production', 'title')).to contain_exactly(deploy_key1)
end
end
context 'when searching by key' do
it 'returns deploy keys with matching sha' do
key = deploy_key2.fingerprint_sha256
expect(described_class.search(key, 'key')).to contain_exactly(deploy_key2)
end
end
context 'when searching without specifying a field' do
it 'returns deploy keys matching either title or sha' do
key = deploy_key3.fingerprint_sha256
expect(described_class.search('Development')).to contain_exactly(deploy_key3)
expect(described_class.search(key)).to contain_exactly(deploy_key3)
end
end
context 'when search term is blank' do
it 'returns all deploy keys' do
expect(described_class.search('')).to contain_exactly(deploy_key1, deploy_key2, deploy_key3)
end
end
end
end
end

View File

@ -0,0 +1,45 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ServicePing::NonSqlServicePing, feature_category: :service_ping do
before_all do
create(:organization, :default)
end
describe 'scopes' do
describe '.for_current_reporting_cycle' do
subject(:recent_service_ping_reports) { described_class.for_current_reporting_cycle }
before_all do
create(:non_sql_service_ping, created_at: (described_class::REPORTING_CADENCE + 1.day).ago)
end
it 'returns nil where no records match filter criteria' do
expect(recent_service_ping_reports).to be_empty
end
context 'with records matching filtering criteria' do
let_it_be(:fresh_record) { create(:non_sql_service_ping) }
let_it_be(:record_at_edge_of_time_range) do
create(:non_sql_service_ping, created_at: described_class::REPORTING_CADENCE.ago)
end
it 'return records within reporting cycle time range ordered by creation time' do
expect(recent_service_ping_reports).to eq [fresh_record, record_at_edge_of_time_range]
end
end
end
end
describe 'validations' do
it { is_expected.to validate_presence_of(:payload) }
it { is_expected.to validate_presence_of(:recorded_at) }
describe 'uniqueness validation' do
let!(:existing_record) { create(:non_sql_service_ping) }
it { is_expected.to validate_uniqueness_of(:recorded_at) }
end
end
end

View File

@ -25,11 +25,28 @@ RSpec.describe API::UsageDataNonSqlMetrics, :aggregate_failures, feature_categor
let(:path) { endpoint }
end
it 'returns non sql metrics if user is admin' do
get api(endpoint, admin, admin_mode: true)
context "when user is admin" do
context "with an available NonSqlServicePing entry" do
it 'returns non sql metrics' do
create :non_sql_service_ping, payload: { counts: { abc: 12 } }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['counts']).to be_a(Hash)
get api(endpoint, admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['counts']).to be_a(Hash)
end
end
context "with no recent NonSqlServicePing entry" do
it 'returns default response' do
create :non_sql_service_ping, payload: { counts: { abc: 12 } }, created_at: 2.weeks.ago
get api(endpoint, admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to eq({})
end
end
end
it 'returns forbidden if user is not admin' do

View File

@ -4,12 +4,15 @@ require 'spec_helper'
RSpec.describe GitlabServicePingWorker, :clean_gitlab_redis_shared_state, feature_category: :service_ping do
let(:payload) { { recorded_at: Time.current.rfc3339 } }
let(:non_sql_payload) { { recorded_at: Time.current.rfc3339, count: 123 } }
before do
allow_next_instance_of(ServicePing::SubmitService) { |service| allow(service).to receive(:execute) }
allow_next_instance_of(ServicePing::BuildPayload) do |service|
allow(service).to receive(:execute).and_return(payload)
end
allow(Gitlab::Usage::ServicePingReport).to receive(:for)
.with(output: :non_sql_metrics_values).and_return(non_sql_payload)
allow(subject).to receive(:sleep)
create(:organization)
@ -36,27 +39,58 @@ RSpec.describe GitlabServicePingWorker, :clean_gitlab_redis_shared_state, featur
end
context 'payload computation' do
it 'creates RawUsageData entry when there is NO entry with the same recorded_at timestamp' do
expect { subject.perform }.to change { RawUsageData.count }.by(1)
end
it 'updates RawUsageData entry when there is entry with the same recorded_at timestamp' do
record = create(:raw_usage_data, payload: { some_metric: 123 }, recorded_at: payload[:recorded_at])
expect { subject.perform }.to change { record.reload.payload }
.from("some_metric" => 123).to(payload.stringify_keys)
end
it 'reports errors and continue on execution' do
error = StandardError.new('some error')
allow(::ServicePing::BuildPayload).to receive(:new).and_raise(error)
expect(::Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(error)
expect_next_instance_of(::ServicePing::SubmitService, payload: nil) do |service|
expect(service).to receive(:execute)
describe "RawUsageData creation" do
it 'creates RawUsageData entry when there is NO entry with the same recorded_at timestamp' do
expect { subject.perform }.to change { RawUsageData.count }.by(1)
end
subject.perform
it 'updates RawUsageData entry when there is entry with the same recorded_at timestamp' do
record = create(:raw_usage_data, payload: { some_metric: 123 }, recorded_at: payload[:recorded_at])
expect { subject.perform }.to change { record.reload.payload }
.from("some_metric" => 123).to(payload.stringify_keys)
end
it 'reports errors and continue on execution' do
error = StandardError.new('some error')
allow(::ServicePing::BuildPayload).to receive(:new).and_raise(error)
expect(::Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(error)
expect_next_instance_of(::ServicePing::SubmitService, payload: nil) do |service|
expect(service).to receive(:execute)
end
subject.perform
end
end
describe "NonSqlServicePing creation" do
it 'creates NonSqlServicePing entry when there is NO entry with the same recorded_at timestamp' do
expect { subject.perform }.to change { ServicePing::NonSqlServicePing.count }.by(1)
end
it 'updates NonSqlServicePing entry when there is entry with the same recorded_at timestamp' do
record = create(
:non_sql_service_ping,
payload: { some_metric: 123 },
recorded_at: non_sql_payload[:recorded_at]
)
expect { subject.perform }.to change { record.reload.payload }
.from("some_metric" => 123).to(non_sql_payload.stringify_keys)
end
it 'reports errors and continue on execution' do
error = StandardError.new('some error')
allow(::Gitlab::Usage::ServicePingReport).to receive(:for).and_raise(error)
expect(::Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(error)
expect_next_instance_of(::ServicePing::SubmitService, payload: payload) do |service|
expect(service).to receive(:execute)
end
subject.perform
end
end
end
@ -66,6 +100,11 @@ RSpec.describe GitlabServicePingWorker, :clean_gitlab_redis_shared_state, featur
.with(described_class::LEASE_KEY, hash_including(timeout: described_class::LEASE_TIMEOUT))
.and_call_original
expect(Gitlab::ExclusiveLeaseHelpers::SleepingLock)
.to receive(:new)
.with(described_class::NON_SQL_LEASE_KEY, hash_including(timeout: described_class::LEASE_TIMEOUT))
.and_call_original
subject.perform
end