Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
b837b7fc8d
commit
8fe70401f0
|
|
@ -369,7 +369,7 @@ jest vue3 mr:
|
|||
parallel: 6
|
||||
script:
|
||||
- run_timed_command "yarn jest:ci:vue3-mr:without-fixtures"
|
||||
allow_failure: true
|
||||
allow_failure: false
|
||||
|
||||
jest-with-fixtures vue3 mr:
|
||||
extends:
|
||||
|
|
@ -420,7 +420,6 @@ jest vue3 predictive:
|
|||
- "detect-tests"
|
||||
script:
|
||||
- if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then run_timed_command "yarn jest:ci:vue3-mr:predictive-without-fixtures"; fi
|
||||
allow_failure: false
|
||||
|
||||
jest-with-fixtures vue3 predictive:
|
||||
extends:
|
||||
|
|
|
|||
|
|
@ -354,6 +354,7 @@ export default {
|
|||
hasBlockedIssuesFeature: this.hasBlockedIssuesFeature,
|
||||
hasIssuableHealthStatusFeature: this.hasIssuableHealthStatusFeature,
|
||||
hasIssueWeightsFeature: this.hasIssueWeightsFeature,
|
||||
hasManualSort: false,
|
||||
});
|
||||
},
|
||||
tabCounts() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { GlFormRadio } from '@gitlab/ui';
|
||||
import { dateInWords, newDate } from '~/lib/utils/datetime_utility';
|
||||
import { localeDateFormat, newDate } from '~/lib/utils/datetime_utility';
|
||||
import { __ } from '~/locale';
|
||||
import { dateFields } from '../../constants';
|
||||
import SidebarFormattedDate from './sidebar_formatted_date.vue';
|
||||
|
|
@ -45,7 +45,7 @@ export default {
|
|||
return this.$options.i18n.noDate;
|
||||
}
|
||||
|
||||
return dateInWords(newDate(dateFixed), true);
|
||||
return localeDateFormat.asDate.format(newDate(dateFixed));
|
||||
},
|
||||
formattedInheritedDate() {
|
||||
const dateFromMilestones = this.issuable[dateFields[this.dateType].dateFromMilestones];
|
||||
|
|
@ -53,7 +53,7 @@ export default {
|
|||
return this.$options.i18n.noDate;
|
||||
}
|
||||
|
||||
return dateInWords(newDate(dateFromMilestones), true);
|
||||
return localeDateFormat.asDate.format(newDate(dateFromMilestones));
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import {
|
|||
TODO_ACTION_TYPE_REVIEW_SUBMITTED,
|
||||
TODO_ACTION_TYPE_UNMERGEABLE,
|
||||
TODO_ACTION_TYPE_SSH_KEY_EXPIRED,
|
||||
TODO_ACTION_TYPE_SSH_KEY_EXPIRING_SOON,
|
||||
} from '../constants';
|
||||
|
||||
export default {
|
||||
|
|
@ -51,7 +52,8 @@ export default {
|
|||
this.todo.action !== TODO_ACTION_TYPE_BUILD_FAILED &&
|
||||
this.todo.action !== TODO_ACTION_TYPE_MERGE_TRAIN_REMOVED &&
|
||||
this.todo.action !== TODO_ACTION_TYPE_UNMERGEABLE &&
|
||||
this.todo.action !== TODO_ACTION_TYPE_SSH_KEY_EXPIRED
|
||||
this.todo.action !== TODO_ACTION_TYPE_SSH_KEY_EXPIRED &&
|
||||
this.todo.action !== TODO_ACTION_TYPE_SSH_KEY_EXPIRING_SOON
|
||||
);
|
||||
},
|
||||
userIsAuthor() {
|
||||
|
|
@ -133,6 +135,10 @@ export default {
|
|||
name = s__('Todos|Your SSH key has expired');
|
||||
}
|
||||
|
||||
if (this.todo.action === TODO_ACTION_TYPE_SSH_KEY_EXPIRING_SOON) {
|
||||
name = s__('Todos|Your SSH key is expiring soon');
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
Sentry.captureException(
|
||||
new Error(`Encountered unknown TODO_ACTION_TYPE ${this.todo.action}`),
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import {
|
|||
TODO_ACTION_TYPE_OKR_CHECKIN_REQUESTED,
|
||||
TODO_ACTION_TYPE_ADDED_APPROVER,
|
||||
TODO_ACTION_TYPE_SSH_KEY_EXPIRED,
|
||||
TODO_ACTION_TYPE_SSH_KEY_EXPIRING_SOON,
|
||||
} from '../constants';
|
||||
import GroupToken from './filtered_search_tokens/group_token.vue';
|
||||
import ProjectToken from './filtered_search_tokens/project_token.vue';
|
||||
|
|
@ -174,6 +175,11 @@ export const ACTION_TYPES = [
|
|||
value: TODO_ACTION_TYPE_SSH_KEY_EXPIRED,
|
||||
title: s__('Todos|SSH key expired'),
|
||||
},
|
||||
{
|
||||
id: '15',
|
||||
value: TODO_ACTION_TYPE_SSH_KEY_EXPIRING_SOON,
|
||||
title: s__('Todos|SSH key expiring soon'),
|
||||
},
|
||||
];
|
||||
|
||||
const DEFAULT_TOKEN_OPTIONS = {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ export const TODO_ACTION_TYPE_REVIEW_SUBMITTED = 'review_submitted';
|
|||
export const TODO_ACTION_TYPE_OKR_CHECKIN_REQUESTED = 'okr_checkin_requested';
|
||||
export const TODO_ACTION_TYPE_ADDED_APPROVER = 'added_approver';
|
||||
export const TODO_ACTION_TYPE_SSH_KEY_EXPIRED = 'ssh_key_expired';
|
||||
export const TODO_ACTION_TYPE_SSH_KEY_EXPIRING_SOON = 'ssh_key_expiring_soon';
|
||||
|
||||
export const TODO_EMPTY_TITLE_POOL = [
|
||||
s__("Todos|Good job! Looks like you don't have anything left on your To-Do List"),
|
||||
|
|
|
|||
|
|
@ -16,5 +16,6 @@ module Types
|
|||
value 'okr_checkin_requested', value: 12, description: 'An OKR assigned to the user requires an update.'
|
||||
value 'added_approver', value: 13, description: 'User was added as an approver.'
|
||||
value 'ssh_key_expired', value: 14, description: 'SSH key of the user has expired.'
|
||||
value 'ssh_key_expiring_soon', value: 15, description: 'SSH key of the user will expire soon.'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ module TodosHelper
|
|||
s_("Todos|requested an OKR update for %{what}"), what: todo.target.title
|
||||
)
|
||||
when Todo::SSH_KEY_EXPIRED then s_('Todos|Your SSH key has expired')
|
||||
when Todo::SSH_KEY_EXPIRING_SOON then s_('Todos|Your SSH key is expiring soon')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -205,7 +206,8 @@ module TodosHelper
|
|||
{ id: Todo::MARKED, text: s_('Todos|Added') },
|
||||
{ id: Todo::BUILD_FAILED, text: s_('Todos|Pipelines') },
|
||||
{ id: Todo::MEMBER_ACCESS_REQUESTED, text: s_('Todos|Member access requested') },
|
||||
{ id: Todo::SSH_KEY_EXPIRED, text: s_('Todos|SSH key expired') }
|
||||
{ id: Todo::SSH_KEY_EXPIRED, text: s_('Todos|SSH key expired') },
|
||||
{ id: Todo::SSH_KEY_EXPIRING_SOON, text: s_('Todos|SSH key expiring soon') }
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ class Todo < ApplicationRecord
|
|||
OKR_CHECKIN_REQUESTED = 12 # This is an EE-only feature
|
||||
ADDED_APPROVER = 13 # This is an EE-only feature,
|
||||
SSH_KEY_EXPIRED = 14
|
||||
SSH_KEY_EXPIRING_SOON = 15
|
||||
|
||||
ACTION_NAMES = {
|
||||
ASSIGNED => :assigned,
|
||||
|
|
@ -40,7 +41,8 @@ class Todo < ApplicationRecord
|
|||
REVIEW_SUBMITTED => :review_submitted,
|
||||
OKR_CHECKIN_REQUESTED => :okr_checkin_requested,
|
||||
ADDED_APPROVER => :added_approver,
|
||||
SSH_KEY_EXPIRED => :ssh_key_expired
|
||||
SSH_KEY_EXPIRED => :ssh_key_expired,
|
||||
SSH_KEY_EXPIRING_SOON => :ssh_key_expiring_soon
|
||||
}.freeze
|
||||
|
||||
ACTIONS_MULTIPLE_ALLOWED = [Todo::MENTIONED, Todo::DIRECTLY_ADDRESSED, Todo::MEMBER_ACCESS_REQUESTED].freeze
|
||||
|
|
@ -128,6 +130,15 @@ class Todo < ApplicationRecord
|
|||
], remove_duplicates: false)
|
||||
end
|
||||
|
||||
def pending_for_expiring_ssh_keys(ssh_key_ids)
|
||||
where(
|
||||
target_type: Key,
|
||||
target_id: ssh_key_ids,
|
||||
action: ::Todo::SSH_KEY_EXPIRING_SOON,
|
||||
state: :pending
|
||||
)
|
||||
end
|
||||
|
||||
# Returns `true` if the current user has any todos for the given target with the optional given state.
|
||||
#
|
||||
# target - The value of the `target_type` column, such as `Issue`.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ module Keys
|
|||
return unless allowed?
|
||||
|
||||
if expiring_soon
|
||||
create_expiring_soon_todos if Feature.enabled?(:todos_for_ssh_key_expiry, user)
|
||||
trigger_expiring_soon_notification
|
||||
else
|
||||
create_expired_todos if Feature.enabled?(:todos_for_ssh_key_expiry, user)
|
||||
|
|
@ -40,6 +41,10 @@ module Keys
|
|||
keys.update_all(expiry_notification_delivered_at: Time.current.utc)
|
||||
end
|
||||
|
||||
def create_expiring_soon_todos
|
||||
todo_service.ssh_key_expiring_soon(keys)
|
||||
end
|
||||
|
||||
def create_expired_todos
|
||||
todo_service.ssh_key_expired(keys)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -164,23 +164,27 @@ class TodoService
|
|||
resolve_todos_for_target(awardable, current_user)
|
||||
end
|
||||
|
||||
# When a SSH key is expiring soon we should:
|
||||
#
|
||||
# * create a todo for the user owning that SSH key
|
||||
#
|
||||
def ssh_key_expiring_soon(ssh_keys)
|
||||
create_ssh_key_todos(Array(ssh_keys), ::Todo::SSH_KEY_EXPIRING_SOON)
|
||||
end
|
||||
|
||||
# When a SSH key expired we should:
|
||||
#
|
||||
# * resolve any corresponding "expiring soon" todo
|
||||
# * create a todo for the user owning that SSH key
|
||||
#
|
||||
def ssh_key_expired(ssh_keys)
|
||||
ssh_keys = Array(ssh_keys)
|
||||
|
||||
ssh_keys.each do |ssh_key|
|
||||
user = ssh_key.user
|
||||
attributes = {
|
||||
target_id: ssh_key.id,
|
||||
target_type: Key,
|
||||
action: ::Todo::SSH_KEY_EXPIRED,
|
||||
author_id: user.id
|
||||
}
|
||||
create_todos(user, attributes, nil, nil)
|
||||
end
|
||||
# Resolve any pending "expiring soon" todos for these keys
|
||||
expiring_key_todos = ::Todo.pending_for_expiring_ssh_keys(ssh_keys.map(&:id))
|
||||
expiring_key_todos.batch_update(state: :done, resolved_by_action: :system_done)
|
||||
|
||||
create_ssh_key_todos(ssh_keys, ::Todo::SSH_KEY_EXPIRED)
|
||||
end
|
||||
|
||||
# When user marks a target as todo
|
||||
|
|
@ -406,6 +410,19 @@ class TodoService
|
|||
create_todos(todo_author, attributes, project.namespace, project)
|
||||
end
|
||||
|
||||
def create_ssh_key_todos(ssh_keys, action)
|
||||
ssh_keys.each do |ssh_key|
|
||||
user = ssh_key.user
|
||||
attributes = {
|
||||
target_id: ssh_key.id,
|
||||
target_type: Key,
|
||||
action: action,
|
||||
author_id: user.id
|
||||
}
|
||||
create_todos(user, attributes, nil, nil)
|
||||
end
|
||||
end
|
||||
|
||||
def attributes_for_target(target)
|
||||
attributes = {
|
||||
project_id: target&.project&.id,
|
||||
|
|
|
|||
|
|
@ -10,11 +10,12 @@ module Ci
|
|||
deduplicate :until_executed
|
||||
urgency :high
|
||||
|
||||
def perform(pipeline_id)
|
||||
Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
|
||||
Ci::PipelineCreation::CancelRedundantPipelinesService
|
||||
.new(pipeline)
|
||||
.execute
|
||||
def perform(pipeline_id, options = {})
|
||||
relation = Ci::Pipeline.all
|
||||
relation = relation.in_partition(options['partition_id']) if options['partition_id'].present?
|
||||
|
||||
relation.find_by_id(pipeline_id).try do |pipeline|
|
||||
Ci::PipelineCreation::CancelRedundantPipelinesService.new(pipeline).execute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/156691
|
|||
rollout_issue_url:
|
||||
milestone: '17.1'
|
||||
group: group::product planning
|
||||
type: wip
|
||||
default_enabled: false
|
||||
type: beta
|
||||
default_enabled: true
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
migration_job_name: BackfillDependencyProxyBlobStatesGroupId
|
||||
description: Backfills sharding key `dependency_proxy_blob_states.group_id` from `dependency_proxy_blobs`.
|
||||
feature_category: geo_replication
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169237
|
||||
milestone: '17.6'
|
||||
queued_migration_version: 20241015075957
|
||||
finalized_by: # version of the migration that finalized this BBM
|
||||
|
|
@ -19,3 +19,4 @@ desired_sharding_key:
|
|||
table: dependency_proxy_blobs
|
||||
sharding_key: group_id
|
||||
belongs_to: dependency_proxy_blob
|
||||
desired_sharding_key_migration_job_name: BackfillDependencyProxyBlobStatesGroupId
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddGroupIdToDependencyProxyBlobStates < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.6'
|
||||
|
||||
def change
|
||||
add_column :dependency_proxy_blob_states, :group_id, :bigint
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class BackfillNullProjectOnCiStagesRecords < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.6'
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_ci
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
stages_model = define_batchable_model('p_ci_stages', primary_key: :id)
|
||||
|
||||
loop do
|
||||
batch = stages_model.where(project_id: nil).limit(100).to_a
|
||||
break if batch.empty?
|
||||
|
||||
stages_model
|
||||
.where(id: batch.pluck(:id))
|
||||
.where('p_ci_stages.pipeline_id = p_ci_pipelines.id')
|
||||
.where('p_ci_stages.partition_id = p_ci_pipelines.partition_id')
|
||||
.update_all('project_id = p_ci_pipelines.project_id FROM p_ci_pipelines')
|
||||
|
||||
stages_model
|
||||
.where(id: batch.pluck(:id))
|
||||
.where(project_id: nil)
|
||||
.delete_all
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
# Not reversable
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class IndexDependencyProxyBlobStatesOnGroupId < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.6'
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'index_dependency_proxy_blob_states_on_group_id'
|
||||
|
||||
def up
|
||||
add_concurrent_index :dependency_proxy_blob_states, :group_id, name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :dependency_proxy_blob_states, INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddDependencyProxyBlobStatesGroupIdFk < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.6'
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_foreign_key :dependency_proxy_blob_states, :namespaces, column: :group_id, on_delete: :cascade
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key :dependency_proxy_blob_states, column: :group_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddDependencyProxyBlobStatesGroupIdTrigger < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.6'
|
||||
|
||||
def up
|
||||
install_sharding_key_assignment_trigger(
|
||||
table: :dependency_proxy_blob_states,
|
||||
sharding_key: :group_id,
|
||||
parent_table: :dependency_proxy_blobs,
|
||||
parent_sharding_key: :group_id,
|
||||
foreign_key: :dependency_proxy_blob_id
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
remove_sharding_key_assignment_trigger(
|
||||
table: :dependency_proxy_blob_states,
|
||||
sharding_key: :group_id,
|
||||
parent_table: :dependency_proxy_blobs,
|
||||
parent_sharding_key: :group_id,
|
||||
foreign_key: :dependency_proxy_blob_id
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class QueueBackfillDependencyProxyBlobStatesGroupId < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.6'
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
|
||||
|
||||
MIGRATION = "BackfillDependencyProxyBlobStatesGroupId"
|
||||
DELAY_INTERVAL = 2.minutes
|
||||
BATCH_SIZE = 1000
|
||||
SUB_BATCH_SIZE = 100
|
||||
|
||||
def up
|
||||
queue_batched_background_migration(
|
||||
MIGRATION,
|
||||
:dependency_proxy_blob_states,
|
||||
:dependency_proxy_blob_id,
|
||||
:group_id,
|
||||
:dependency_proxy_blobs,
|
||||
:group_id,
|
||||
:dependency_proxy_blob_id,
|
||||
job_interval: DELAY_INTERVAL,
|
||||
batch_size: BATCH_SIZE,
|
||||
sub_batch_size: SUB_BATCH_SIZE
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
delete_batched_background_migration(
|
||||
MIGRATION,
|
||||
:dependency_proxy_blob_states,
|
||||
:dependency_proxy_blob_id,
|
||||
[
|
||||
:group_id,
|
||||
:dependency_proxy_blobs,
|
||||
:group_id,
|
||||
:dependency_proxy_blob_id
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
fd3f1a27204fe2952e2f83a94f92737edfd1ff7b446e5db98b052bb03e3373d3
|
||||
|
|
@ -0,0 +1 @@
|
|||
bd0cac7a4cd41fad0dfdf2959f52ad3d2fb37563df9bb5ac3c5ab2c1c592f9d3
|
||||
|
|
@ -0,0 +1 @@
|
|||
be10cd330779b21118c96f3e940e3632e8d79566eeb38af0c9118c0ab8507102
|
||||
|
|
@ -0,0 +1 @@
|
|||
e384696ed03e4ddb5b88941cf0141cb9793c66eebcb6892e1cee3ed1225201aa
|
||||
|
|
@ -0,0 +1 @@
|
|||
33ad1996ec23c69a5295ab18b7ba1b986e4d1f3e05de123178e5c864e531fb6b
|
||||
|
|
@ -0,0 +1 @@
|
|||
bad4fab793a81707348b46027bee797eaa641ddb71e17d1c22950887dc590d2e
|
||||
|
|
@ -1275,6 +1275,22 @@ RETURN NEW;
|
|||
END
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION trigger_38bfee591e40() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
IF NEW."group_id" IS NULL THEN
|
||||
SELECT "group_id"
|
||||
INTO NEW."group_id"
|
||||
FROM "dependency_proxy_blobs"
|
||||
WHERE "dependency_proxy_blobs"."id" = NEW."dependency_proxy_blob_id";
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION trigger_3d1a58344b29() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
|
|
@ -10507,6 +10523,7 @@ CREATE TABLE dependency_proxy_blob_states (
|
|||
verification_retry_count smallint DEFAULT 0 NOT NULL,
|
||||
verification_checksum bytea,
|
||||
verification_failure text,
|
||||
group_id bigint,
|
||||
CONSTRAINT check_8e4f76fffe CHECK ((char_length(verification_failure) <= 255))
|
||||
);
|
||||
|
||||
|
|
@ -28870,6 +28887,8 @@ CREATE INDEX index_dependency_proxy_blob_states_needs_verification ON dependency
|
|||
|
||||
CREATE INDEX index_dependency_proxy_blob_states_on_dependency_proxy_blob_id ON dependency_proxy_blob_states USING btree (dependency_proxy_blob_id);
|
||||
|
||||
CREATE INDEX index_dependency_proxy_blob_states_on_group_id ON dependency_proxy_blob_states USING btree (group_id);
|
||||
|
||||
CREATE INDEX index_dependency_proxy_blob_states_on_verification_state ON dependency_proxy_blob_states USING btree (verification_state);
|
||||
|
||||
CREATE INDEX index_dependency_proxy_blob_states_pending_verification ON dependency_proxy_blob_states USING btree (verified_at NULLS FIRST) WHERE (verification_state = 0);
|
||||
|
|
@ -33868,6 +33887,8 @@ CREATE TRIGGER trigger_3691f9f6a69f BEFORE INSERT OR UPDATE ON remote_developmen
|
|||
|
||||
CREATE TRIGGER trigger_388de55cd36c BEFORE INSERT OR UPDATE ON ci_builds_runner_session FOR EACH ROW EXECUTE FUNCTION trigger_388de55cd36c();
|
||||
|
||||
CREATE TRIGGER trigger_38bfee591e40 BEFORE INSERT OR UPDATE ON dependency_proxy_blob_states FOR EACH ROW EXECUTE FUNCTION trigger_38bfee591e40();
|
||||
|
||||
CREATE TRIGGER trigger_3d1a58344b29 BEFORE INSERT OR UPDATE ON alert_management_alert_assignees FOR EACH ROW EXECUTE FUNCTION trigger_3d1a58344b29();
|
||||
|
||||
CREATE TRIGGER trigger_3e067fa9bfe3 BEFORE INSERT OR UPDATE ON incident_management_timeline_event_tag_links FOR EACH ROW EXECUTE FUNCTION trigger_3e067fa9bfe3();
|
||||
|
|
@ -34998,6 +35019,9 @@ ALTER TABLE ONLY milestones
|
|||
ALTER TABLE ONLY boards_epic_list_user_preferences
|
||||
ADD CONSTRAINT fk_95eac55851 FOREIGN KEY (epic_list_id) REFERENCES boards_epic_lists(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY dependency_proxy_blob_states
|
||||
ADD CONSTRAINT fk_95ee495fd6 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY issues
|
||||
ADD CONSTRAINT fk_96b1dd429c FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -363,10 +363,12 @@ these steps:
|
|||
Rendered diagrams are cached. To see the updates, try these steps:
|
||||
|
||||
- If the diagram is in a Markdown file, make a small change to the Markdown file, and commit it. This triggers a re-render.
|
||||
- [Clear your GitLab cache](../raketasks/maintenance.md#clear-redis-cache).
|
||||
- [Invalidate the Markdown cache](../invalidate_markdown_cache.md#invalidate-the-cache) to force any cached Markdown
|
||||
in the database or Redis to be cleared.
|
||||
|
||||
If you're still not seeing the updated URL, check the following:
|
||||
|
||||
- Ensure the PlantUML server is accessible from your GitLab instance.
|
||||
- Verify that the PlantUML integration is enabled in your GitLab settings.
|
||||
- Check the GitLab logs for errors related to PlantUML rendering.
|
||||
- [Clear your GitLab Redis cache](../raketasks/maintenance.md#clear-redis-cache).
|
||||
|
|
|
|||
|
|
@ -120,12 +120,72 @@ Disabling the feature flag stops logs from being written.
|
|||
|
||||
### Logs in your GitLab installation
|
||||
|
||||
In your instance log directory, a file called `llm.log` is populated.
|
||||
The logging setup is designed to protect sensitive information while maintaining transparency about system operations, and is made up of the following components:
|
||||
|
||||
- Logs that capture requests to the GitLab instance.
|
||||
- Feature flag and logging control.
|
||||
- The `llm.log` file.
|
||||
|
||||
#### Logs that capture requests to the GitLab instance
|
||||
|
||||
Logging in the `application.json`, `production_json.log`, and `production.log` files, among others, capture requests to the GitLab instance:
|
||||
|
||||
- **Filtered Requests**: We log the requests in these files but ensure that sensitive data (such as input parameters) is **filtered**. This means that while the request metadata is captured (for example, the request type, endpoint, and response status), the actual input data (for example, the query parameters, variables, and content) is not logged to prevent the exposure of sensitive information.
|
||||
- **Example 1**: In the case of a code suggestions completion request, the logs capture the request details while filtering sensitive information:
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/graphql",
|
||||
"controller": "GraphqlController",
|
||||
"action": "execute",
|
||||
"status": 500,
|
||||
"params": [
|
||||
{"key": "query", "value": "[FILTERED]"},
|
||||
{"key": "variables", "value": "[FILTERED]"},
|
||||
{"key": "operationName", "value": "chat"}
|
||||
],
|
||||
"exception": {
|
||||
"class": "NoMethodError",
|
||||
"message": "undefined method `id` for {:skip=>true}:Hash"
|
||||
},
|
||||
"time": "2024-08-28T14:13:50.328Z"
|
||||
}
|
||||
```
|
||||
|
||||
As shown, while the error information and general structure of the request are logged, the sensitive input parameters are marked as `[FILTERED]`.
|
||||
|
||||
- **Example 2**: In the case of a code suggestions completion request, the logs also capture the request details while filtering sensitive information:
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/api/v4/code_suggestions/completions",
|
||||
"status": 200,
|
||||
"params": [
|
||||
{"key": "prompt_version", "value": 1},
|
||||
{"key": "current_file", "value": {"file_name": "/test.rb", "language_identifier": "ruby", "content_above_cursor": "[FILTERED]", "content_below_cursor": "[FILTERED]"}},
|
||||
{"key": "telemetry", "value": []}
|
||||
],
|
||||
"time": "2024-10-15T06:51:09.004Z"
|
||||
}
|
||||
```
|
||||
|
||||
As shown, while the general structure of the request is logged, the sensitive input parameters such as `content_above_cursor` and `content_below_cursor` are marked as `[FILTERED]`.
|
||||
|
||||
### Feature Flag and Logging Control
|
||||
|
||||
**Feature Flag Dependency**: You can control a subset of these logs by enabling or disabling the `expanded_ai_logging` feature flag. Disabling the feature flag disables logging for specific operations. For more information, see the [Feature Flag section under Privacy Considerations](../../development/ai_features/index.md#privacy-considerations).
|
||||
|
||||
### The `llm.log` file
|
||||
|
||||
The [`llm.log` file](../../administration/logs/index.md#llmlog) in your instance is populated only when the `:expanded_ai_logging` feature flag is enabled. When this feature flag is active, full logging is enabled, capturing all prompts, inputs, and outputs in `llm.log` on your GitLab self-managed instance.
|
||||
|
||||
For more information on:
|
||||
|
||||
- Logged events and their properties, see the [logged event documentation](../../development/ai_features/logged_events.md).
|
||||
- How to rotate, manage, export and visualize the logs in `llm.log`, see the [log system documentation](../logs/index.md).
|
||||
- How to rotate, manage, export, and visualize the logs in `llm.log`, see the [log system documentation](../logs/index.md).
|
||||
- The log file location (for example, so you can delete logs), see [LLM input and output logging](../logs/index.md#llm-input-and-output-logging).
|
||||
|
||||
### Logs in your AI Gateway container
|
||||
|
||||
|
|
@ -140,9 +200,10 @@ docker run -e AIGW_GITLAB_URL=<your_gitlab_instance> \
|
|||
<image>
|
||||
```
|
||||
|
||||
If you do not specify a file name, logs are streamed to the output.
|
||||
If you do not specify a filename, logs are streamed to the output and can also be managed using Docker logs.
|
||||
For more information, see the [Docker Logs documentation](https://docs.docker.com/reference/cli/docker/container/logs/).
|
||||
|
||||
Additionally, the outputs of the AI Gateway execution can also be useful for debugging issues. To access them:
|
||||
Additionally, the outputs of the AI Gateway execution can help with debugging issues. To access them:
|
||||
|
||||
- When using Docker:
|
||||
|
||||
|
|
@ -158,17 +219,186 @@ Additionally, the outputs of the AI Gateway execution can also be useful for deb
|
|||
|
||||
To ingest these logs into the logging solution, see your logging provider documentation.
|
||||
|
||||
### Logs structure
|
||||
|
||||
When a POST request is made (for example, to the `/chat/completions` endpoint), the server logs the request:
|
||||
|
||||
- Payload
|
||||
- Headers
|
||||
- Metadata
|
||||
|
||||
#### 1. Request payload
|
||||
|
||||
The JSON payload typically includes the following fields:
|
||||
|
||||
- `messages`: An array of message objects.
|
||||
- Each message object contains:
|
||||
- `content`: A string representing the user's input or query.
|
||||
- `role`: Indicates the role of the message sender (for example, `user`).
|
||||
- `model`: A string specifying the model to be used (for example, `mistral`).
|
||||
- `max_tokens`: An integer specifying the maximum number of tokens to generate in the response.
|
||||
- `n`: An integer indicating the number of completions to generate.
|
||||
- `stop`: An array of strings denoting stop sequences for the generated text.
|
||||
- `stream`: A boolean indicating whether the response should be streamed.
|
||||
- `temperature`: A float controlling the randomness of the output.
|
||||
|
||||
##### Example request
|
||||
|
||||
```json
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"content": "<s>[SUFFIX]None[PREFIX]# # build a hello world ruby method\n def say_goodbye\n puts \"Goodbye, World!\"\n end\n\ndef main\n say_hello\n say_goodbye\nend\n\nmain",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
"model": "mistral",
|
||||
"max_tokens": 128,
|
||||
"n": 1,
|
||||
"stop": ["[INST]", "[/INST]", "[PREFIX]", "[MIDDLE]", "[SUFFIX]"],
|
||||
"stream": false,
|
||||
"temperature": 0.0
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Request headers
|
||||
|
||||
The request headers provide additional context about the client making the request. Key headers might include:
|
||||
|
||||
- `Authorization`: Contains the Bearer token for API access.
|
||||
- `Content-Type`: Indicates the media type of the resource (for example, `JSON`).
|
||||
- `User-Agent`: Information about the client software making the request.
|
||||
- `X-Stainless-` headers: Various headers providing additional metadata about the client environment.
|
||||
|
||||
##### Example request headers
|
||||
|
||||
```json
|
||||
{
|
||||
"host": "0.0.0.0:4000",
|
||||
"accept-encoding": "gzip, deflate",
|
||||
"connection": "keep-alive",
|
||||
"accept": "application/json",
|
||||
"content-type": "application/json",
|
||||
"user-agent": "AsyncOpenAI/Python 1.51.0",
|
||||
"authorization": "Bearer <TOKEN>",
|
||||
"content-length": "364"
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. Request metadata
|
||||
|
||||
The metadata includes various fields that describe the context of the request:
|
||||
|
||||
- `requester_metadata`: Additional metadata about the requester.
|
||||
- `user_api_key`: The API key used for the request (anonymized).
|
||||
- `api_version`: The version of the API being used.
|
||||
- `request_timeout`: The timeout duration for the request.
|
||||
- `call_id`: A unique identifier for the call.
|
||||
|
||||
##### Example metadata
|
||||
|
||||
```json
|
||||
{
|
||||
"user_api_key": "<ANONYMIZED_KEY>",
|
||||
"api_version": "1.48.18",
|
||||
"request_timeout": 600,
|
||||
"call_id": "e1aaa316-221c-498c-96ce-5bc1e7cb63af"
|
||||
}
|
||||
```
|
||||
|
||||
### Example response
|
||||
|
||||
The server responds with a structured model response. For example:
|
||||
|
||||
```python
|
||||
Response: ModelResponse(
|
||||
id='chatcmpl-5d16ad41-c130-4e33-a71e-1c392741bcb9',
|
||||
choices=[
|
||||
Choices(
|
||||
finish_reason='stop',
|
||||
index=0,
|
||||
message=Message(
|
||||
content=' Here is the corrected Ruby code for your function:\n\n```ruby\ndef say_hello\n puts "Hello, World!"\nend\n\ndef say_goodbye\n puts "Goodbye, World!"\nend\n\ndef main\n say_hello\n say_goodbye\nend\n\nmain\n```\n\nIn your original code, the method names were misspelled as `say_hell` and `say_gobdye`. I corrected them to `say_hello` and `say_goodbye`, respectively. Also, there was no need for the prefix',
|
||||
role='assistant',
|
||||
tool_calls=None,
|
||||
function_call=None
|
||||
)
|
||||
)
|
||||
],
|
||||
created=1728983827,
|
||||
model='mistral',
|
||||
object='chat.completion',
|
||||
system_fingerprint=None,
|
||||
usage=Usage(
|
||||
completion_tokens=128,
|
||||
prompt_tokens=69,
|
||||
total_tokens=197,
|
||||
completion_tokens_details=None,
|
||||
prompt_tokens_details=None
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
### Logs in your inference service provider
|
||||
|
||||
GitLab does not manage logs generated by your inference service provider. Please refer to the documentation of your inference service
|
||||
GitLab does not manage logs generated by your inference service provider. See the documentation of your inference service
|
||||
provider on how to use their logs.
|
||||
|
||||
## Logging behavior in GitLab and AI Gateway environments
|
||||
|
||||
GitLab provides logging functionality for AI-related activities through the use of `llm.log`, which captures inputs, outputs, and other relevant information. However, the loggig behavior differs depending on whether the GitLab instance and AI Gateway (AI Gateway) are **self-hosted** or **cloud-connected**.
|
||||
|
||||
By default, the log does not contain LLM prompt input and response output to support [data retention policies](../../user/gitlab_duo/data_usage.md#data-retention) of AI feature data.
|
||||
|
||||
## Logging Scenarios
|
||||
|
||||
### GitLab self-managed and self-hosted AI Gateway
|
||||
|
||||
In this configuration, both GitLab and the AI Gateway are hosted by the customer.
|
||||
|
||||
- **Logging Behavior**: Full logging is enabled, and all prompts, inputs, and outputs are logged to `llm.log` on the GitLab self-managed instance.
|
||||
- **Expanded Logging**: When the `:expanded_ai_logging` feature flag is activated, extra debugging information is logged, including:
|
||||
- Preprocessed prompts.
|
||||
- Final prompts.
|
||||
- Additional context.
|
||||
- **Privacy**: Because both GitLab and AI Gateway are self-hosted:
|
||||
- The customer has full control over data handling.
|
||||
- Logging of sensitive information can be enabled or disabled at the customer's discretion.
|
||||
|
||||
### GitLab self-managed and GitLab-managed AI Gateway (cloud-connected)
|
||||
|
||||
In this scenario, the customer hosts GitLab but relies on the GitLab-managed AI Gateway for AI processing.
|
||||
|
||||
- **Logging Behavior**: Prompts and inputs sent to the AI Gateway are **not logged** in the cloud-connected AI Gateway to prevent exposure of sensitive information such as personally identifiable information (PII).
|
||||
- **Expanded Logging**: Even if the `:expanded_ai_logging` feature flag is enabled, no detailed logs are generated in the GitLab-managed AI Gateway to avoid unintended leaks of sensitive information.
|
||||
- Logging remains **minimal** in this setup, and the expanded logging features are disabled by default.
|
||||
- **Privacy**: This configuration is designed to ensure that sensitive data is not logged in a cloud environment.
|
||||
|
||||
## Feature Flag: `:expanded_ai_logging`
|
||||
|
||||
The `:expanded_ai_logging` feature flag controls whether additional debugging information, including prompts and inputs, is logged. This flag is essential for monitoring and debugging AI-related activities.
|
||||
|
||||
### Behavior by Deployment Setup
|
||||
|
||||
- **GitLab self-managed and self-hosted AI Gateway**: The feature flag enables detailed logging to `llm.log` on the self-hosted instance, capturing inputs and outputs for AI models.
|
||||
- **GitLab self-managed and GitLab-managed AI Gateway**: The feature flag enables logging on your self-managed instance. However, the flag does **not** activate expanded logging for the GitLab-managed AI Gateway side. Logging remains disabled for cloud-connected AI Gateway to protect sensitive data.
|
||||
For more information, see the [Feature Flag section under Privacy Considerations](../../development/ai_features/index.md#privacy-considerations) documentation.
|
||||
|
||||
### Logging in cloud-connected AI Gateways
|
||||
|
||||
To prevent potential data leakage of sensitive information, expanded logging (including prompts and inputs) is intentionally disabled when using a cloud-connected AI Gateway. Preventing the exposure of PII is a priority.
|
||||
|
||||
### Cross-referencing logs between AI Gateway and GitLab
|
||||
|
||||
The property `correlation_id` is assigned to every request and is carried across different components that respond to a
|
||||
request. For more information, see the [documentation on finding logs with a correlation ID](../logs/tracing_correlation_id.md).
|
||||
|
||||
Correlation ID is not available in your model provider logs.
|
||||
The Correlation ID can be found in your AI Gateway and GitLab logs. However, it is not present in your model provider logs.
|
||||
|
||||
#### Related topics
|
||||
|
||||
- [Parsing GitLab logs with jq](../logs/log_parsing.md)
|
||||
- [Searching your logs for the correlation ID](../logs/tracing_correlation_id.md#searching-your-logs-for-the-correlation-id)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
|
|
|||
|
|
@ -39370,6 +39370,7 @@ Values for sorting timelogs.
|
|||
| <a id="todoactionenumreview_requested"></a>`review_requested` | Review was requested from the user. |
|
||||
| <a id="todoactionenumreview_submitted"></a>`review_submitted` | Merge request authored by the user received a review. |
|
||||
| <a id="todoactionenumssh_key_expired"></a>`ssh_key_expired` | SSH key of the user has expired. |
|
||||
| <a id="todoactionenumssh_key_expiring_soon"></a>`ssh_key_expiring_soon` | SSH key of the user will expire soon. |
|
||||
| <a id="todoactionenumunmergeable"></a>`unmergeable` | Merge request authored by the user could not be merged. |
|
||||
|
||||
### `TodoSort`
|
||||
|
|
|
|||
|
|
@ -292,11 +292,27 @@ the migration that was used to enqueue it. Pay careful attention to:
|
|||
When finalizing a batched background migration you also need to update the
|
||||
`finalized_by` in the corresponding `db/docs/batched_background_migrations`
|
||||
file. The value should be the timestamp/version of the migration you added to
|
||||
finalize it.
|
||||
finalize it. The [schema version of the RSpec tests](../testing_guide/testing_migrations_guide.md#testing-a-non-activerecordmigration-class)
|
||||
associated with the migration should also be set to this version to avoid having the tests fail due
|
||||
to future schema changes.
|
||||
|
||||
See the below [Examples](#examples) for specific details on what the actual
|
||||
migration code should be.
|
||||
|
||||
### Deleting batched background migration code
|
||||
|
||||
Once a batched background migration has been finalized, the migration code in `lib/gitlab/background_migration/`
|
||||
and its associated tests can be deleted after the next required stop following the finalization.
|
||||
|
||||
Here is an example scenario:
|
||||
|
||||
- 17.2 and 17.5 are required stops.
|
||||
- In 17.0 the batched background migration is queued.
|
||||
- In 17.3 the migration may be finalized, provided that it's completed in GitLab.com.
|
||||
- In 17.6 the code related to the migration may be deleted.
|
||||
|
||||
Batched background migration code is routinely deleted when migrations are squashed.
|
||||
|
||||
### Use job arguments
|
||||
|
||||
`BatchedMigrationJob` provides the `job_arguments` helper method for job classes to define the job arguments they need.
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ In the following example, you add the utility classes `gl-fixed` and `gl-inset-x
|
|||
<style>
|
||||
.my-class {
|
||||
top: $header-height;
|
||||
z-index: 999;
|
||||
min-height: $comparison-empty-state-height;
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
|
|
@ -235,7 +235,7 @@ In the following example, you add the utility classes `gl-fixed` and `gl-inset-x
|
|||
<style>
|
||||
.my-class {
|
||||
top: $header-height;
|
||||
z-index: 999;
|
||||
min-height: $comparison-empty-state-height;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
|
|
|||
|
|
@ -83,11 +83,16 @@ You can view and [manage renewal invoice](../self_managed/index.md#manage-renewa
|
|||
|
||||
### Renew for fewer seats
|
||||
|
||||
You can renew your subscription for fewer seats, as long as the seat total is equal to or greater than the billable user quantity at the time of renewal.
|
||||
If you want to renew for fewer seats, you can do either of the following:
|
||||
Subscription renewals with fewer seats must have or exceed the current number of billable users.
|
||||
Before you renew your subscription, [reduce the number of billable users](#remove-users-from-subscription)
|
||||
if it exceeds the number of seats you want to renew for.
|
||||
|
||||
- [Manually renew](../self_managed/index.md#renew-subscription-manually) within 15 days of subscription renewal date, and **specify the desired seat quantity** on the renewal page. To reduce billable user quantity, [remove users from your subscription](#remove-users-from-subscription).
|
||||
- Disable automatic subscription renewal and work with the Sales team to renew it for the number of seats you want.
|
||||
To manually renew your subscription for fewer seats, you can either:
|
||||
|
||||
- [Manually renew](../self_managed/index.md#renew-subscription-manually) within 15 days of the
|
||||
subscription renewal date. Ensure that you specify the seat quantity when you renew.
|
||||
- [Disable automatic renewal of your subscription](../self_managed/index.md#enable-or-disable-automatic-subscription-renewal),
|
||||
and contact the GitLab Sales team to renew it for the number of seats you want.
|
||||
|
||||
### Automatic subscription renewal
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module BackgroundMigration
|
||||
class BackfillDependencyProxyBlobStatesGroupId < BackfillDesiredShardingKeyJob
|
||||
operation_name :backfill_dependency_proxy_blob_states_group_id
|
||||
feature_category :geo_replication
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -14311,6 +14311,9 @@ msgstr ""
|
|||
msgid "ComplianceFrameworks|The compliance framework must be edited in top-level group %{linkStart}namespace%{linkEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "ComplianceFrameworks|The default framework can't be deleted"
|
||||
msgstr ""
|
||||
|
||||
msgid "ComplianceFrameworks|There can be only one default framework."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -26310,9 +26313,6 @@ msgstr ""
|
|||
msgid "GroupRoadmap|%{dateWord} – No end date"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupRoadmap|%{startDateInWords} – %{endDateInWords}"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupRoadmap|Loading epics"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -26349,10 +26349,10 @@ msgstr ""
|
|||
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %{linkStart}child epics%{linkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
|
||||
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{dateRange}."
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
|
||||
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{dateRange}."
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupRoadmap|View epics list"
|
||||
|
|
@ -57258,6 +57258,9 @@ msgstr ""
|
|||
msgid "Todos|SSH key expired"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|SSH key expiring soon"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|Something went wrong. Please try again."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -57297,6 +57300,9 @@ msgstr ""
|
|||
msgid "Todos|Your SSH key has expired"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|Your SSH key is expiring soon"
|
||||
msgstr ""
|
||||
|
||||
msgid "Todos|Your To-Do List shows what to work on next"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -141,8 +141,11 @@ module QA
|
|||
end
|
||||
|
||||
def running_on_dot_com?
|
||||
uri = URI.parse(Runtime::Scenario.gitlab_address)
|
||||
uri.host.include?('.com')
|
||||
URI.parse(Runtime::Scenario.gitlab_address).host.include?('.com')
|
||||
end
|
||||
|
||||
def running_on_release?
|
||||
URI.parse(Runtime::Scenario.gitlab_address).host.include?('release.gitlab.net')
|
||||
end
|
||||
|
||||
def running_on_dev?
|
||||
|
|
|
|||
|
|
@ -64,8 +64,9 @@ module QA
|
|||
#
|
||||
# @return [void]
|
||||
def wait_for_login_page_to_load
|
||||
# Do not perform headless request on .com due to cloudfare
|
||||
if Runtime::Env.running_on_dot_com?
|
||||
# Do not perform headless request on .com or release environment due to cloudfare
|
||||
# TODO: add additional check to detect when environment doesn't allow to check sign in page via headless request
|
||||
if Runtime::Env.running_on_dot_com? || Runtime::Env.running_on_release?
|
||||
debug("Checking for required elements via web browser")
|
||||
return Capybara.current_session.using_wait_time(wait) { Runtime::Browser.visit(:gitlab, Page::Main::Login) }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,497 @@
|
|||
# Lines beginning with a hash are ignored, like this one.
|
||||
# Do not add new specs to this file.
|
||||
ee/spec/frontend/access_tokens/components/expires_at_field_spec.js
|
||||
ee/spec/frontend/admin/application_settings/deletion_protection/index_spec.js
|
||||
ee/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js
|
||||
ee/spec/frontend/admin/subscriptions/show/components/subscription_activation_form_spec.js
|
||||
ee/spec/frontend/admin/subscriptions/show/components/subscription_activation_modal_spec.js
|
||||
ee/spec/frontend/admin/subscriptions/show/components/subscription_breakdown_spec.js
|
||||
ee/spec/frontend/admin/subscriptions/show/components/subscription_details_history_spec.js
|
||||
ee/spec/frontend/ai/settings/components/duo_experiment_beta_features_form_spec.js
|
||||
ee/spec/frontend/analytics/analytics_dashboards/components/analytics_dashboard_panel_spec.js
|
||||
ee/spec/frontend/analytics/analytics_dashboards/components/analytics_dashboards_breadcrumbs_spec.js
|
||||
ee/spec/frontend/analytics/analytics_dashboards/components/analytics_visualization_designer_spec.js
|
||||
ee/spec/frontend/analytics/analytics_dashboards/components/list/feature_list_item_spec.js
|
||||
ee/spec/frontend/analytics/cycle_analytics/components/value_stream_aggregation_status_spec.js
|
||||
ee/spec/frontend/analytics/cycle_analytics/components/value_stream_form_content_spec.js
|
||||
ee/spec/frontend/analytics/cycle_analytics/vsa_settings/components/value_stream_form_content_spec.js
|
||||
ee/spec/frontend/analytics/dashboards/ai_impact/components/metric_table_spec.js
|
||||
ee/spec/frontend/analytics/devops_reports/devops_adoption/components/devops_adoption_app_spec.js
|
||||
ee/spec/frontend/analytics/devops_reports/devops_adoption/components/devops_adoption_overview_spec.js
|
||||
ee/spec/frontend/analytics/devops_reports/devops_adoption/components/devops_adoption_overview_table_spec.js
|
||||
ee/spec/frontend/analytics/group_ci_cd_analytics/components/release_stats_card_spec.js
|
||||
ee/spec/frontend/analytics/merge_request_analytics/components/filter_bar_spec.js
|
||||
ee/spec/frontend/analytics/merge_request_analytics/components/throughput_chart_spec.js
|
||||
ee/spec/frontend/analytics/merge_request_analytics/components/throughput_table_spec.js
|
||||
ee/spec/frontend/approvals/components/approval_rules_app_spec.js
|
||||
ee/spec/frontend/approvals/components/security_configuration/unconfigured_security_rule_spec.js
|
||||
ee/spec/frontend/approvals/components/security_configuration/unconfigured_security_rules_spec.js
|
||||
ee/spec/frontend/approvals/mr_edit/mr_rules_spec.js
|
||||
ee/spec/frontend/approvals/project_settings/project_rules_spec.js
|
||||
ee/spec/frontend/audit_events/components/audit_events_filter_spec.js
|
||||
ee/spec/frontend/boards/components/board_content_sidebar_spec.js
|
||||
ee/spec/frontend/boards/components/board_form_spec.js
|
||||
ee/spec/frontend/boards/components/board_list_spec.js
|
||||
ee/spec/frontend/boards/components/board_new_issue_spec.js
|
||||
ee/spec/frontend/boards/components/epic_board_content_sidebar_spec.js
|
||||
ee/spec/frontend/boards/components/epics_swimlanes_spec.js
|
||||
ee/spec/frontend/ci/pipeline_details/header/pipeline_header_spec.js
|
||||
ee/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js
|
||||
ee/spec/frontend/ci/runner/admin_runners_dashboard/admin_runners_wait_times_spec.js
|
||||
ee/spec/frontend/ci/runner/components/runner_details_spec.js
|
||||
ee/spec/frontend/ci/runner/components/runner_form_fields_spec.js
|
||||
ee/spec/frontend/ci/runner/components/runner_header_spec.js
|
||||
ee/spec/frontend/ci/runner/components/runner_usage_spec.js
|
||||
ee/spec/frontend/ci/runner/components/stat/runner_stats_spec.js
|
||||
ee/spec/frontend/ci/runner/components/stat/runner_upgrade_status_stats_spec.js
|
||||
ee/spec/frontend/ci/runner/group_runners/group_runners_app_spec.js
|
||||
ee/spec/frontend/ci/runner/group_runners_dashboard/group_runners_wait_times_spec.js
|
||||
ee/spec/frontend/ci/secrets/components/secrets_app_spec.js
|
||||
ee/spec/frontend/ci/secrets/components/secrets_breadcrumbs_spec.js
|
||||
ee/spec/frontend/ci/secrets/router_spec.js
|
||||
ee/spec/frontend/clusters/components/environments_spec.js
|
||||
ee/spec/frontend/compliance_dashboard/components/frameworks_report/edit_framework/components/policies_section_spec.js
|
||||
ee/spec/frontend/compliance_dashboard/components/frameworks_report/framework_info_drawer_spec.js
|
||||
ee/spec/frontend/compliance_dashboard/components/frameworks_report/report_spec.js
|
||||
ee/spec/frontend/compliance_dashboard/components/projects_report/report_spec.js
|
||||
ee/spec/frontend/compliance_dashboard/components/standards_adherence_report/base_table_spec.js
|
||||
ee/spec/frontend/compliance_dashboard/components/standards_adherence_report/standards_adherence_table_spec.js
|
||||
ee/spec/frontend/contextual_sidebar/components/trial_status_widget_spec.js
|
||||
ee/spec/frontend/dependencies/components/app_spec.js
|
||||
ee/spec/frontend/dependencies/components/dependency_location_spec.js
|
||||
ee/spec/frontend/dependencies/components/dependency_path_viewer_spec.js
|
||||
ee/spec/frontend/dependencies/components/filtered_search/tokens/component_token_spec.js
|
||||
ee/spec/frontend/dependencies/components/filtered_search/tokens/license_token_spec.js
|
||||
ee/spec/frontend/dependencies/components/filtered_search/tokens/package_manager_token_spec.js
|
||||
ee/spec/frontend/dependencies/components/filtered_search/tokens/project_token_spec.js
|
||||
ee/spec/frontend/environments_dashboard/components/project_header_spec.js
|
||||
ee/spec/frontend/external_issues_list/components/external_issues_list_root_spec.js
|
||||
ee/spec/frontend/geo_sites/components/details/secondary_site/geo_site_replication_details_responsive_spec.js
|
||||
ee/spec/frontend/geo_sites/index_spec.js
|
||||
ee/spec/frontend/groups/components/invite_members_spec.js
|
||||
ee/spec/frontend/groups/settings/components/comma_separated_list_token_selector_spec.js
|
||||
ee/spec/frontend/incidents/components/service_level_agreement_cell_spec.js
|
||||
ee/spec/frontend/insights/insights_router_spec.js
|
||||
ee/spec/frontend/integrations/edit/components/jira_issue_creation_vulnerabilities_spec.js
|
||||
ee/spec/frontend/issuable/components/related_issuable_item_spec.js
|
||||
ee/spec/frontend/issues/list/components/issues_list_app_spec.js
|
||||
ee/spec/frontend/issues/service_desk/components/service_desk_list_app_spec.js
|
||||
ee/spec/frontend/issues_analytics/components/issues_analytics_table_spec.js
|
||||
ee/spec/frontend/iterations/components/iteration_form_spec.js
|
||||
ee/spec/frontend/iterations/components/iteration_report_issues_spec.js
|
||||
ee/spec/frontend/members/components/action_dropdowns/user_action_dropdown_spec.js
|
||||
ee/spec/frontend/members/components/modals/ldap_override_confirmation_modal_spec.js
|
||||
ee/spec/frontend/members/components/table/drawer/role_details_drawer_spec.js
|
||||
ee/spec/frontend/members/components/table/drawer/role_updater_spec.js
|
||||
ee/spec/frontend/members/components/table/max_role_spec.js
|
||||
ee/spec/frontend/members/components/table/member_action_buttons_spec.js
|
||||
ee/spec/frontend/members/components/table/members_table_spec.js
|
||||
ee/spec/frontend/metrics/details/filter_bar/groupby_filter_spec.js
|
||||
ee/spec/frontend/metrics/details/metrics_details_spec.js
|
||||
ee/spec/frontend/metrics/details/related_traces_spec.js
|
||||
ee/spec/frontend/ml/ai_agents/views/edit_agent_spec.js
|
||||
ee/spec/frontend/notes/components/ai_summary_spec.js
|
||||
ee/spec/frontend/notes/components/notes_app_spec.js
|
||||
ee/spec/frontend/on_demand_scans/components/action_button_spec.js
|
||||
ee/spec/frontend/on_demand_scans/components/tabs/base_tab_spec.js
|
||||
ee/spec/frontend/on_demand_scans_form/components/scan_schedule_spec.js
|
||||
ee/spec/frontend/oncall_schedule/schedule/components/current_day_indicator_spec.js
|
||||
ee/spec/frontend/oncall_schedule/schedule/components/preset_days/days_header_sub_item_spec.js
|
||||
ee/spec/frontend/oncall_schedule/schedule/components/preset_weeks/weeks_header_sub_item_spec.js
|
||||
ee/spec/frontend/oncall_schedule/schedule/components/shifts/components/schedule_shift_wrapper_spec.js
|
||||
ee/spec/frontend/oncall_schedule/schedule/mixins/common_mixin_spec.js
|
||||
ee/spec/frontend/password/components/password_requirement_list_spec.js
|
||||
ee/spec/frontend/product_analytics/onboarding/components/onboarding_state_spec.js
|
||||
ee/spec/frontend/product_analytics/onboarding/onboarding_view_spec.js
|
||||
ee/spec/frontend/projects/settings/branch_rules/components/view/index_spec.js
|
||||
ee/spec/frontend/projects/settings/components/shared_runners_toggle_spec.js
|
||||
ee/spec/frontend/protected_environments/protected_environment_edit_spec.js
|
||||
ee/spec/frontend/related_items_tree/components/related_items_tree_body_spec.js
|
||||
ee/spec/frontend/related_items_tree/components/tree_root_spec.js
|
||||
ee/spec/frontend/repository/components/blob_button_group_spec.js
|
||||
ee/spec/frontend/requirements/components/requirement_item_spec.js
|
||||
ee/spec/frontend/requirements/components/requirements_root_spec.js
|
||||
ee/spec/frontend/roadmap/components/roadmap_shell_spec.js
|
||||
ee/spec/frontend/roles_and_permissions/components/create_member_role_spec.js
|
||||
ee/spec/frontend/roles_and_permissions/components/role_selector_spec.js
|
||||
ee/spec/frontend/saml_providers/saml_settings_form_spec.js
|
||||
ee/spec/frontend/security_configuration/components/app_spec.js
|
||||
ee/spec/frontend/security_configuration/components/dynamic_fields_spec.js
|
||||
ee/spec/frontend/security_configuration/components/expandable_section_spec.js
|
||||
ee/spec/frontend/security_configuration/dast_pre_scan_verification/components/pre_scan_verification_configurator_spec.js
|
||||
ee/spec/frontend/security_configuration/dast_profiles/components/dast_profiles_list_spec.js
|
||||
ee/spec/frontend/security_configuration/dast_profiles/dast_scanner_profiles_form/components/dast_scanner_profiles_form_spec.js
|
||||
ee/spec/frontend/security_dashboard/components/project/security_scanner_alert_spec.js
|
||||
ee/spec/frontend/security_dashboard/components/shared/empty_states/dashboard_has_no_vulnerabilities_spec.js
|
||||
ee/spec/frontend/security_dashboard/components/shared/filtered_search/tokens/activity_token_spec.js
|
||||
ee/spec/frontend/security_dashboard/components/shared/filtered_search/tokens/cluster_token_spec.js
|
||||
ee/spec/frontend/security_dashboard/components/shared/filtered_search/tokens/severity_token_spec.js
|
||||
ee/spec/frontend/security_dashboard/components/shared/filtered_search/tokens/status_token_spec.js
|
||||
ee/spec/frontend/security_dashboard/components/shared/filtered_search/tokens/tool_token_spec.js
|
||||
ee/spec/frontend/security_dashboard/components/shared/filters/querystring_sync_spec.js
|
||||
ee/spec/frontend/security_dashboard/components/shared/vulnerability_details_graphql/details_section_spec.js
|
||||
ee/spec/frontend/security_dashboard/components/shared/vulnerability_report/container_scanning_for_registry_tab_spec.js
|
||||
ee/spec/frontend/security_dashboard/components/shared/vulnerability_report/vulnerability_list_graphql_spec.js
|
||||
ee/spec/frontend/security_dashboard/components/shared/vulnerability_report/vulnerability_report_spec.js
|
||||
ee/spec/frontend/security_dashboard/components/shared/vulnerability_report/vulnerability_report_tabs_spec.js
|
||||
ee/spec/frontend/security_orchestration/components/policies/list_component_spec.js
|
||||
ee/spec/frontend/security_orchestration/components/policies/list_header_spec.js
|
||||
ee/spec/frontend/security_orchestration/components/policies/project_modal_spec.js
|
||||
ee/spec/frontend/security_orchestration/components/policy_drawer/drawer_layout_spec.js
|
||||
ee/spec/frontend/security_orchestration/components/policy_drawer/scan_execution/details_drawer_spec.js
|
||||
ee/spec/frontend/security_orchestration/components/policy_drawer/toggle_list_spec.js
|
||||
ee/spec/frontend/security_orchestration/components/policy_editor/pipeline_execution/action/action_section_spec.js
|
||||
ee/spec/frontend/security_orchestration/components/policy_editor/pipeline_execution/action/code_block_file_path_spec.js
|
||||
ee/spec/frontend/security_orchestration/components/policy_editor/pipeline_execution/rule/rule_section_spec.js
|
||||
ee/spec/frontend/security_orchestration/components/policy_editor/scan_result/rule/scan_filters/status_filter_spec.js
|
||||
ee/spec/frontend/security_orchestration/components/policy_editor/scan_result/rule/scan_filters/status_filters_spec.js
|
||||
ee/spec/frontend/security_orchestration/components/policy_editor/section_layout_spec.js
|
||||
ee/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
|
||||
ee/spec/frontend/status_checks/components/actions_spec.js
|
||||
ee/spec/frontend/status_checks/components/modal_create_spec.js
|
||||
ee/spec/frontend/status_checks/mount_spec.js
|
||||
ee/spec/frontend/subscriptions/buy_addons_shared/components/checkout/addon_purchase_details_spec.js
|
||||
ee/spec/frontend/subscriptions/new/components/checkout/billing_address_spec.js
|
||||
ee/spec/frontend/subscriptions/new/components/checkout/order_summary_spec.js
|
||||
ee/spec/frontend/subscriptions/new/components/checkout/subscription_details_spec.js
|
||||
ee/spec/frontend/subscriptions/shared/privacy_and_terms_confirm_spec.js
|
||||
ee/spec/frontend/tracing/details/tracing_details_spec.js
|
||||
ee/spec/frontend/tracing/details/tracing_span_chart_spec.js
|
||||
ee/spec/frontend/usage_quotas/code_suggestions/components/add_on_eligible_user_list_spec.js
|
||||
ee/spec/frontend/usage_quotas/code_suggestions/components/health_check_list_spec.js
|
||||
ee/spec/frontend/usage_quotas/code_suggestions/components/saas_add_on_eligible_user_list_spec.js
|
||||
ee/spec/frontend/usage_quotas/pipelines/components/app_spec.js
|
||||
ee/spec/frontend/usage_quotas/seats/components/subscription_user_list_spec.js
|
||||
ee/spec/frontend/usage_quotas/storage/components/namespace_storage_app_spec.js
|
||||
ee/spec/frontend/users/identity_verification/components/credit_card_verification_spec.js
|
||||
ee/spec/frontend/users/identity_verification/components/international_phone_input_spec.js
|
||||
ee/spec/frontend/users/identity_verification/components/phone_verification_spec.js
|
||||
ee/spec/frontend/users/identity_verification/components/verify_phone_verification_code_spec.js
|
||||
ee/spec/frontend/users_select/index_spec.js
|
||||
ee/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_container_spec.js
|
||||
ee/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js
|
||||
ee/spec/frontend/vue_shared/components/groups_list/groups_list_item_spec.js
|
||||
ee/spec/frontend/vue_shared/components/projects_list/projects_list_item_spec.js
|
||||
ee/spec/frontend/vue_shared/components/reports/report_issues_spec.js
|
||||
ee/spec/frontend/vue_shared/components/reports/report_item_spec.js
|
||||
ee/spec/frontend/vue_shared/purchase_flow/components/checkout/sprintf_with_links_spec.js
|
||||
ee/spec/frontend/vue_shared/security_reports/components/security_training_promo_spec.js
|
||||
ee/spec/frontend/vulnerabilities/code_flow/code_flow_steps_section_spec.js
|
||||
ee/spec/frontend/vulnerabilities/generic_report/types/list_graphql_spec.js
|
||||
ee/spec/frontend/vulnerabilities/related_issues_spec.js
|
||||
ee/spec/frontend/vulnerabilities/vulnerability_file_content_viewer_spec.js
|
||||
ee/spec/frontend/vulnerabilities/vulnerability_file_contents_spec.js
|
||||
ee/spec/frontend/workspaces/common/components/workspaces_list/workspaces_table_spec.js
|
||||
ee/spec/frontend/workspaces/user/init_user_workspaces_app_spec.js
|
||||
ee/spec/frontend/workspaces/user/router/index_spec.js
|
||||
spec/frontend/__helpers__/vue_test_utils_helper_spec.js
|
||||
spec/frontend/access_tokens/index_spec.js
|
||||
spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js
|
||||
spec/frontend/admin/abuse_report/components/reported_content_spec.js
|
||||
spec/frontend/admin/broadcast_messages/components/base_spec.js
|
||||
spec/frontend/admin/signup_restrictions/components/signup_checkbox_spec.js
|
||||
spec/frontend/admin/users/components/actions/delete_with_contributions_spec.js
|
||||
spec/frontend/alert_management/components/alert_management_table_spec.js
|
||||
spec/frontend/alerts_settings/components/alerts_settings_form_spec.js
|
||||
spec/frontend/analytics/shared/components/date_ranges_dropdown_spec.js
|
||||
spec/frontend/authentication/two_factor_auth/components/recovery_codes_spec.js
|
||||
spec/frontend/authentication/two_factor_auth/index_spec.js
|
||||
spec/frontend/awards_handler_spec.js
|
||||
spec/frontend/blob/components/blob_header_spec.js
|
||||
spec/frontend/boards/board_list_spec.js
|
||||
spec/frontend/boards/components/board_content_sidebar_spec.js
|
||||
spec/frontend/boards/components/board_content_spec.js
|
||||
spec/frontend/boards/components/board_form_spec.js
|
||||
spec/frontend/boards/components/board_options_spec.js
|
||||
spec/frontend/boards/components/board_settings_sidebar_spec.js
|
||||
spec/frontend/boards/components/board_top_bar_spec.js
|
||||
spec/frontend/boards/components/toggle_focus_spec.js
|
||||
spec/frontend/boards/project_select_spec.js
|
||||
spec/frontend/branches/components/delete_branch_modal_spec.js
|
||||
spec/frontend/branches/components/delete_merged_branches_spec.js
|
||||
spec/frontend/cascading_settings/components/cascading_lock_icon_spec.js
|
||||
spec/frontend/cascading_settings/components/lock_tooltip_spec.js
|
||||
spec/frontend/ci/artifacts/components/artifacts_bulk_delete_spec.js
|
||||
spec/frontend/ci/catalog/components/ci_catalog_home_spec.js
|
||||
spec/frontend/ci/catalog/components/list/ci_resources_list_item_spec.js
|
||||
spec/frontend/ci/catalog/components/pages/ci_resource_details_page_spec.js
|
||||
spec/frontend/ci/catalog/index_spec.js
|
||||
spec/frontend/ci/ci_variable_list/components/ci_variable_drawer_spec.js
|
||||
spec/frontend/ci/ci_variable_list/components/ci_variable_shared_spec.js
|
||||
spec/frontend/ci/job_details/components/log/line_header_spec.js
|
||||
spec/frontend/ci/job_details/components/log/line_spec.js
|
||||
spec/frontend/ci/job_details/components/log/log_spec.js
|
||||
spec/frontend/ci/job_details/components/sidebar/job_sidebar_retry_button_spec.js
|
||||
spec/frontend/ci/job_details/components/sidebar/stages_dropdown_spec.js
|
||||
spec/frontend/ci/jobs_page/job_page_app_spec.js
|
||||
spec/frontend/ci/pipeline_details/graph/components/job_group_dropdown_spec.js
|
||||
spec/frontend/ci/pipeline_details/header/components/header_badges_spec.js
|
||||
spec/frontend/ci/pipeline_editor/components/header/validation_segment_spec.js
|
||||
spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/rules_item_spec.js
|
||||
spec/frontend/ci/pipeline_editor/components/lint/ci_lint_warnings_spec.js
|
||||
spec/frontend/ci/pipeline_editor/components/pipeline_editor_tabs_spec.js
|
||||
spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js
|
||||
spec/frontend/ci/pipeline_mini_graph/legacy_pipeline_mini_graph/legacy_pipeline_stage_spec.js
|
||||
spec/frontend/ci/pipeline_mini_graph/pipeline_mini_graph_spec.js
|
||||
spec/frontend/ci/pipelines_page/components/pipeline_multi_actions_spec.js
|
||||
spec/frontend/ci/pipelines_page/components/pipelines_artifacts_spec.js
|
||||
spec/frontend/ci/pipelines_page/components/pipelines_filtered_search_spec.js
|
||||
spec/frontend/ci/runner/admin_runner_show/admin_runner_show_app_spec.js
|
||||
spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js
|
||||
spec/frontend/ci/runner/components/cells/link_cell_spec.js
|
||||
spec/frontend/ci/runner/components/registration/registration_instructions_spec.js
|
||||
spec/frontend/ci/runner/components/runner_bulk_delete_spec.js
|
||||
spec/frontend/ci/runner/components/runner_details_spec.js
|
||||
spec/frontend/ci/runner/components/runner_form_fields_spec.js
|
||||
spec/frontend/ci/runner/components/runner_managers_detail_spec.js
|
||||
spec/frontend/ci/runner/components/runner_managers_table_spec.js
|
||||
spec/frontend/ci/runner/components/runner_platforms_radio_spec.js
|
||||
spec/frontend/ci/runner/components/runner_tags_spec.js
|
||||
spec/frontend/ci/runner/components/stat/runner_stats_spec.js
|
||||
spec/frontend/ci/runner/group_runner_show/group_runner_show_app_spec.js
|
||||
spec/frontend/ci/runner/group_runners/group_runners_app_spec.js
|
||||
spec/frontend/ci_settings_pipeline_triggers/components/edit_trigger_modal_spec.js
|
||||
spec/frontend/clusters/agents/components/activity_history_item_spec.js
|
||||
spec/frontend/clusters/agents/components/revoke_token_button_spec.js
|
||||
spec/frontend/clusters/agents/components/show_spec.js
|
||||
spec/frontend/clusters/components/new_cluster_spec.js
|
||||
spec/frontend/clusters_list/components/delete_agent_button_spec.js
|
||||
spec/frontend/comment_templates/components/list_item_spec.js
|
||||
spec/frontend/content_editor/components/bubble_menus/media_bubble_menu_spec.js
|
||||
spec/frontend/content_editor/components/toolbar_button_spec.js
|
||||
spec/frontend/content_editor/components/wrappers/code_block_spec.js
|
||||
spec/frontend/content_editor/components/wrappers/html_comment_spec.js
|
||||
spec/frontend/content_editor/components/wrappers/image_spec.js
|
||||
spec/frontend/content_editor/components/wrappers/paragraph_spec.js
|
||||
spec/frontend/content_editor/components/wrappers/playable_spec.js
|
||||
spec/frontend/content_editor/components/wrappers/table_cell_base_spec.js
|
||||
spec/frontend/crm/crm_form_spec.js
|
||||
spec/frontend/custom_emoji/components/list_spec.js
|
||||
spec/frontend/design_management/components/design_notes/design_reply_form_spec.js
|
||||
spec/frontend/design_management/components/design_overlay_spec.js
|
||||
spec/frontend/design_management/pages/design/index_spec.js
|
||||
spec/frontend/design_management/pages/index_spec.js
|
||||
spec/frontend/design_management/router_spec.js
|
||||
spec/frontend/diffs/components/diff_line_note_form_spec.js
|
||||
spec/frontend/diffs/components/image_diff_overlay_spec.js
|
||||
spec/frontend/diffs/components/tree_list_spec.js
|
||||
spec/frontend/editor/components/source_editor_toolbar_spec.js
|
||||
spec/frontend/editor/extensions/source_editor_toolbar_ext_spec.js
|
||||
spec/frontend/error_tracking/components/error_details_spec.js
|
||||
spec/frontend/error_tracking/components/error_tracking_list_spec.js
|
||||
spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js
|
||||
spec/frontend/feature_flags/components/strategy_spec.js
|
||||
spec/frontend/gitlab_version_check/index_spec.js
|
||||
spec/frontend/glql/components/common/facade_spec.js
|
||||
spec/frontend/glql/components/presenters/link_spec.js
|
||||
spec/frontend/glql/components/presenters/list_spec.js
|
||||
spec/frontend/glql/components/presenters/table_spec.js
|
||||
spec/frontend/glql/components/presenters/text_spec.js
|
||||
spec/frontend/glql/core/presenter_spec.js
|
||||
spec/frontend/groups/components/group_name_and_path_spec.js
|
||||
spec/frontend/groups/components/overview_tabs_spec.js
|
||||
spec/frontend/groups/components/transfer_group_form_spec.js
|
||||
spec/frontend/helpers/init_simple_app_helper_spec.js
|
||||
spec/frontend/ide/components/branches/item_spec.js
|
||||
spec/frontend/ide/components/commit_sidebar/list_item_spec.js
|
||||
spec/frontend/ide/components/commit_sidebar/message_field_spec.js
|
||||
spec/frontend/ide/components/merge_requests/item_spec.js
|
||||
spec/frontend/ide/components/merge_requests/list_spec.js
|
||||
spec/frontend/ide/components/nav_dropdown_button_spec.js
|
||||
spec/frontend/ide/components/new_dropdown/index_spec.js
|
||||
spec/frontend/ide/components/shared/commit_message_field_spec.js
|
||||
spec/frontend/ide/ide_router_extension_spec.js
|
||||
spec/frontend/ide/ide_router_spec.js
|
||||
spec/frontend/ide/sync_router_and_store_spec.js
|
||||
spec/frontend/import_entities/import_projects/components/import_projects_table_spec.js
|
||||
spec/frontend/integrations/beyond_identity/components/exclusions_list_spec.js
|
||||
spec/frontend/integrations/edit/components/integration_form_spec.js
|
||||
spec/frontend/integrations/edit/components/sections/connection_spec.js
|
||||
spec/frontend/invite_members/components/members_token_select_spec.js
|
||||
spec/frontend/issuable/components/issuable_by_email_spec.js
|
||||
spec/frontend/issuable/related_issues/components/related_issues_root_spec.js
|
||||
spec/frontend/issues/dashboard/components/index_spec.js
|
||||
spec/frontend/issues/list/components/issues_list_app_spec.js
|
||||
spec/frontend/issues/service_desk/components/service_desk_list_app_spec.js
|
||||
spec/frontend/issues/show/components/app_spec.js
|
||||
spec/frontend/issues/show/components/fields/description_spec.js
|
||||
spec/frontend/issues/show/components/header_actions_spec.js
|
||||
spec/frontend/issues/show/components/incidents/create_timeline_events_form_spec.js
|
||||
spec/frontend/issues/show/components/incidents/edit_timeline_event_spec.js
|
||||
spec/frontend/issues/show/components/incidents/timeline_events_form_spec.js
|
||||
spec/frontend/issues/show/components/incidents/timeline_events_tab_spec.js
|
||||
spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js
|
||||
spec/frontend/kubernetes_dashboard/components/workload_details_item_spec.js
|
||||
spec/frontend/lib/utils/breadcrumbs_spec.js
|
||||
spec/frontend/lib/utils/confirm_via_gl_modal/confirm_action_spec.js
|
||||
spec/frontend/members/components/app_spec.js
|
||||
spec/frontend/members/components/modals/leave_modal_spec.js
|
||||
spec/frontend/members/components/table/drawer/role_details_drawer_spec.js
|
||||
spec/frontend/members/components/table/max_role_spec.js
|
||||
spec/frontend/members/components/table/members_pagination_spec.js
|
||||
spec/frontend/members/components/table/members_table_spec.js
|
||||
spec/frontend/members/placeholders/components/app_spec.js
|
||||
spec/frontend/merge_request_dashboard/components/assigned_users_spec.js
|
||||
spec/frontend/merge_requests/list/components/merge_requests_list_app_spec.js
|
||||
spec/frontend/milestones/components/milestone_combobox_spec.js
|
||||
spec/frontend/ml/experiment_tracking/routes/experiments/show/ml_experiments_show_spec.js
|
||||
spec/frontend/ml/model_registry/apps/show_ml_model_spec.js
|
||||
spec/frontend/ml/model_registry/components/candidate_detail_spec.js
|
||||
spec/frontend/ml/model_registry/components/model_edit_spec.js
|
||||
spec/frontend/ml/model_registry/components/model_version_create_spec.js
|
||||
spec/frontend/ml/model_registry/components/model_version_detail_spec.js
|
||||
spec/frontend/notebook/cells/markdown_spec.js
|
||||
spec/frontend/notebook/cells/output/html_spec.js
|
||||
spec/frontend/notes/components/discussion_notes_spec.js
|
||||
spec/frontend/notes/components/note_preview_spec.js
|
||||
spec/frontend/notes/components/notes_app_spec.js
|
||||
spec/frontend/notes/components/timeline_toggle_spec.js
|
||||
spec/frontend/notes/components/toggle_replies_widget_spec.js
|
||||
spec/frontend/organizations/groups_and_projects/components/app_spec.js
|
||||
spec/frontend/organizations/shared/components/new_edit_form_spec.js
|
||||
spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_row_spec.js
|
||||
spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js
|
||||
spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
|
||||
spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js
|
||||
spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js
|
||||
spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js
|
||||
spec/frontend/packages_and_registries/package_registry/pages/details_spec.js
|
||||
spec/frontend/packages_and_registries/settings/group/components/forwarding_settings_spec.js
|
||||
spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js
|
||||
spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js
|
||||
spec/frontend/packages_and_registries/settings/project/settings/components/container_protection_rule_form_spec.js
|
||||
spec/frontend/packages_and_registries/settings/project/settings/components/container_protection_rules_spec.js
|
||||
spec/frontend/packages_and_registries/settings/project/settings/components/packages_protection_rule_form_spec.js
|
||||
spec/frontend/packages_and_registries/settings/project/settings/components/packages_protection_rules_spec.js
|
||||
spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js
|
||||
spec/frontend/pages/import/bulk_imports/failures/index_spec.js
|
||||
spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
|
||||
spec/frontend/pages/projects/forks/new/components/project_namespace_spec.js
|
||||
spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
|
||||
spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js
|
||||
spec/frontend/pages/shared/wikis/components/delete_wiki_modal_spec.js
|
||||
spec/frontend/pages/shared/wikis/components/wiki_more_dropdown_spec.js
|
||||
spec/frontend/performance_bar/index_spec.js
|
||||
spec/frontend/pipeline_wizard/components/commit_spec.js
|
||||
spec/frontend/pipeline_wizard/components/step_spec.js
|
||||
spec/frontend/profile/preferences/components/integration_view_spec.js
|
||||
spec/frontend/profile/preferences/components/profile_preferences_spec.js
|
||||
spec/frontend/projects/commit/components/form_modal_spec.js
|
||||
spec/frontend/projects/commits/components/author_select_spec.js
|
||||
spec/frontend/projects/compare/components/revision_dropdown_spec.js
|
||||
spec/frontend/projects/components/new_edit_form_spec.js
|
||||
spec/frontend/projects/new/components/new_project_url_select_spec.js
|
||||
spec/frontend/projects/report_abuse/components/report_abuse_dropdown_item_spec.js
|
||||
spec/frontend/projects/settings/branch_rules/components/view/rule_drawer_spec.js
|
||||
spec/frontend/projects/settings/components/branch_rule_modal_spec.js
|
||||
spec/frontend/projects/settings/repository/branch_rules/app_spec.js
|
||||
spec/frontend/projects/settings/topics/components/topics_token_selector_spec.js
|
||||
spec/frontend/projects/settings_service_desk/components/custom_email_form_spec.js
|
||||
spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js
|
||||
spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
|
||||
spec/frontend/projects/your_work/components/app_spec.js
|
||||
spec/frontend/ref/components/ambiguous_ref_modal_spec.js
|
||||
spec/frontend/ref/init_ambiguous_ref_modal_spec.js
|
||||
spec/frontend/releases/components/app_edit_new_spec.js
|
||||
spec/frontend/releases/components/asset_links_form_spec.js
|
||||
spec/frontend/releases/components/tag_create_spec.js
|
||||
spec/frontend/releases/components/tag_field_exsting_spec.js
|
||||
spec/frontend/releases/components/tag_search_spec.js
|
||||
spec/frontend/repository/components/blob_controls_spec.js
|
||||
spec/frontend/repository/components/breadcrumbs_spec.js
|
||||
spec/frontend/repository/components/table/index_spec.js
|
||||
spec/frontend/repository/components/table/row_spec.js
|
||||
spec/frontend/repository/router_spec.js
|
||||
spec/frontend/right_sidebar_spec.js
|
||||
spec/frontend/search/results/components/status_bar_spec.js
|
||||
spec/frontend/search/sidebar/components/branch_dropdown_spec.js
|
||||
spec/frontend/search/sidebar/components/checkbox_filter_spec.js
|
||||
spec/frontend/search/sidebar/components/label_dropdown_items_spec.js
|
||||
spec/frontend/search/topbar/components/app_spec.js
|
||||
spec/frontend/security_configuration/components/feature_card_spec.js
|
||||
spec/frontend/sessions/new/components/email_verification_spec.js
|
||||
spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js
|
||||
spec/frontend/set_status_modal/user_profile_set_status_wrapper_spec.js
|
||||
spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
|
||||
spec/frontend/sidebar/components/confidential/confidentiality_dropdown_spec.js
|
||||
spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
|
||||
spec/frontend/sidebar/components/incidents/escalation_status_spec.js
|
||||
spec/frontend/sidebar/components/incidents/sidebar_escalation_status_spec.js
|
||||
spec/frontend/sidebar/components/labels/labels_select_vue/dropdown_contents_labels_view_spec.js
|
||||
spec/frontend/sidebar/components/labels/labels_select_vue/labels_select_root_spec.js
|
||||
spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_spec.js
|
||||
spec/frontend/sidebar/components/lock/issuable_lock_form_spec.js
|
||||
spec/frontend/sidebar/components/milestone/milestone_dropdown_spec.js
|
||||
spec/frontend/sidebar/components/subscriptions/subscriptions_dropdown_spec.js
|
||||
spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js
|
||||
spec/frontend/silent_mode_settings/components/app_spec.js
|
||||
spec/frontend/snippets/components/snippet_header_spec.js
|
||||
spec/frontend/super_sidebar/components/flyout_menu_spec.js
|
||||
spec/frontend/super_sidebar/components/global_search/components/frequent_items_spec.js
|
||||
spec/frontend/super_sidebar/components/nav_item_router_link_spec.js
|
||||
spec/frontend/super_sidebar/components/organization_switcher_spec.js
|
||||
spec/frontend/super_sidebar/components/sidebar_hover_peek_behavior_spec.js
|
||||
spec/frontend/super_sidebar/components/sidebar_peek_behavior_spec.js
|
||||
spec/frontend/super_sidebar/components/sidebar_portal_spec.js
|
||||
spec/frontend/super_sidebar/components/super_sidebar_spec.js
|
||||
spec/frontend/super_sidebar/components/user_menu_spec.js
|
||||
spec/frontend/tags/components/delete_tag_modal_spec.js
|
||||
spec/frontend/tags/init_delete_tag_modal_spec.js
|
||||
spec/frontend/tooltips/components/tooltips_spec.js
|
||||
spec/frontend/tooltips/index_spec.js
|
||||
spec/frontend/usage_quotas/storage/components/container_registry_usage_spec.js
|
||||
spec/frontend/usage_quotas/storage/components/namespace_storage_app_spec.js
|
||||
spec/frontend/users/profile/actions/components/user_actions_app_spec.js
|
||||
spec/frontend/users_select/index_spec.js
|
||||
spec/frontend/vue_alerts_spec.js
|
||||
spec/frontend/vue_merge_request_widget/components/checks/conflicts_spec.js
|
||||
spec/frontend/vue_merge_request_widget/components/merge_checks_spec.js
|
||||
spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js
|
||||
spec/frontend/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js
|
||||
spec/frontend/vue_merge_request_widget/components/states/mr_widget_merging_spec.js
|
||||
spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js
|
||||
spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js
|
||||
spec/frontend/vue_popovers_spec.js
|
||||
spec/frontend/vue_shared/components/alert_details_table_spec.js
|
||||
spec/frontend/vue_shared/components/badges/beta_badge_spec.js
|
||||
spec/frontend/vue_shared/components/chronic_duration_input_spec.js
|
||||
spec/frontend/vue_shared/components/color_picker/color_picker_spec.js
|
||||
spec/frontend/vue_shared/components/color_select_dropdown/dropdown_contents_spec.js
|
||||
spec/frontend/vue_shared/components/confirm_modal_spec.js
|
||||
spec/frontend/vue_shared/components/design_management/design_note_pin_spec.js
|
||||
spec/frontend/vue_shared/components/diff_stats_dropdown_spec.js
|
||||
spec/frontend/vue_shared/components/file_finder/index_spec.js
|
||||
spec/frontend/vue_shared/components/file_tree_spec.js
|
||||
spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
|
||||
spec/frontend/vue_shared/components/filtered_search_bar/tokens/date_token_spec.js
|
||||
spec/frontend/vue_shared/components/filtered_search_bar/tokens/user_token_spec.js
|
||||
spec/frontend/vue_shared/components/gl_modal_vuex_spec.js
|
||||
spec/frontend/vue_shared/components/list_selector/group_item_spec.js
|
||||
spec/frontend/vue_shared/components/list_selector/user_item_spec.js
|
||||
spec/frontend/vue_shared/components/markdown/header_spec.js
|
||||
spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js
|
||||
spec/frontend/vue_shared/components/markdown/suggestion_diff_row_spec.js
|
||||
spec/frontend/vue_shared/components/markdown_drawer/markdown_drawer_spec.js
|
||||
spec/frontend/vue_shared/components/metric_images/metric_image_details_modal_spec.js
|
||||
spec/frontend/vue_shared/components/notes/noteable_warning_spec.js
|
||||
spec/frontend/vue_shared/components/page_heading_spec.js
|
||||
spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
|
||||
spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
|
||||
spec/frontend/vue_shared/components/registry/registry_search_spec.js
|
||||
spec/frontend/vue_shared/components/runner_instructions/instructions/runner_aws_instructions_spec.js
|
||||
spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
|
||||
spec/frontend/vue_shared/components/segmented_control_button_group_spec.js
|
||||
spec/frontend/vue_shared/components/slot_switch_spec.js
|
||||
spec/frontend/vue_shared/components/smart_virtual_list_spec.js
|
||||
spec/frontend/vue_shared/components/source_viewer/components/chunk_spec.js
|
||||
spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
|
||||
spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
|
||||
spec/frontend/vue_shared/directives/tooltip_on_truncate_spec.js
|
||||
spec/frontend/vue_shared/directives/track_event_spec.js
|
||||
spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js
|
||||
spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js
|
||||
spec/frontend/webhooks/components/form_custom_headers_spec.js
|
||||
spec/frontend/webhooks/components/form_url_app_spec.js
|
||||
spec/frontend/work_items/components/design_management/design_preview/design_overlay_spec.js
|
||||
spec/frontend/work_items/components/work_item_description_rendered_spec.js
|
||||
spec/frontend/work_items/router_spec.js
|
||||
|
|
@ -1,25 +1,25 @@
|
|||
const { relative } = require('node:path');
|
||||
const { readFile } = require('node:fs/promises');
|
||||
const { relative, join } = require('node:path');
|
||||
const { setTimeout: setTimeoutPromise } = require('node:timers/promises');
|
||||
const axios = require('axios');
|
||||
const FixtureCISequencer = require('./fixture_ci_sequencer');
|
||||
|
||||
const url = 'https://gitlab-org.gitlab.io/frontend/playground/jest-speed-reporter/vue3.json';
|
||||
const url =
|
||||
'https://gitlab-org.gitlab.io/frontend/playground/fast-jest-vue-3-quarantine/gitlab.txt';
|
||||
|
||||
// These fail due to template compilation errors, so aren't recorded in the
|
||||
// JUnit report that the Jest Speed Reporter project consumes. We must explicitly
|
||||
// exclude them until this is solved.
|
||||
// See https://gitlab.com/gitlab-org/gitlab/-/issues/478773.
|
||||
const SPECS_THAT_FAIL_TO_COMPILE = [
|
||||
'spec/frontend/boards/components/board_app_spec.js',
|
||||
'ee/spec/frontend/boards/components/board_app_spec.js',
|
||||
'spec/frontend/boards/components/board_content_spec.js',
|
||||
'ee/spec/frontend/boards/components/board_content_spec.js',
|
||||
];
|
||||
function parse(quarantineFileContent) {
|
||||
return quarantineFileContent
|
||||
.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line && !line.startsWith('#'));
|
||||
}
|
||||
|
||||
async function getFailedFilesAsAbsolutePaths(n = 0, maxRetries = 3) {
|
||||
// See https://gitlab.com/gitlab-org/frontend/playground/fast-jest-vue-3-quarantine for details
|
||||
// about how to fast quarantine files.
|
||||
async function getFastQuarantinedFiles(n = 0, maxRetries = 3) {
|
||||
try {
|
||||
const { data } = await axios.get(url, { timeout: 10_000 });
|
||||
return new Set([...data.failedFiles, ...SPECS_THAT_FAIL_TO_COMPILE]);
|
||||
return parse(data);
|
||||
} catch (error) {
|
||||
console.error('\nFailed to fetch list of specs failing with @vue/compat: %s', error.message);
|
||||
|
||||
|
|
@ -27,24 +27,40 @@ async function getFailedFilesAsAbsolutePaths(n = 0, maxRetries = 3) {
|
|||
const waitMs = 5_000 * 2 ** n;
|
||||
console.error(`Waiting ${waitMs}ms to retry (${maxRetries - n} remaining)`);
|
||||
await setTimeoutPromise(waitMs);
|
||||
return getFailedFilesAsAbsolutePaths(n + 1);
|
||||
return getFastQuarantinedFiles(n + 1);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function getLocalQuarantinedFiles() {
|
||||
const content = await readFile(join(__dirname, 'quarantined_vue3_specs.txt'), {
|
||||
encoding: 'UTF-8',
|
||||
});
|
||||
|
||||
return parse(content);
|
||||
}
|
||||
|
||||
async function getQuarantinedFiles() {
|
||||
const results = await Promise.all([getFastQuarantinedFiles(), getLocalQuarantinedFiles()]);
|
||||
return new Set(results.flat());
|
||||
}
|
||||
|
||||
class SkipSpecsBrokenInVueCompatFixtureCISequencer extends FixtureCISequencer {
|
||||
#failedSpecFilesPromise = getFailedFilesAsAbsolutePaths();
|
||||
#quarantinedFiles = getQuarantinedFiles();
|
||||
|
||||
async shard(tests, options) {
|
||||
const failedSpecFiles = await this.#failedSpecFilesPromise;
|
||||
|
||||
const testsExcludingOnesThatFailInVueCompat = tests.filter(
|
||||
(test) => !failedSpecFiles.has(relative(test.context.config.rootDir, test.path)),
|
||||
const quarantinedFiles = await this.#quarantinedFiles;
|
||||
console.warn(
|
||||
`Skipping ${quarantinedFiles.size} quarantined specs:\n${[...quarantinedFiles].join('\n')}`,
|
||||
);
|
||||
|
||||
return super.shard(testsExcludingOnesThatFailInVueCompat, options);
|
||||
const testsExcludingQuarantined = tests.filter(
|
||||
(test) => !quarantinedFiles.has(relative(test.context.config.rootDir, test.path)),
|
||||
);
|
||||
|
||||
return super.shard(testsExcludingQuarantined, options);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -130,36 +130,55 @@ describe('IssuesDashboardApp component', () => {
|
|||
await waitForPromises();
|
||||
});
|
||||
|
||||
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/391722
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('renders IssuableList component', () => {
|
||||
expect(findIssuableList().props()).toMatchObject({
|
||||
currentTab: STATUS_OPEN,
|
||||
hasNextPage: true,
|
||||
hasPreviousPage: false,
|
||||
hasScopedLabelsFeature: defaultProvide.hasScopedLabelsFeature,
|
||||
initialSortBy: CREATED_DESC,
|
||||
issuables: issuesQueryResponse.data.issues.nodes,
|
||||
issuablesLoading: false,
|
||||
namespace: 'dashboard',
|
||||
recentSearchesStorageKey: 'issues',
|
||||
showPaginationControls: true,
|
||||
sortOptions: getSortOptions({
|
||||
hasBlockedIssuesFeature: defaultProvide.hasBlockedIssuesFeature,
|
||||
hasIssuableHealthStatusFeature: defaultProvide.hasIssuableHealthStatusFeature,
|
||||
hasIssueWeightsFeature: defaultProvide.hasIssueWeightsFeature,
|
||||
}),
|
||||
tabCounts: {
|
||||
describe('IssuableList component', () => {
|
||||
it('renders', () => {
|
||||
expect(findIssuableList().props()).toMatchObject({
|
||||
currentTab: STATUS_OPEN,
|
||||
hasNextPage: true,
|
||||
hasPreviousPage: false,
|
||||
hasScopedLabelsFeature: true,
|
||||
initialSortBy: CREATED_DESC,
|
||||
namespace: 'dashboard',
|
||||
recentSearchesStorageKey: 'issues',
|
||||
showPaginationControls: true,
|
||||
showWorkItemTypeIcon: true,
|
||||
truncateCounts: true,
|
||||
useKeysetPagination: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('renders issues', () => {
|
||||
expect(findIssuableList().props('issuables')).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('renders sort options', () => {
|
||||
expect(findIssuableList().props('sortOptions')).toEqual(
|
||||
getSortOptions({
|
||||
hasBlockedIssuesFeature: defaultProvide.hasBlockedIssuesFeature,
|
||||
hasIssuableHealthStatusFeature: defaultProvide.hasIssuableHealthStatusFeature,
|
||||
hasIssueWeightsFeature: defaultProvide.hasIssueWeightsFeature,
|
||||
hasManualSort: false,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('renders tabs', () => {
|
||||
expect(findIssuableList().props('tabs')).toEqual(IssuesDashboardApp.issuableListTabs);
|
||||
});
|
||||
|
||||
it('renders tab counts', () => {
|
||||
expect(findIssuableList().props('tabCounts')).toEqual({
|
||||
opened: 1,
|
||||
closed: 2,
|
||||
all: 3,
|
||||
},
|
||||
tabs: IssuesDashboardApp.issuableListTabs,
|
||||
urlParams: {
|
||||
});
|
||||
});
|
||||
|
||||
it('renders url params', () => {
|
||||
expect(findIssuableList().props('urlParams')).toMatchObject({
|
||||
sort: urlSortParams[CREATED_DESC],
|
||||
state: STATUS_OPEN,
|
||||
},
|
||||
useKeysetPagination: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {
|
|||
TODO_ACTION_TYPE_REVIEW_SUBMITTED,
|
||||
TODO_ACTION_TYPE_UNMERGEABLE,
|
||||
TODO_ACTION_TYPE_SSH_KEY_EXPIRED,
|
||||
TODO_ACTION_TYPE_SSH_KEY_EXPIRING_SOON,
|
||||
} from '~/todos/constants';
|
||||
|
||||
describe('TodoItemBody', () => {
|
||||
|
|
@ -59,21 +60,22 @@ describe('TodoItemBody', () => {
|
|||
|
||||
describe('correct text for actionName', () => {
|
||||
it.each`
|
||||
actionName | text | showsAuthor
|
||||
${TODO_ACTION_TYPE_ADDED_APPROVER} | ${'set you as an approver.'} | ${true}
|
||||
${TODO_ACTION_TYPE_APPROVAL_REQUIRED} | ${'set you as an approver.'} | ${true}
|
||||
${TODO_ACTION_TYPE_ASSIGNED} | ${'assigned you.'} | ${true}
|
||||
${TODO_ACTION_TYPE_BUILD_FAILED} | ${'The pipeline failed.'} | ${false}
|
||||
${TODO_ACTION_TYPE_DIRECTLY_ADDRESSED} | ${'mentioned you.'} | ${true}
|
||||
${TODO_ACTION_TYPE_MARKED} | ${'added a to-do item'} | ${true}
|
||||
${TODO_ACTION_TYPE_MEMBER_ACCESS_REQUESTED} | ${'has requested access to'} | ${true}
|
||||
${TODO_ACTION_TYPE_MENTIONED} | ${'mentioned you.'} | ${true}
|
||||
${TODO_ACTION_TYPE_MERGE_TRAIN_REMOVED} | ${'Removed from Merge Train.'} | ${false}
|
||||
${TODO_ACTION_TYPE_OKR_CHECKIN_REQUESTED} | ${'requested an OKR update for'} | ${true}
|
||||
${TODO_ACTION_TYPE_REVIEW_REQUESTED} | ${'requested a review.'} | ${true}
|
||||
${TODO_ACTION_TYPE_REVIEW_SUBMITTED} | ${'reviewed your merge request.'} | ${true}
|
||||
${TODO_ACTION_TYPE_UNMERGEABLE} | ${'Could not merge.'} | ${false}
|
||||
${TODO_ACTION_TYPE_SSH_KEY_EXPIRED} | ${'Your SSH key has expired.'} | ${false}
|
||||
actionName | text | showsAuthor
|
||||
${TODO_ACTION_TYPE_ADDED_APPROVER} | ${'set you as an approver.'} | ${true}
|
||||
${TODO_ACTION_TYPE_APPROVAL_REQUIRED} | ${'set you as an approver.'} | ${true}
|
||||
${TODO_ACTION_TYPE_ASSIGNED} | ${'assigned you.'} | ${true}
|
||||
${TODO_ACTION_TYPE_BUILD_FAILED} | ${'The pipeline failed.'} | ${false}
|
||||
${TODO_ACTION_TYPE_DIRECTLY_ADDRESSED} | ${'mentioned you.'} | ${true}
|
||||
${TODO_ACTION_TYPE_MARKED} | ${'added a to-do item'} | ${true}
|
||||
${TODO_ACTION_TYPE_MEMBER_ACCESS_REQUESTED} | ${'has requested access to'} | ${true}
|
||||
${TODO_ACTION_TYPE_MENTIONED} | ${'mentioned you.'} | ${true}
|
||||
${TODO_ACTION_TYPE_MERGE_TRAIN_REMOVED} | ${'Removed from Merge Train.'} | ${false}
|
||||
${TODO_ACTION_TYPE_OKR_CHECKIN_REQUESTED} | ${'requested an OKR update for'} | ${true}
|
||||
${TODO_ACTION_TYPE_REVIEW_REQUESTED} | ${'requested a review.'} | ${true}
|
||||
${TODO_ACTION_TYPE_REVIEW_SUBMITTED} | ${'reviewed your merge request.'} | ${true}
|
||||
${TODO_ACTION_TYPE_UNMERGEABLE} | ${'Could not merge.'} | ${false}
|
||||
${TODO_ACTION_TYPE_SSH_KEY_EXPIRED} | ${'Your SSH key has expired.'} | ${false}
|
||||
${TODO_ACTION_TYPE_SSH_KEY_EXPIRING_SOON} | ${'Your SSH key is expiring soon.'} | ${false}
|
||||
`('renders "$text" for the "$actionName" action', ({ actionName, text, showsAuthor }) => {
|
||||
createComponent({ action: actionName });
|
||||
expect(wrapper.text()).toContain(text);
|
||||
|
|
|
|||
|
|
@ -368,6 +368,7 @@ RSpec.describe TodosHelper do
|
|||
Todo::MERGE_TRAIN_REMOVED | true | s_("Todos|Removed from Merge Train")
|
||||
Todo::REVIEW_SUBMITTED | false | s_('Todos|reviewed your merge request')
|
||||
Todo::SSH_KEY_EXPIRED | true | s_('Todos|Your SSH key has expired')
|
||||
Todo::SSH_KEY_EXPIRING_SOON | true | s_('Todos|Your SSH key is expiring soon')
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::BackgroundMigration::BackfillDependencyProxyBlobStatesGroupId,
|
||||
feature_category: :geo_replication,
|
||||
schema: 20241015075953 do
|
||||
include_examples 'desired sharding key backfill job' do
|
||||
let(:batch_table) { :dependency_proxy_blob_states }
|
||||
let(:backfill_column) { :group_id }
|
||||
let(:batch_column) { :dependency_proxy_blob_id }
|
||||
let(:backfill_via_table) { :dependency_proxy_blobs }
|
||||
let(:backfill_via_column) { :group_id }
|
||||
let(:backfill_via_foreign_key) { :dependency_proxy_blob_id }
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe QueueBackfillDependencyProxyBlobStatesGroupId, feature_category: :geo_replication do
|
||||
let!(:batched_migration) { described_class::MIGRATION }
|
||||
|
||||
it 'schedules a new batched migration' do
|
||||
reversible_migration do |migration|
|
||||
migration.before -> {
|
||||
expect(batched_migration).not_to have_scheduled_batched_migration
|
||||
}
|
||||
|
||||
migration.after -> {
|
||||
expect(batched_migration).to have_scheduled_batched_migration(
|
||||
table_name: :dependency_proxy_blob_states,
|
||||
column_name: :dependency_proxy_blob_id,
|
||||
interval: described_class::DELAY_INTERVAL,
|
||||
batch_size: described_class::BATCH_SIZE,
|
||||
sub_batch_size: described_class::SUB_BATCH_SIZE,
|
||||
gitlab_schema: :gitlab_main_cell,
|
||||
job_arguments: [
|
||||
:group_id,
|
||||
:dependency_proxy_blobs,
|
||||
:group_id,
|
||||
:dependency_proxy_blob_id
|
||||
]
|
||||
)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe BackfillNullProjectOnCiStagesRecords, migration: :gitlab_ci, feature_category: :database do
|
||||
let(:pipelines_table) { table(:p_ci_pipelines, primary_key: :id, database: :ci) }
|
||||
let(:stages_table) { table(:p_ci_stages, primary_key: :id, database: :ci) }
|
||||
|
||||
let!(:pipeline_with_project) { pipelines_table.create!(project_id: 42, partition_id: 100) }
|
||||
let!(:stage_to_be_backfilled) do
|
||||
stages_table.create!(name: 'backfilled', pipeline_id: pipeline_with_project.id, partition_id: 100)
|
||||
end
|
||||
|
||||
let!(:stage_with_project_id) { stages_table.create!(name: 'standard', project_id: 11, partition_id: 100) }
|
||||
let!(:stage_orphaned) { stages_table.create!(name: 'deleted', partition_id: 100) }
|
||||
|
||||
describe '#up' do
|
||||
it 'backfills applicable records' do
|
||||
expect { migrate! }
|
||||
.to change { stage_to_be_backfilled.reload.project_id }.from(nil).to(pipeline_with_project.project_id)
|
||||
.and not_change { stage_with_project_id.reload.project_id }.from(11)
|
||||
end
|
||||
|
||||
it 'deletes orphaned records' do
|
||||
expect { migrate! }.to change { stages_table.count }.by(-1)
|
||||
|
||||
expect { stage_orphaned.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -552,6 +552,18 @@ RSpec.describe Todo, feature_category: :team_planning do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.pending_for_expiring_ssh_keys' do
|
||||
it 'returns only todos matching the given key ids' do
|
||||
todo1 = create(:todo, target_type: Key, target_id: 1, action: described_class::SSH_KEY_EXPIRING_SOON, state: :pending)
|
||||
todo2 = create(:todo, target_type: Key, target_id: 2, action: described_class::SSH_KEY_EXPIRING_SOON, state: :pending)
|
||||
create(:todo, target_type: Key, target_id: 3, action: described_class::SSH_KEY_EXPIRING_SOON, state: :done)
|
||||
create(:todo, target_type: Issue, target_id: 1, action: described_class::ASSIGNED, state: :pending)
|
||||
todos = described_class.pending_for_expiring_ssh_keys([1, 2, 3])
|
||||
|
||||
expect(todos).to contain_exactly(todo1, todo2)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.for_user' do
|
||||
it 'returns the expected todos' do
|
||||
user1 = create(:user)
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ RSpec.describe Keys::ExpiryNotificationService, feature_category: :source_code_m
|
|||
let(:expiring_soon) { true }
|
||||
|
||||
context 'when user has permission to receive notification' do
|
||||
it_behaves_like 'creates todo'
|
||||
it_behaves_like 'sends a notification'
|
||||
|
||||
it_behaves_like 'uses notification service to send email to the user', :ssh_key_expiring_soon
|
||||
|
|
@ -108,11 +109,20 @@ RSpec.describe Keys::ExpiryNotificationService, feature_category: :source_code_m
|
|||
it 'updates notified column' do
|
||||
expect { subject.execute }.to change { key.reload.before_expiry_notification_delivered_at }
|
||||
end
|
||||
|
||||
context 'when derisk feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(todos_for_ssh_key_expiry: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'does not create todo'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user does NOT have permission to receive notification' do
|
||||
include_context 'block user'
|
||||
|
||||
it_behaves_like 'does not create todo'
|
||||
it_behaves_like 'does not send notification'
|
||||
|
||||
it 'does not update notified column' do
|
||||
|
|
|
|||
|
|
@ -1121,6 +1121,31 @@ RSpec.describe TodoService, feature_category: :team_planning do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#ssh_key_expiring_soon' do
|
||||
let_it_be(:ssh_key) { create(:key, user: author) }
|
||||
|
||||
context 'when given a single key' do
|
||||
it 'creates a pending todo for the user' do
|
||||
service.ssh_key_expiring_soon(ssh_key)
|
||||
|
||||
should_create_todo(user: author, author: author, target: ssh_key, project: nil, action: Todo::SSH_KEY_EXPIRING_SOON)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when given an array of keys' do
|
||||
let_it_be(:ssh_key_of_member) { create(:key, user: member) }
|
||||
let_it_be(:ssh_key_of_guest) { create(:key, user: guest) }
|
||||
|
||||
it 'creates a pending todo for each key with the correct user' do
|
||||
service.ssh_key_expiring_soon([ssh_key, ssh_key_of_member, ssh_key_of_guest])
|
||||
|
||||
should_create_todo(user: author, author: author, target: ssh_key, project: nil, action: Todo::SSH_KEY_EXPIRING_SOON)
|
||||
should_create_todo(user: member, author: member, target: ssh_key_of_member, project: nil, action: Todo::SSH_KEY_EXPIRING_SOON)
|
||||
should_create_todo(user: guest, author: guest, target: ssh_key_of_guest, project: nil, action: Todo::SSH_KEY_EXPIRING_SOON)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#ssh_key_expired' do
|
||||
let_it_be(:ssh_key) { create(:key, user: author) }
|
||||
|
||||
|
|
@ -1144,6 +1169,24 @@ RSpec.describe TodoService, feature_category: :team_planning do
|
|||
should_create_todo(user: guest, author: guest, target: ssh_key_of_guest, project: nil, action: Todo::SSH_KEY_EXPIRED)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'auto-resolve behavior' do
|
||||
let_it_be(:ssh_key_2) { create(:key, user: author) }
|
||||
let_it_be(:todo_for_expiring_key_1) { create(:todo, target: ssh_key, action: Todo::SSH_KEY_EXPIRING_SOON, user: author) }
|
||||
let_it_be(:todo_for_expiring_key_2) { create(:todo, target: ssh_key_2, action: Todo::SSH_KEY_EXPIRING_SOON, user: author) }
|
||||
|
||||
it 'resolves the "expiring soon" todo for the same key' do
|
||||
service.ssh_key_expired(ssh_key)
|
||||
|
||||
expect(todo_for_expiring_key_1.reload.state).to eq 'done'
|
||||
end
|
||||
|
||||
it 'does not resolve "expiring soon" todos of other keys' do
|
||||
service.ssh_key_expired(ssh_key)
|
||||
|
||||
expect(todo_for_expiring_key_2.state).to eq 'pending'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#merge_request_build_failed' do
|
||||
|
|
|
|||
|
|
@ -24,6 +24,24 @@ RSpec.describe Ci::CancelRedundantPipelinesWorker, feature_category: :continuous
|
|||
perform
|
||||
end
|
||||
|
||||
context 'with a passed partition_id' do
|
||||
subject(:perform) { described_class.new.perform(pipeline.id, { 'partition_id' => pipeline.partition_id }) }
|
||||
|
||||
it 'finds the passed pipeline in the correct partition and passes it to the service' do
|
||||
expect(Ci::PipelineCreation::CancelRedundantPipelinesService)
|
||||
.to receive(:new)
|
||||
.with(pipeline)
|
||||
.and_return(service)
|
||||
|
||||
expect(service).to receive(:execute)
|
||||
|
||||
recorder = ActiveRecord::QueryRecorder.new { perform }
|
||||
|
||||
expect(recorder.count).to eq(1)
|
||||
expect(recorder.log.first).to match(/^SELECT "ci_pipelines".*"partition_id" = #{pipeline.partition_id}/)
|
||||
end
|
||||
end
|
||||
|
||||
context 'if pipeline is deleted' do
|
||||
subject(:perform) { described_class.new.perform(non_existing_record_id) }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue