Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-10-16 15:19:00 +00:00
parent b837b7fc8d
commit 8fe70401f0
50 changed files with 1308 additions and 109 deletions

View File

@ -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:

View File

@ -354,6 +354,7 @@ export default {
hasBlockedIssuesFeature: this.hasBlockedIssuesFeature,
hasIssuableHealthStatusFeature: this.hasIssuableHealthStatusFeature,
hasIssueWeightsFeature: this.hasIssueWeightsFeature,
hasManualSort: false,
});
},
tabCounts() {

View File

@ -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: {

View File

@ -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}`),

View File

@ -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 = {

View File

@ -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"),

View File

@ -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

View File

@ -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

View File

@ -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`.

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
fd3f1a27204fe2952e2f83a94f92737edfd1ff7b446e5db98b052bb03e3373d3

View File

@ -0,0 +1 @@
bd0cac7a4cd41fad0dfdf2959f52ad3d2fb37563df9bb5ac3c5ab2c1c592f9d3

View File

@ -0,0 +1 @@
be10cd330779b21118c96f3e940e3632e8d79566eeb38af0c9118c0ab8507102

View File

@ -0,0 +1 @@
e384696ed03e4ddb5b88941cf0141cb9793c66eebcb6892e1cee3ed1225201aa

View File

@ -0,0 +1 @@
33ad1996ec23c69a5295ab18b7ba1b986e4d1f3e05de123178e5c864e531fb6b

View File

@ -0,0 +1 @@
bad4fab793a81707348b46027bee797eaa641ddb71e17d1c22950887dc590d2e

View File

@ -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;

View File

@ -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).

View File

@ -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

View File

@ -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`

View File

@ -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.

View File

@ -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>
```

View File

@ -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

View File

@ -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

View File

@ -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 ""

View File

@ -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?

View File

@ -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

View File

@ -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

View File

@ -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);
}
}

View File

@ -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,
});
});
});

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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) }