diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index 63e52067421..383c3a6f39b 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -343,44 +343,6 @@
- name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.9
alias: zoekt-ci-image
-.ai-gateway-variables:
- variables:
- AIGW_AUTH__BYPASS_EXTERNAL: true
- AIGW_GOOGLE_CLOUD_PLATFORM__PROJECT: $VERTEX_AI_PROJECT
- AIGW_GOOGLE_CLOUD_PLATFORM__SERVICE_ACCOUNT_JSON_KEY: $VERTEX_AI_CREDENTIALS
- AIGW_FASTAPI__DOCS_URL: "/docs"
- AIGW_FASTAPI__OPENAPI_URL: "/openapi.json"
- AIGW_FASTAPI__API_PORT: 5052
- ANTHROPIC_API_KEY: $ANTHROPIC_API_KEY_FOR_SERVICE
- # CI_DEBUG_SERVICES: "true" # Enable this variable when you debug ai-gateway boot failure.
-
-.ai-gateway-services:
- services:
- - name: registry.gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/model-gateway:v1.18.0
- alias: ai-gateway
-
-.litellm-proxy-variables:
- variables:
- LITELLM_CONFIG_CONTENT: |
- model_list:
- - model_name: codestral
- litellm_params:
- model: ollama/codestral
- mock_response: "Mock response from codestral"
- - model_name: mistral
- litellm_params:
- model: ollama/mistral
- mock_response: "Mock response from mistral"
-
-.litellm-proxy-services:
- services:
- - name: ghcr.io/berriai/litellm:main-latest
- alias: litellm-proxy
- entrypoint: ["/bin/sh", "-c"]
- command:
- - |
- mkdir -p /tmp && echo "${LITELLM_CONFIG_CONTENT}" > /tmp/config.yaml && litellm --config /tmp/config.yaml
-
.use-pg14:
extends:
- .pg-base-variables
@@ -431,13 +393,9 @@
extends:
- .use-pg14
- .zoekt-variables
- - .ai-gateway-variables
- - .litellm-proxy-variables
services:
- !reference [.db-services-with-auto-explain, services]
- !reference [.es7-services, services]
- - !reference [.ai-gateway-services, services]
- - !reference [.litellm-proxy-services, services]
.use-pg15-es7-ee:
extends:
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 1341e9a3462..e2d3008a6b9 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -895,21 +895,6 @@ rspec-ee integration pg16 single-db-sec-connection:
- .rspec-ee-integration-parallel
- .rails:rules:single-db-sec-connection-ee
-.custom-models-variables:
- variables:
- AIGW_CUSTOM_MODELS__ENABLED: true
- AI_GATEWAY_URL: http://ai-gateway:5052
- LITELLM_PROXY_URL: http://litellm-proxy:4000
-
-rspec-ee system custom-models pg16:
- extends:
- - .rspec-ee-base-pg16
- - .rails:rules:ee-only-system
- - .custom-models-variables
- script:
- - !reference [.base-script, script]
- - rspec_parallelized_job "--tag requires_custom_models_setup"
-
rspec-ee system pg16:
extends:
- .rspec-ee-base-pg16
@@ -1224,7 +1209,7 @@ rspec-ee system pg17:
stage: test
script:
- !reference [.base-script, script]
- - rspec_section rspec_fail_fast "${MATCHING_TESTS_PATH}" "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~zoekt --tag ~click_house --tag ~real_ai_request"
+ - rspec_section rspec_fail_fast "${MATCHING_TESTS_PATH}" "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~zoekt --tag ~click_house"
rspec fail-fast:
extends:
diff --git a/.gitlab/ci/rails/shared.gitlab-ci.yml b/.gitlab/ci/rails/shared.gitlab-ci.yml
index c2f82a735b2..5c37ef4870d 100644
--- a/.gitlab/ci/rails/shared.gitlab-ci.yml
+++ b/.gitlab/ci/rails/shared.gitlab-ci.yml
@@ -107,7 +107,7 @@ include:
# spec/lib, yet background migration tests are also sitting there,
# and they should run on their own jobs so we don't need to run them
# in unit tests again.
- - rspec_section rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~level:background_migration --tag ~click_house --tag ~real_ai_request"
+ - rspec_section rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~level:background_migration --tag ~click_house"
after_script:
- source scripts/utils.sh
- log_disk_usage # https://gitlab.com/gitlab-org/gitlab/-/issues/478880
@@ -205,7 +205,7 @@ include:
.rspec-base-migration:
script:
- !reference [.base-script, script]
- - rspec_section rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~zoekt --tag ~click_house --tag ~real_ai_request"
+ - rspec_section rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~zoekt --tag ~click_house"
after_script:
- !reference [.rspec-base, after_script]
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 80863db629f..69aa6aa3657 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -2384,36 +2384,6 @@
- <<: *if-default-refs
changes: *code-backstage-patterns
-.rails:rules:ee-gitlab-duo-chat-base:
- rules:
- - !reference [".strict-ee-only-rules", rules]
- - if: '$ANTHROPIC_API_KEY == null'
- when: never
- - <<: *if-fork-merge-request
- when: never
-
-.rails:rules:ee-gitlab-duo-chat-optional:
- rules:
- - !reference [".rails:rules:ee-gitlab-duo-chat-base", rules]
- - <<: *if-merge-request
- changes: *backend-patterns
- when: never
- allow_failure: true
-
-.rails:rules:ee-gitlab-duo-chat-always:
- rules:
- - !reference [".rails:rules:ee-gitlab-duo-chat-base", rules]
- - <<: *if-merge-request
- changes: *ai-patterns
-
-.rails:rules:ee-gitlab-duo-chat-qa-full:
- rules:
- - !reference [".rails:rules:ee-gitlab-duo-chat-optional", rules]
- - <<: *if-default-branch-refs
- changes: *setup-test-env-patterns
- when: never
- allow_failure: true
-
.rails:rules:db:check-schema:
rules:
- <<: *if-not-ee
diff --git a/.rubocop_todo/gitlab/feature_flag_without_actor.yml b/.rubocop_todo/gitlab/feature_flag_without_actor.yml
index 80e79892c36..d052a6d0cb4 100644
--- a/.rubocop_todo/gitlab/feature_flag_without_actor.yml
+++ b/.rubocop_todo/gitlab/feature_flag_without_actor.yml
@@ -149,7 +149,6 @@ Gitlab/FeatureFlagWithoutActor:
- 'lib/gitlab/git/diff.rb'
- 'lib/gitlab/git/repository.rb'
- 'lib/gitlab/git/user.rb'
- - 'lib/gitlab/grape_logging/loggers/response_logger.rb'
- 'lib/gitlab/internal_events.rb'
- 'lib/gitlab/lograge/custom_options.rb'
- 'lib/gitlab/memory/reports/heap_dump.rb'
diff --git a/.rubocop_todo/layout/line_end_string_concatenation_indentation.yml b/.rubocop_todo/layout/line_end_string_concatenation_indentation.yml
index f8420befaf8..e543c5fff18 100644
--- a/.rubocop_todo/layout/line_end_string_concatenation_indentation.yml
+++ b/.rubocop_todo/layout/line_end_string_concatenation_indentation.yml
@@ -306,7 +306,6 @@ Layout/LineEndStringConcatenationIndentation:
- 'ee/spec/services/protected_environments/update_service_spec.rb'
- 'ee/spec/services/security/security_orchestration_policies/ci_action/template_spec.rb'
- 'ee/spec/services/security/token_revocation_service_spec.rb'
- - 'ee/spec/support/llm.rb'
- 'ee/spec/support/shared_examples/lib/gitlab/llm/chain/slash_command_tool_shared_examples.rb'
- 'ee/spec/support/shared_examples/requests/api/graphql/ci/queueing_history_shared_examples.rb'
- 'ee/spec/support/shared_examples/requests/identity_verification_shared_examples.rb'
diff --git a/.rubocop_todo/rspec/feature_category.yml b/.rubocop_todo/rspec/feature_category.yml
index 2adb29399b6..be7e73a23b6 100644
--- a/.rubocop_todo/rspec/feature_category.yml
+++ b/.rubocop_todo/rspec/feature_category.yml
@@ -2498,7 +2498,6 @@ RSpec/FeatureCategory:
- 'spec/lib/gitlab/grape_logging/loggers/filter_parameters_spec.rb'
- 'spec/lib/gitlab/grape_logging/loggers/perf_logger_spec.rb'
- 'spec/lib/gitlab/grape_logging/loggers/queue_duration_logger_spec.rb'
- - 'spec/lib/gitlab/grape_logging/loggers/response_logger_spec.rb'
- 'spec/lib/gitlab/grape_logging/loggers/token_logger_spec.rb'
- 'spec/lib/gitlab/grape_logging/loggers/urgency_logger_spec.rb'
- 'spec/lib/gitlab/graphql/authorize/authorize_resource_spec.rb'
diff --git a/.rubocop_todo/rspec/named_subject.yml b/.rubocop_todo/rspec/named_subject.yml
index c3a217604a2..9adc0303f5f 100644
--- a/.rubocop_todo/rspec/named_subject.yml
+++ b/.rubocop_todo/rspec/named_subject.yml
@@ -1966,7 +1966,6 @@ RSpec/NamedSubject:
- 'spec/lib/gitlab/grape_logging/loggers/exception_logger_spec.rb'
- 'spec/lib/gitlab/grape_logging/loggers/filter_parameters_spec.rb'
- 'spec/lib/gitlab/grape_logging/loggers/queue_duration_logger_spec.rb'
- - 'spec/lib/gitlab/grape_logging/loggers/response_logger_spec.rb'
- 'spec/lib/gitlab/grape_logging/loggers/token_logger_spec.rb'
- 'spec/lib/gitlab/graphql/batch_key_spec.rb'
- 'spec/lib/gitlab/graphql/copy_field_description_spec.rb'
diff --git a/.rubocop_todo/rspec/verified_double_reference.yml b/.rubocop_todo/rspec/verified_double_reference.yml
index 0d7387cebdc..937da31b45b 100644
--- a/.rubocop_todo/rspec/verified_double_reference.yml
+++ b/.rubocop_todo/rspec/verified_double_reference.yml
@@ -3,8 +3,6 @@
RSpec/VerifiedDoubleReference:
Exclude:
- 'ee/spec/controllers/groups/analytics/productivity_analytics_controller_spec.rb'
- - 'ee/spec/features/custom_models/code_suggestions_spec.rb'
- - 'ee/spec/features/custom_models/duo_chat_spec.rb'
- 'ee/spec/features/merge_request/user_sees_security_policy_rules_licence_compliance_spec.rb'
- 'ee/spec/features/projects/google_cloud/artifact_registry_spec.rb'
- 'ee/spec/features/projects/integrations/google_cloud_platform/user_activates_artifact_management_spec.rb'
diff --git a/AI_GATEWAY_VERSION b/AI_GATEWAY_VERSION
deleted file mode 100644
index ada8921c1f0..00000000000
--- a/AI_GATEWAY_VERSION
+++ /dev/null
@@ -1 +0,0 @@
-1dbddb919823f69cb58bf36343c84c52ec4a3418
diff --git a/app/assets/javascripts/groups_projects/components/tab_view.vue b/app/assets/javascripts/groups_projects/components/tab_view.vue
index fc2378dca4f..e0bcc2a4f33 100644
--- a/app/assets/javascripts/groups_projects/components/tab_view.vue
+++ b/app/assets/javascripts/groups_projects/components/tab_view.vue
@@ -1,15 +1,12 @@
diff --git a/app/assets/javascripts/organizations/shared/components/groups_view.vue b/app/assets/javascripts/organizations/shared/components/groups_view.vue
index af450e3f6c4..0397fc21357 100644
--- a/app/assets/javascripts/organizations/shared/components/groups_view.vue
+++ b/app/assets/javascripts/organizations/shared/components/groups_view.vue
@@ -192,7 +192,7 @@ export default {
{{ $options.i18n.viewAll }}
-
+
diff --git a/app/assets/javascripts/projects/your_work/components/app.vue b/app/assets/javascripts/projects/your_work/components/app.vue
index 6d23db5fd19..046ef5089d1 100644
--- a/app/assets/javascripts/projects/your_work/components/app.vue
+++ b/app/assets/javascripts/projects/your_work/components/app.vue
@@ -1,7 +1,9 @@
-
+
diff --git a/app/assets/javascripts/projects/your_work/constants.js b/app/assets/javascripts/projects/your_work/constants.js
index 100b918289e..9d451958476 100644
--- a/app/assets/javascripts/projects/your_work/constants.js
+++ b/app/assets/javascripts/projects/your_work/constants.js
@@ -1,4 +1,7 @@
import { __, s__ } from '~/locale';
+import ProjectsList from '~/vue_shared/components/projects_list/projects_list.vue';
+import ProjectsListEmptyState from '~/vue_shared/components/projects_list/projects_list_empty_state.vue';
+import { formatProjects } from '~/projects/your_work/utils';
import projectsQuery from './graphql/queries/projects.query.graphql';
import userProjectsQuery from './graphql/queries/user_projects.query.graphql';
@@ -7,13 +10,24 @@ const transformSortToUpperCase = (variables) => ({
sort: variables.sort.toUpperCase(),
});
+const baseTab = {
+ listComponent: ProjectsList,
+ listComponentProps: {
+ listItemClass: 'gl-px-5',
+ showProjectIcon: true,
+ },
+ emptyStateComponent: ProjectsListEmptyState,
+ formatter: formatProjects,
+};
+
export const CONTRIBUTED_TAB = {
+ ...baseTab,
text: __('Contributed'),
value: 'contributed',
query: userProjectsQuery,
variables: { contributed: true },
queryPath: 'currentUser.contributedProjects',
- emptyState: {
+ emptyStateComponentProps: {
title: s__("Projects|You haven't contributed to any projects yet."),
description: s__(
'Projects|Projects where you contribute code, create issues or epics, or participate in discussions will appear here.',
@@ -23,12 +37,13 @@ export const CONTRIBUTED_TAB = {
};
export const STARRED_TAB = {
+ ...baseTab,
text: __('Starred'),
value: 'starred',
query: userProjectsQuery,
variables: { starred: true },
queryPath: 'currentUser.starredProjects',
- emptyState: {
+ emptyStateComponentProps: {
title: s__("Projects|You haven't starred any projects yet."),
description: s__(
'Projects|Visit a project and select the star icon to save projects you want to find later.',
@@ -38,34 +53,37 @@ export const STARRED_TAB = {
};
export const PERSONAL_TAB = {
+ ...baseTab,
text: __('Personal'),
value: 'personal',
query: projectsQuery,
variables: { personal: true },
queryPath: 'projects',
- emptyState: {
+ emptyStateComponentProps: {
title: s__("Projects|You don't have any personal projects yet."),
},
};
export const MEMBER_TAB = {
+ ...baseTab,
text: __('Member'),
value: 'member',
query: projectsQuery,
variables: { membership: true },
queryPath: 'projects',
- emptyState: {
+ emptyStateComponentProps: {
title: s__("Projects|You aren't a member of any projects yet."),
},
};
export const INACTIVE_TAB = {
+ ...baseTab,
text: __('Inactive'),
value: 'inactive',
query: projectsQuery,
variables: { archived: 'ONLY', membership: true },
queryPath: 'projects',
- emptyState: {
+ emptyStateComponentProps: {
title: s__("Projects|You don't have any inactive projects."),
description: s__('Projects|Projects that are archived or pending deletion will appear here.'),
},
diff --git a/app/assets/javascripts/search/topbar/components/app.vue b/app/assets/javascripts/search/topbar/components/app.vue
index 1811a608d7c..8a5cbacc77a 100644
--- a/app/assets/javascripts/search/topbar/components/app.vue
+++ b/app/assets/javascripts/search/topbar/components/app.vue
@@ -19,7 +19,7 @@ import { SCOPE_BLOB } from '~/search/sidebar/constants';
import { SYNTAX_OPTIONS_ADVANCED_DOCUMENT, SYNTAX_OPTIONS_ZOEKT_DOCUMENT } from '../constants';
import SearchTypeIndicator from './search_type_indicator.vue';
-import GlSearchBoxByType from './search_box_by_type.vue';
+import GlobalSearchInput from './global_search_input.vue';
const trackingMixin = InternalEvents.mixin();
@@ -34,7 +34,7 @@ export default {
},
components: {
GlButton,
- GlSearchBoxByType,
+ GlobalSearchInput,
MarkdownDrawer,
SearchTypeIndicator,
},
@@ -130,7 +130,7 @@ export default {
- ({
export const Default = Template.bind({});
Default.args = {
- groups,
+ items: groups,
showGroupIcon: true,
};
diff --git a/app/assets/javascripts/vue_shared/components/groups_list/groups_list.vue b/app/assets/javascripts/vue_shared/components/groups_list/groups_list.vue
index 96c62994d55..8fca11ae661 100644
--- a/app/assets/javascripts/vue_shared/components/groups_list/groups_list.vue
+++ b/app/assets/javascripts/vue_shared/components/groups_list/groups_list.vue
@@ -6,9 +6,10 @@ import {
import GroupsListItem from './groups_list_item.vue';
export default {
+ name: 'GroupsList',
components: { GroupsListItem },
props: {
- groups: {
+ items: {
type: Array,
required: true,
},
@@ -37,7 +38,7 @@ export default {
**Subscription**
-and check the subscription plan.
-
### Set up and run GDK
-#### Option A: in GitLab.com Mode
-
-**Why:** Most Duo features are available on GitLab.com first, so emulating a multi-tenant environment.
-
-**How:**
-
-Run the Rake task to set up Duo features for a group:
-
-```shell
-GITLAB_SIMULATE_SAAS=1 bundle exec 'rake gitlab:duo:setup'
-```
-
-```shell
-gdk restart
-```
-
-Replace `test-group-name` with the name of any top-level group. Duo will
-be configured for that group. If the group doesn't exist, it creates a new
-one.
-
-Make sure the script succeeds. It prints error messages with links on how
-to resolve any errors. You can re-run the script until it succeeds.
-
-In multi-tennent mode, membership to a group with Duo features enabled is what enables
-many AI features. Make sure that your test user is a member of the group with
-Duo features enabled (`test-group-name`).
-
-This Rake task creates Duo Enterprise add-on attached to that group.
-
-In case you need Duo Pro add-on attached, please use:
-
-```shell
-GITLAB_SIMULATE_SAAS=1 bundle exec 'rake gitlab:duo:setup[duo_pro]'
-```
-
-Duo Pro add-on serves smaller scope of features. Usage of add-on depends on what features you want to use.
-
-This Rake task will assign Duo Add-on seat to the 'root' user.
-
-#### Option B: in Self-managed Mode
-
-**Why:** If you want to test something specific to self-managed setups or validate that a Duo feature
-also works for our self-managed customers.
-
-**How:**
-
-Run the Rake task to set up Duo features for the instance:
-
-```shell
-GITLAB_SIMULATE_SAAS=0 bundle exec 'rake gitlab:duo:setup'
-```
-
-```shell
-gdk restart
-```
-
-This Rake task creates Duo Enterprise add-on attached to your instance.
-
-In case you need Duo Pro add-on attached, please use:
-
-```shell
-GITLAB_SIMULATE_SAAS=0 bundle exec 'rake gitlab:duo:setup[duo_pro]'
-```
-
-Duo Pro add-on serves smaller scope of features. Usage of add-on depends on what features you want to use.
-
-This Rake task will assign Duo Add-on seat to the 'root' user.
-
-### Optional: Set `CLOUD_CONNECTOR_SELF_SIGN_TOKENS` environment variable
-
-**Why:** Setting this environment variable will allow the local GitLab instance to
-issue tokens itself, without syncing with CustomersDot first, which simplifies your local setup.
-With this set, you can skip the
-CustomersDot setup. However, note that this now requires the AI gateway to fetch token validation keys from your
-GitLab instance instead of CustomersDot, as explained [here](#option-1-use-your-gitlab-instance-as-a-provider).
-
-**Caveat:** Setting `CLOUD_CONNECTOR_SELF_SIGN_TOKENS` during local development creates a configuration that differs from
-the production customer environment.
-This divergence could mask potential issues that would only surface in the customer's setup.
-
-**How:** The following should be set in the `env.runit` file in your GDK root:
-
-```shell
-# /env.runit
-
-export CLOUD_CONNECTOR_SELF_SIGN_TOKENS=1
-```
-
-You need to restart GDK to apply the change.
-
-### Testing the setup
-
-In the Admin Area, you can run [a health check](../../user/gitlab_duo/setup.md#run-a-health-check-for-gitlab-duo)
-to see if Duo is correctly set up.
-
-### Enabled by default: Authentication and authorization in AI gateway
-
-**Why:** The AI gateway has [authentication and authorization](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/-/blob/main/docs/auth.md)
-flow to verify if clients have permission to access the features. Auth is
-enforced in any live environments hosted by GitLab infra team.
-
-To disable authorization checks (for debugging purposes only), set `AIGW_AUTH__BYPASS_EXTERNAL` to `true` in the
-`/env.runit` file in GDK.
-
-#### Option 1: Use your GitLab instance as a provider
-
-**Why:** this is the simplest method of testing authentication and reflects our setup on GitLab.com.
-
-**How:**
-Assuming that you are running the [AI gateway with GDK](#required-install-ai-gateway),
-apply the following configuration to GDK:
-
-```shell
-# /env.runit
-
-export GITLAB_SIMULATE_SAAS=1
-export CLOUD_CONNECTOR_SELF_SIGN_TOKENS=1
-export AIGW_AUTH__BYPASS_EXTERNAL=false
-```
-
-and `gdk restart`.
-
-#### Option 2: Use your customersDot instance as a provider
-
-**Why**: CustomersDot setup is required when you want to test or update functionality
-related to [cloud licensing](https://about.gitlab.com/pricing/licensing-faq/cloud-licensing/).
-This is the configuration that all self-managed customers use who do not self-host the AI gateway
-but rely on our cloud-hosted AI gateway instances instead.
-
-{{< alert type="note" >}}
-
-This setup is challenging. There is [an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/463341)
-for discussing how to make it easier to test the customersDot integration locally.
-Until that is addressed, this setup process is time-consuming.
-
-{{< /alert >}}
-
-If you need to get customersDot working for your local GitLab Rails instance for
-any reason, reach out to `#s_fulfillment_engineering` in Slack. For questions around the integration of CDot with other systems to deliver AI use cases, reach out to `#g_cloud_connector`.
-assistance.
-
-### Help
-
-- [Here's how to reach us!](https://handbook.gitlab.com/handbook/engineering/development/data-science/ai-powered/ai-framework/#-how-to-reach-us)
-- View [guidelines](duo_chat.md) for working with GitLab Duo Chat.
+For detailed instructions on setting up your GDK for GitLab Duo development, see [GitLab Duo licensing for local development](ai_development_license.md).
## Tips for local development
@@ -380,3 +228,8 @@ An [example](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/
## Security
Refer to the [secure coding guidelines for Artificial Intelligence (AI) features](../secure_coding_guidelines.md#artificial-intelligence-ai-features).
+
+## Help
+
+- [Here's how to reach us!](https://handbook.gitlab.com/handbook/engineering/development/data-science/ai-powered/ai-framework/#-how-to-reach-us)
+- View [guidelines](duo_chat.md) for working with GitLab Duo Chat.
diff --git a/doc/development/ai_features/ai_development_license.md b/doc/development/ai_features/ai_development_license.md
new file mode 100644
index 00000000000..a66d92e9021
--- /dev/null
+++ b/doc/development/ai_features/ai_development_license.md
@@ -0,0 +1,281 @@
+---
+stage: AI-powered
+group: AI Framework
+info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
+description: Documentation about GitLab Duo licensing options for local development
+title: GitLab Duo licensing for local development
+---
+
+This document explains the different licensing options available for GitLab Duo features in local development environments.
+
+> **Note:** When developing GitLab Duo features, it's important to test in both multi-tenant (GitLab.com) and single-tenant (Self-managed/Dedicated) environments where appropriate. There is no default or recommended approach - the setup you choose should be based on your specific testing requirements.
+
+## Overview
+
+GitLab Duo features require either Duo Pro or Duo Enterprise licensing. When developing locally, there are multiple approaches to set up licensing, each serving different development needs.
+
+This guide helps you understand:
+
+- Which licensing approach to use for your specific development needs
+- How to set up each licensing option
+- The trade-offs between different approaches
+
+## Quick reference
+
+You should choose a license setup based on your development needs. Each approach provides a different testing environment:
+
+| Development Scenario | License Setup | Instructions |
+|----------------------|---------------------------|-------------|
+| Multi-tenant setup (GitLab.com) | Local license with Rake task | [Option A](#option-a-local-license-with-rake-task-multi-tenantgitlabcom-mode) |
+| Single-tenant setup (Self-managed/Dedicated) | Local license with Rake task in self-managed mode | [Option B](#option-b-local-license-with-rake-task-in-self-managed-mode-single-tenant-setup) |
+| Full dog-fooding experience | Cloud license via CustomersDot | [Option C](#option-c-cloud-license-via-customersdot) |
+
+## Prerequisites for all options
+
+### Install AI gateway
+
+**Why:** Duo features (except for Duo Workflow) route LLM requests through the AI gateway.
+
+**How:**
+Follow [these instructions](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/gitlab_ai_gateway.md#install)
+to install the AI gateway with GDK. We recommend this route for most users.
+
+You can also install AI gateway by:
+
+1. [Cloning the repository directly](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist).
+1. [Running the server locally](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist#how-to-run-the-server-locally).
+
+We only recommend this for users who have a specific reason for *not* running
+the AI gateway through GDK.
+
+### Set up GitLab Team Member License
+
+**Why:** GitLab Duo is available to Premium and Ultimate customers only. You
+likely want an Ultimate license for your GDK. Ultimate gets you access to
+all GitLab Duo features.
+
+**How:**
+
+Follow [the process to obtain an EE license](https://handbook.gitlab.com/handbook/engineering/developer-onboarding/#working-on-gitlab-ee-developer-licenses)
+for your local instance and [upload the license](../../administration/license_file.md).
+
+To verify that the license is applied, go to **Admin area** > **Subscription**
+and check the subscription plan.
+
+## Option A: Local license with Rake task (Multi-tenant/GitLab.com mode)
+
+This approach configures your environment to behave like GitLab.com (multi-tenant) for Duo features development.
+
+### When to use
+
+- When you need to test in a multi-tenant environment (similar to GitLab.com)
+- When developing features that are specific to or need validation in GitLab.com
+- When testing integration points that behave differently in multi-tenant mode
+
+### Setup steps
+
+- Ensure that you have a [GitLab Team Member License](https://handbook.gitlab.com/handbook/engineering/developer-onboarding/#working-on-gitlab-ee-developer-licenses) and that it is [activated](../../administration/license_file.md).
+- Run the Rake task to set up Duo features for a group:
+
+```shell
+GITLAB_SIMULATE_SAAS=1 bundle exec 'rake gitlab:duo:setup'
+```
+
+- Restart your GDK:
+
+```shell
+gdk restart
+```
+
+- This Rake task creates a Duo Enterprise add-on attached to your group and assigns a Duo add-on seat to the 'root' user.
+
+> **Note:** This Rake task primarily creates database records to simulate licensing in your development environment. With `GITLAB_SIMULATE_SAAS=1`, the environment is configured to behave like GitLab.com and allows self-signing tokens automatically.
+
+- If you need to set up a Duo Pro add-on instead, run this Rake task:
+
+```shell
+GITLAB_SIMULATE_SAAS=1 bundle exec 'rake gitlab:duo:setup[pro]'
+```
+
+### Pros
+
+- Quick setup for multi-tenant testing
+- No need to connect to external services
+- Simulates the GitLab.com environment
+- No need to set `CLOUD_CONNECTOR_SELF_SIGN_TOKENS` as it's handled automatically
+
+### Cons
+
+- Not a true representation of how real cloud customers would experience the setup
+- May mask issues that only appear in production environments with real cloud licensing
+
+## Option B: Local license with Rake task in self-managed mode (Single-tenant setup)
+
+This approach configures your environment to behave like a self-managed or Dedicated GitLab instance (single-tenant).
+
+### When to use
+
+- When you need to test in a single-tenant environment (similar to Self-managed or Dedicated)
+- When developing features that are specific to or need validation in self-managed or Dedicated environments
+- When testing integration points that behave differently in single-tenant mode
+
+### Setup steps
+
+- Ensure that you have a [GitLab Team Member License](https://handbook.gitlab.com/handbook/engineering/developer-onboarding/#working-on-gitlab-ee-developer-licenses) and that it is [activated](../../administration/license_file.md).
+- Run the Rake task to set up Duo features for the instance in self-managed mode:
+
+```shell
+GITLAB_SIMULATE_SAAS=0 bundle exec 'rake gitlab:duo:setup'
+```
+
+- Restart your GDK:
+
+```shell
+gdk restart
+```
+
+- This Rake task creates a Duo Enterprise add-on attached to your instance and assigns a Duo add-on seat to the 'root' user.
+
+> **Note:** This Rake task primarily creates database records to simulate licensing in your development environment.
+
+- For self-managed mode, you need to configure environment variables for self-signing tokens:
+
+```shell
+# /env.runit
+
+export CLOUD_CONNECTOR_SELF_SIGN_TOKENS=1
+```
+
+- Restart GDK again to apply the change.
+
+> **Note:** In self-managed mode, `CLOUD_CONNECTOR_SELF_SIGN_TOKENS` is required to allow your local GitLab instance to issue tokens itself, without syncing with CustomersDot. With `GITLAB_SIMULATE_SAAS=1` (Option A), this variable is not needed but can be left in place when switching between modes as it doesn't interfere with multi-tenant operation.
+
+### Pros
+
+- Quick setup for single-tenant testing
+- No need to connect to external services
+- Simulates self-managed/Dedicated environments
+
+### Cons
+
+- Not a true representation of how real self-managed customers would experience the setup
+- May mask issues that only appear in production environments with real cloud licensing
+
+## Option C: Cloud license via CustomersDot
+
+This approach uses a real cloud license through CustomersDot, providing the most authentic testing environment that matches what customers experience.
+
+### When to use
+
+- When testing or updating functionality related to cloud licensing
+- When you need to use the staging AI Gateway or want to run CustomersDot and the AI gateway locally
+- When you want to fully dog-food the customer experience
+- When troubleshooting issues specific to license validation in production
+
+### Setup steps
+
+- Add a **Self-Managed Ultimate** subscription with a [Duo Pro or Duo Enterprise subscription add-on](../../subscriptions/subscription-add-ons.md) to your GDK instance.
+ - Sign in to the [staging Customers Portal](https://customers.staging.gitlab.com) by selecting the **Continue with GitLab.com account** button. If you do not have an existing account, you are prompted to create one.
+ - If you do not have an existing cloud activation code, visit the **Self-Managed Ultimate Subscription** page using the [buy subscription flow link](https://gitlab.com/gitlab-org/customers-gitlab-com/-/blob/8aa922840091ad5c5d96ada43d0065a1b6198841/doc/flows/buy_subscription.md).
+ - Purchase the subscription using [a test credit card](https://gitlab.com/gitlab-org/customers-gitlab-com/#testing-credit-card-information).
+ - Once you have a subscription, on the subscription card, select the ellipse menu **...** > **Buy Duo Pro add-on** (or Duo Enterprise if needed).
+ - Use the previously saved credit card information, and the same number of seats as in the subscription.
+
+- Follow the activation instructions:
+
+ - Set environment variables:
+
+ ```shell
+ export GITLAB_LICENSE_MODE=test
+ export CUSTOMER_PORTAL_URL=https://customers.staging.gitlab.com
+ ```
+
+ - **Note on GDK and AI Gateway:** While GDK can include AI Gateway as part of its distribution, developers may run AI Gateway with different configurations or ports. Currently, GitLab instances need explicit configuration of the AI Gateway URL, even in development environments.
+
+ - If you need to connect to the staging AI Gateway, configure it through the Admin UI (this option is only available with Ultimate license and active Duo Enterprise add-on):
+
+ 1. Go to **Admin Area** > **Settings** > **GitLab Duo** > **Self-hosted models**
+ 1. Set the **AI Gateway URL** to `https://cloud.staging.gitlab.com/ai`
+ 1. Click **Save changes**
+
+ - Alternatively, you can set the AI gateway URL in a Rails console (useful when you don't have access to the Admin UI):
+
+ ```ruby
+ Ai::Setting.instance.update!(ai_gateway_url: 'https://cloud.staging.gitlab.com/ai')
+ ```
+
+ - Restart your GDK.
+ - Go to `/admin/subscription`.
+ - Optional. Remove any active license.
+ - Add the new activation code.
+
+- Inside your GDK, navigate to **Admin area** > **GitLab Duo Pro**, go to `/admin/code_suggestions`
+- Filter users to find `root` and click the toggle to assign a GitLab Duo Pro add-on seat to the root user.
+
+### Pros
+
+- Provides the most authentic testing environment
+- Required for testing with staging AI Gateway
+- Tests the complete flow including cloud license validation
+- Most closely mirrors customer experience
+
+### Cons
+
+- Significantly more complex to set up
+- Requires interaction with external services
+- Time-consuming to configure
+
+### Future improvements
+
+> **Note:** There are ongoing plans to streamline the configuration of AI Gateway in development environments to reduce manual setup steps. In the future, we aim to automate this process as part of the GDK setup. For now, please follow the manual configuration steps described above.
+
+## Setting up Duo on your GitLab.com staging account
+
+When working in staging environments, you may need to set up Duo add-ons for your staging account. This is different from setting up your local development environment.
+
+> **Note:** This section contains the same information as the previous [Staging account setup](staging_accounts.md) document, which now redirects here.
+
+### Duo Pro
+
+1. Have your account ready at .
+1. [Create a new group](../../user/group/_index.md#create-a-group) or use an existing one as the namespace which will receive the Duo Pro access.
+1. Go to **Settings > Billing**.
+1. Initiate the purchase flow for the Ultimate plan by clicking on `Upgrade to Ultimate`.
+1. After being redirected to , click on `Continue with your Gitlab.com account`.
+1. Purchase the SaaS Ultimate subscription using [a test credit card](https://gitlab.com/gitlab-org/customers-gitlab-com#testing-credit-card-information).
+1. Find the newly purchased subscription card, and select from the three dots menu the option `Buy GitLab Duo Pro`.
+1. Purchase the GitLab Duo Pro add-on using the same test credit card from the above steps.
+1. Go back to and verify that your group has access to Duo Pro by navigating to `Settings > GitLab Duo` and managing seats.
+
+### Duo Enterprise
+
+**Internal use only:** Given that purchasing a license for Duo Enterprise is not self-serviceable, post a request in the `#g_provision` Slack channel to grant access to your customer staging account with a Duo Enterprise license.
+
+## Testing your setup
+
+In the Admin Area, you can run [a health check](../../user/gitlab_duo/setup.md#run-a-health-check-for-gitlab-duo)
+to see if Duo is correctly set up.
+
+## Troubleshooting
+
+If you're having issues with your Duo license setup:
+
+- Verify your license is active by checking the Admin Area
+- Ensure your user has a Duo seat assigned
+- Run the [Duo health check](../../user/gitlab_duo/setup.md#run-a-health-check-for-gitlab-duo) to identify specific issues
+- Check logs for any authentication or license validation errors
+- For cloud license issues, reach out to `#s_fulfillment_engineering` in Slack
+- For AI Gateway connection issues, reach out to `#g_cloud_connector` in Slack
+
+## Best Practices
+
+- **Test in both environments**: For thorough testing, consider alternating between multi-tenant and single-tenant setups to ensure your feature works well in both environments.
+- **Consult domain documentation**: Review specific feature documentation to understand if there are any environment-specific behaviors you need to consider.
+- **Consider end-user context**: Remember that features should work well for both GitLab.com users and self-managed/dedicated customers.
+
+## Additional resources
+
+- [AI Features Documentation](../ai_features/_index.md)
+- [Code Suggestions Development](../ai_features/code_suggestions.md)
+- [License Management Guidelines for Code Suggestions](../ai_features/code_suggestions.md#setup-instructions-to-use-gdk-with-the-code-suggestions-add-on)
+- [Duo Enterprise License Access Process for Staging Environment](https://gitlab.com/gitlab-com/runbooks/-/blob/master/docs/duo/duo_license.md?ref_type=heads)
diff --git a/doc/development/ai_features/staging_accounts.md b/doc/development/ai_features/staging_accounts.md
index 0d5e6815cba..5502eb62658 100644
--- a/doc/development/ai_features/staging_accounts.md
+++ b/doc/development/ai_features/staging_accounts.md
@@ -3,20 +3,7 @@ stage: AI-powered
group: AI Framework
info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
title: Set up Duo on your GitLab.com staging account
+redirect_to: '../ai_features/ai_development_license.md#setting-up-duo-on-your-gitlabcom-staging-account'
---
-## Duo Pro
-
-1. Have your account ready at .
-1. [Create a new group](../../user/group/_index.md#create-a-group) or use an existing one as the namespace which will receive the Duo Pro access.
-1. Go to **Settings > Billing**.
-1. Initiate the purchase flow for the Ultimate plan by clicking on `Upgrade to Ultimate`.
-1. After being redirected to , click on `Continue with your Gitlab.com account`.
-1. Purchase the SaaS Ultimate subscription using [a test credit card](https://gitlab.com/gitlab-org/customers-gitlab-com#testing-credit-card-information).
-1. Find the newly purchased subscription card, and select from the three dots menu the option `Buy GitLab Duo Pro`.
-1. Purchase the GitLab Duo Pro add-on using the same test credit card from the above steps.
-1. Go back to and verify that your group has access to Duo Pro by navigating to `Settings > GitLab Duo` and managing seats.
-
-## Duo Enterprise
-
-**Internal use only:** Given that purchasing a license for Duo Enterprise is not self-serviceable, post a request in the `#g_provision` Slack channel to grant access to your customer staging account with a Duo Enterprise license.
+This document has been consolidated into [GitLab Duo licensing for local development](ai_development_license.md#setting-up-duo-on-your-gitlabcom-staging-account).
diff --git a/doc/development/custom_models/_index.md b/doc/development/custom_models/_index.md
deleted file mode 100644
index e27a761d3e2..00000000000
--- a/doc/development/custom_models/_index.md
+++ /dev/null
@@ -1,87 +0,0 @@
----
-stage: AI-powered
-group: Custom Models
-info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
-title: Setting up local development
----
-
-## Set up your local GitLab instance
-
-1. [Configure GDK to set up Duo Features in the local environment](../ai_features/_index.md)
-
-1. For AI gateway:
-
-- Set `AIGW_CUSTOM_MODELS__ENABLED=True`
-- Set `AIGW_AUTH__BYPASS_EXTERNAL=False` or `AIGW_GITLAB_URL=`
-
-1. Run `gitlab:duo:verify_self_hosted_setup` task to verify the setup
-
-## Configure self-hosted models
-
-1. Follow the [instructions](../../administration/gitlab_duo_self_hosted/configure_duo_features.md#configure-the-self-hosted-model) to configure self-hosted models
-1. Follow the [instructions](../../administration/gitlab_duo_self_hosted/configure_duo_features.md#configure-gitlab-duo-features-to-use-self-hosted-models) to configure features to use the models
-
-AI-powered features are now powered by self-hosted models.
-
-## Configure features to use AI vendor models
-
-After adding [support](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164924) for configuring features to either use self-hosted models for AI Vendor, setting `CLOUD_CONNECTOR_SELF_SIGN_TOKENS` is no longer necessary for the customers. But it is harder for developers to configure the features to use AI vendored because we still want to send all requests to the local AI gateway instead of Cloud Connector.
-
-Setting [`CLOUD_CONNECTOR_BASE_URL`](https://gitlab.com/gitlab-org/gitlab/-/blob/1452de8cde035bb5eba53ba2a2903c28fc237455/config/initializers/1_settings.rb#L1028) is not sufficient because we [add](https://gitlab.com/gitlab-org/gitlab/-/blob/1452de8cde035bb5eba53ba2a2903c28fc237455/ee/lib/gitlab/ai_gateway.rb#L14) `/ai` suffix to it.
-
-Currently, there are the following workarounds:
-
-1. Verify that `CLOUD_CONNECTOR_SELF_SIGN_TOKENS=1`
-1. Remove `ai_feature_settings` record responsible for the configuration to fallback to using the AI gateway URL (configured through `Ai::Setting.instance.ai_gateway_url`) as Cloud Connector URL:
-
-```ruby
-Ai::FeatureSetting.find_by(feature: :duo_chat).destroy!
-```
-
-## Testing
-
-To comprehensively test that a feature using Custom Models works as expected, you must write `system` specs.
-
-This is required because, unlike `unit` tests, `system` specs invoke all the components involved in the custom models stack. For example, the Puma, Workhorse, AI gateway + LLM Mock server.
-
-To write a new `system` test and for it to run successfully, there are the following prerequisites:
-
-- AI gateway must be running (usually on port `5052`), and you must configure the AI gateway URL through the `Ai::Setting.instance` record:
-
- ```shell
- Ai::Setting.instance.update!(ai_gateway_url: 'http://localhost:5052')
- ```
-
-- We use [LiteLLM proxy](https://www.litellm.ai/) to return mock responses. You must configure LiteLLM to return mock responses using a configuration file:
-
- ```yaml
- # config.yaml
- model_list:
- - model_name: codestral
- litellm_params:
- model: ollama/codestral
- mock_response: "Mock response from codestral"
- ```
-
-- LiteLLM proxy must be running (usually on port `4000`), and the you must configure the environment variable `LITELLM_PROXY_URL`:
-
- ```shell
- litellm --config config.yaml
-
- export LITELLM_PROXY_URL="http://localhost:4000"
- ```
-
-- You must tag the RSpec file with `requires_custom_models_setup`.
-
-For an example, see [`ee/spec/features/custom_models/code_suggestions_spec.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/244e37a201620f9d98503e186b60e4e572a05d6e/ee/spec/features/custom_models/code_suggestions_spec.rb). In this file, we test that the code completions feature uses a self-hosted `codestral` model.
-
-### Testing On CI
-
-On CI, AI gateway and LiteLLM proxy are already configured to run for all tests tagged with `requires_custom_models_setup`.
-
-
-
-However, you must also update the `config` for LiteLLM if you are testing features that use newer models in the specs that have not been used before.
-The configuration for LiteLLM is in [`.gitlab/ci/global.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/2b14f212d48ca2c22904805600491baf8460427e/.gitlab/ci/global.gitlab-ci.yml#L332).
-
-
diff --git a/doc/development/python_guide/maintainership.md b/doc/development/python_guide/maintainership.md
index 057f52a78fe..a0787752e81 100644
--- a/doc/development/python_guide/maintainership.md
+++ b/doc/development/python_guide/maintainership.md
@@ -7,12 +7,44 @@ title: Python Merge Requests Guidelines
GitLab standard [code review guidelines](../code_review.md#approval-guidelines) apply to Python projects as well.
-## How to find a reviewer
+## How to set up a Python code review process
-This section explains how to integrate your project with [reviewer roulette](../code_review.md#reviewer-roulette)
-and other resources to find reviewers with Python expertise.
+There are two main approaches to set up a Python code review process at GitLab:
-[Work item](https://gitlab.com/gitlab-org/gitlab/-/issues/514318).
+1. **Established Projects:** Larger Python projects typically have their own dedicated pool of reviewers through reviewer-roulette. To set this up, please refer to [Setting Up Reviewer Roulette](#setting-up-reviewer-roulette).
+1. **Smaller Projects:** For projects with fewer contributors, we maintain a shared pool of Python reviewers across GitLab.
+
+### Setting Up Reviewer Roulette
+
+This section explains how to integrate your project with [reviewer roulette](../code_review.md#reviewer-roulette) and other resources to connect project contributors with Python experts for code reviews.
+
+For both large and small projects, Reviewer Roulette can automate the reviewer assignment process. To set up:
+
+1. Add the Python project to the list of [GitLab projects](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/projects.yml?ref_type=heads).
+1. Project maintainer(s) should add a group for the project in the [GitLab.org maintainers repository](https://gitlab.com/gitlab-org/maintainers)
+1. Install and configure [Dangerfiles](https://gitlab.com/gitlab-org/ruby/gems/gitlab-dangerfiles) in your project, ensuring [CI is properly set up](https://gitlab.com/gitlab-org/ruby/gems/gitlab-dangerfiles#ci-configuration) to enable the Reviewer Roulette plugin.
+
+Then, depending on your project size:
+
+- **For large projects with sufficient contributors:**
+
+ - Eligible team members should add the Python project to the `projects` field in their individual entry in [team_members](https://gitlab.com/gitlab-com/www-gitlab-com/-/tree/master/data/team_members/person) or [team_database](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/doc/team_database.md), specifying appropriate roles such as reviewer or maintainer.
+ - Add the [individual roulette configuration](https://gitlab.com/gitlab-org/python/code-review-templates/-/tree/main/individual_roulette?ref_type=heads) to your project.
+
+- **For smaller projects (e.g. fewer than 10 contributors):**
+
+ - Leverage the company wide pool of Python experts by adding the [shared pool configuration](https://gitlab.com/gitlab-org/python/code-review-templates/-/tree/main/shared_pull/danger?ref_type=heads) to your project.
+ - You can also encourage contributors or other non-domain reviewers to reach out in your team's Slack channel for domain expertise where needed.
+
+When a merge request is created, Review Roulette will randomly select qualified reviewers based on your configuration.
+
+### Additional recommendations
+
+Please refer to [the documentation](../code_review.md#reviewer-roulette)
+
+### Ask for help
+
+If contributors have questions or need additional help with Python-specific reviews, direct them to the GitLab #python or #python_maintainers Slack channels for assistance.
## How to find a project to review
diff --git a/doc/user/project/repository/code_suggestions/_index.md b/doc/user/project/repository/code_suggestions/_index.md
index 84e0912e556..0b4f388d823 100644
--- a/doc/user/project/repository/code_suggestions/_index.md
+++ b/doc/user/project/repository/code_suggestions/_index.md
@@ -145,18 +145,14 @@ For use cases and best practices, follow the [GitLab Duo examples documentation]
## The context Code Suggestions is aware of
-Code Suggestions is aware of and uses:
+Code Suggestions uses the following information about your development environment as context to enrich suggestions:
-- The file open in your IDE.
-- The content before and after the cursor in that file.
+- The file open in your IDE, including the content before and after the cursor in that file.
- The filename and extension.
-
-Code Suggestions also uses files from your repository as context to make suggestions and
-generate code:
-
-- Code completion can use files in your repository that are written in the [languages enabled for Code Suggestions in your IDE](supported_extensions.md#supported-languages).
-- Code generation can use files in your repository that are written in the following
-languages:
+- (Optional) Files open in tabs in your IDE. These files give GitLab Duo more information about the standards and practices in your code project. On by default. To manage tabs as context, see [Using open files as context](#using-open-files-as-context).
+- (Optional) Files imported in the current opened file. These imported files give GitLab Duo more information about the classes and methods used in the current file. Off by default. To manage imported files as context, see [Using imported files as context](#using-imported-files-as-context).
+- Code suggestion functionality uses content from the [supported languages](supported_extensions.md#supported-languages).
+- Code generation functionality uses content from the following languages:
- Go
- Java
- JavaScript
@@ -197,11 +193,7 @@ GitLab recently refactored the Open Tabs internal logic for Duo Code Suggestions
{{< /alert >}}
-As well as using files from your repository, Code Suggestions can use the files
-open in tabs in your IDE as context.
-
-These files give GitLab Duo more information about the standards and practices
-in your code project.
+If tab as context is on, Code Suggestions uses the files open in tabs in your IDE as context. These files give GitLab Duo more information about the standards and practices in your code project.
#### Turn on open files as context
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 421c9b86cc8..7c2ddfefb5c 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -43,8 +43,7 @@ module API
Gitlab::GrapeLogging::Loggers::CorrelationIdLogger.new,
Gitlab::GrapeLogging::Loggers::ContextLogger.new,
Gitlab::GrapeLogging::Loggers::ContentLogger.new,
- Gitlab::GrapeLogging::Loggers::UrgencyLogger.new,
- Gitlab::GrapeLogging::Loggers::ResponseLogger.new
+ Gitlab::GrapeLogging::Loggers::UrgencyLogger.new
]
allow_access_with_scope :api
diff --git a/lib/gitlab/database_importers/security/training_providers/importer.rb b/lib/gitlab/database_importers/security/training_providers/importer.rb
index 87bef6400fa..4f6409dd894 100644
--- a/lib/gitlab/database_importers/security/training_providers/importer.rb
+++ b/lib/gitlab/database_importers/security/training_providers/importer.rb
@@ -23,7 +23,7 @@ module Gitlab
SECUREFLAG_DATA = {
name: 'SecureFlag',
description: "Get remediation advice with example code and recommended hands-on labs in a fully
- interactive virtualised environment.",
+ interactive virtualized environment.",
url: "https://knowledge-base-api.secureflag.com/gitlab"
}.freeze
diff --git a/lib/gitlab/grape_logging/loggers/response_logger.rb b/lib/gitlab/grape_logging/loggers/response_logger.rb
deleted file mode 100644
index 767c282d62e..00000000000
--- a/lib/gitlab/grape_logging/loggers/response_logger.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module GrapeLogging
- module Loggers
- class ResponseLogger < ::GrapeLogging::Loggers::Base
- def parameters(_, response)
- return {} unless Feature.enabled?(:log_response_length)
-
- response_bytes = 0
-
- case response
- when String
- response_bytes = response.bytesize
- else
- response.each { |resp| response_bytes += resp.to_s.bytesize }
- end
-
- {
- response_bytes: response_bytes
- }
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/lograge/custom_options.rb b/lib/gitlab/lograge/custom_options.rb
index c52228c9455..655e71a600e 100644
--- a/lib/gitlab/lograge/custom_options.rb
+++ b/lib/gitlab/lograge/custom_options.rb
@@ -7,7 +7,7 @@ module Gitlab
LIMITED_ARRAY_SENTINEL = { key: 'truncated', value: '...' }.freeze
IGNORE_PARAMS = Set.new(%w[controller action format]).freeze
- KNOWN_PAYLOAD_PARAMS = [:remote_ip, :user_id, :username, :ua, :queue_duration_s, :response_bytes,
+ KNOWN_PAYLOAD_PARAMS = [:remote_ip, :user_id, :username, :ua, :queue_duration_s,
:etag_route, :request_urgency, :target_duration_s] + CLOUDFLARE_CUSTOM_HEADERS.values
def self.call(event)
@@ -36,10 +36,6 @@ module Gitlab
payload[:feature_flag_states] = Feature.logged_states.map { |key, state| "#{key}:#{state ? 1 : 0}" }
end
- if Feature.disabled?(:log_response_length)
- payload.delete(:response_bytes)
- end
-
payload
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 6758ea46f87..4a64b9f0782 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -63749,6 +63749,9 @@ msgstr ""
msgid "UserMapping|Placeholders"
msgstr ""
+msgid "UserMapping|Please upload a valid CSV file."
+msgstr ""
+
msgid "UserMapping|Reassign"
msgstr ""
diff --git a/qa/qa/specs/features/browser_ui/10_govern/login/register_spec.rb b/qa/qa/specs/features/browser_ui/10_govern/login/register_spec.rb
index 3697c8530d0..92e40e44642 100644
--- a/qa/qa/specs/features/browser_ui/10_govern/login/register_spec.rb
+++ b/qa/qa/specs/features/browser_ui/10_govern/login/register_spec.rb
@@ -56,8 +56,7 @@ module QA
show.delete_account(user.password)
end
- expect { user.exists? }.to eventually_be_falsey.within(max_duration: 120, sleep_interval: 3),
- "Expected user to be deleted, but it still exists"
+ expect(page).to have_text("Account scheduled for removal.")
end
it "allows to recreate deleted user with same credeintials",
diff --git a/scripts/utils.sh b/scripts/utils.sh
index 60ab6749415..949be5cbc85 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -543,23 +543,25 @@ function log_disk_usage() {
# all functions below are for customizing CI job exit code
function run_with_custom_exit_code() {
- set +e # temporarily disable exit on error to prevent premature exit
+ set -o pipefail # Take the exit status of the rightmost command that failed
+ set +e # temporarily disable exit on error to prevent premature exit
- # runs command passed in as argument, save standard error and standard output
- output=$(set -e; "$@" 2>&1)
+ local trace_file="/tmp/stdout_stderr_log.out"
+
+ # Run the command and tee output to both the terminal and the file
+ "$@" 2>&1 | tee "$trace_file"
initial_exit_code=$?
-
+
echo "initial_exit_code: $initial_exit_code"
- local trace_file="stdout_stderr_log.out"
-
- echo "$output" | tee "$trace_file"
-
find_custom_exit_code "$initial_exit_code" "$trace_file"
new_exit_code=$?
echo "new_exit_code=$new_exit_code"
+
+ # Restore shell default behavior
set -e
+ set +o pipefail
exit "$new_exit_code"
}
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 18369ee2b39..2104353a336 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -561,28 +561,6 @@ RSpec.describe ApplicationController, feature_category: :shared do
expect(controller.last_payload[:target_duration_s]).to eq(0.25)
end
end
-
- it 'logs response length' do
- sign_in user
-
- get :index
-
- expect(controller.last_payload[:response_bytes]).to eq('authenticated'.bytesize)
- end
-
- context 'with log_response_length disabled' do
- before do
- stub_feature_flags(log_response_length: false)
- end
-
- it 'logs response length' do
- sign_in user
-
- get :index
-
- expect(controller.last_payload).not_to include(:response_bytes)
- end
- end
end
describe '#access_denied' do
diff --git a/spec/controllers/oauth/tokens_controller_spec.rb b/spec/controllers/oauth/tokens_controller_spec.rb
index 489470dc0df..19fcaa85294 100644
--- a/spec/controllers/oauth/tokens_controller_spec.rb
+++ b/spec/controllers/oauth/tokens_controller_spec.rb
@@ -39,27 +39,5 @@ RSpec.describe Oauth::TokensController, feature_category: :user_management do
expect(controller.last_payload[:metadata]).to include(Gitlab::ApplicationContext.current)
end
-
- it 'logs response length' do
- sign_in user
-
- post :create
-
- expect(controller.last_payload[:response_bytes]).to eq('authenticated'.bytesize)
- end
-
- context 'with log_response_length disabled' do
- before do
- stub_feature_flags(log_response_length: false)
- end
-
- it 'logs response length' do
- sign_in user
-
- post :create
-
- expect(controller.last_payload).not_to include(:response_bytes)
- end
- end
end
end
diff --git a/spec/frontend/groups_projects/components/tab_view_spec.js b/spec/frontend/groups_projects/components/tab_view_spec.js
index 5c6440cc900..312ef500321 100644
--- a/spec/frontend/groups_projects/components/tab_view_spec.js
+++ b/spec/frontend/groups_projects/components/tab_view_spec.js
@@ -113,8 +113,8 @@ describe('TabView', () => {
});
});
- it('passes projects to `ProjectsList` component', () => {
- expect(findProjectsList().props('projects')).toEqual(formatProjects(expectedProjects));
+ it('passes items to `ProjectsList` component', () => {
+ expect(findProjectsList().props('items')).toEqual(formatProjects(expectedProjects));
});
it('passes `timestampType` prop to `ProjectsList` component', () => {
@@ -292,8 +292,12 @@ describe('TabView', () => {
});
it('renders an empty state and passes title and description prop', () => {
- expect(findEmptyState().props('title')).toBe(CONTRIBUTED_TAB.emptyState.title);
- expect(findEmptyState().props('description')).toBe(CONTRIBUTED_TAB.emptyState.description);
+ expect(findEmptyState().props('title')).toBe(
+ CONTRIBUTED_TAB.emptyStateComponentProps.title,
+ );
+ expect(findEmptyState().props('description')).toBe(
+ CONTRIBUTED_TAB.emptyStateComponentProps.description,
+ );
});
});
diff --git a/spec/frontend/groups_projects/components/tabs_with_list_spec.js b/spec/frontend/groups_projects/components/tabs_with_list_spec.js
index fe53bb22a28..fa063bb745f 100644
--- a/spec/frontend/groups_projects/components/tabs_with_list_spec.js
+++ b/spec/frontend/groups_projects/components/tabs_with_list_spec.js
@@ -64,6 +64,10 @@ const defaultProvide = {
programmingLanguages,
};
+const defaultPropsData = {
+ tabs: PROJECT_DASHBOARD_TABS,
+};
+
const searchTerm = 'foo bar';
const mockEndCursor = 'mockEndCursor';
const mockStartCursor = 'mockStartCursor';
@@ -86,6 +90,7 @@ describe('TabsWithList', () => {
const createComponent = async ({
provide = {},
+ propsData = {},
projectsCountHandler = successHandler,
userPreferencesUpdateHandler = userPreferencesUpdateSuccessHandler,
route = defaultRoute,
@@ -104,6 +109,7 @@ describe('TabsWithList', () => {
TabView: stubComponent(TabView),
},
provide: { ...defaultProvide, ...provide },
+ propsData: { ...defaultPropsData, ...propsData },
});
};
diff --git a/spec/frontend/members/placeholders/components/csv_upload_modal_spec.js b/spec/frontend/members/placeholders/components/csv_upload_modal_spec.js
index 9bb15851b4e..eb81426abcd 100644
--- a/spec/frontend/members/placeholders/components/csv_upload_modal_spec.js
+++ b/spec/frontend/members/placeholders/components/csv_upload_modal_spec.js
@@ -58,10 +58,6 @@ describe('CsvUploadModal', () => {
});
describe('CSV upload', () => {
- beforeEach(() => {
- jest.spyOn(FileReader.prototype, 'readAsText');
- });
-
it('renders the upload dropzone', () => {
expect(findUploadDropzone().exists()).toBe(true);
});
@@ -90,18 +86,23 @@ describe('CsvUploadModal', () => {
});
describe('submitting the data', () => {
+ const preventDefault = jest.fn();
+ const file = new File(['test'], 'file.csv');
+
beforeEach(() => {
jest.spyOn(axios, 'post');
+
+ findUploadDropzone().vm.$emit('change', file);
+ });
+
+ it('prevents modal from getting closed', () => {
+ findGlModal().vm.$emit('primary', { preventDefault });
+
+ expect(preventDefault).toHaveBeenCalled();
});
it('calls the endpoint with the correct data', async () => {
- const uploadDropzone = findUploadDropzone();
- const file = new File(['test'], 'file.csv');
-
- uploadDropzone.vm.$emit('change', file);
- await waitForPromises();
-
- findGlModal().vm.$emit('primary');
+ findGlModal().vm.$emit('primary', { preventDefault });
await waitForPromises();
const expectedFormData = new FormData();
@@ -118,7 +119,7 @@ describe('CsvUploadModal', () => {
.onPost(MOCK_REASSIGNMENT_CSV_PATH)
.reply(HTTP_STATUS_OK, { message: mockMessage });
- findGlModal().vm.$emit('primary');
+ findGlModal().vm.$emit('primary', { preventDefault });
await waitForPromises();
expect(createAlert).toHaveBeenCalledWith({
@@ -136,7 +137,7 @@ describe('CsvUploadModal', () => {
.onPost(MOCK_REASSIGNMENT_CSV_PATH)
.reply(HTTP_STATUS_UNPROCESSABLE_ENTITY, { message: mockMessage });
- findGlModal().vm.$emit('primary');
+ findGlModal().vm.$emit('primary', { preventDefault });
await waitForPromises();
expect(createAlert).toHaveBeenCalledWith({
@@ -149,7 +150,7 @@ describe('CsvUploadModal', () => {
.onPost(MOCK_REASSIGNMENT_CSV_PATH)
.reply(HTTP_STATUS_INTERNAL_SERVER_ERROR, { error: new Error('error uploading CSV') });
- findGlModal().vm.$emit('primary');
+ findGlModal().vm.$emit('primary', { preventDefault });
await waitForPromises();
expect(createAlert).toHaveBeenCalledWith({
diff --git a/spec/frontend/organizations/shared/components/groups_view_spec.js b/spec/frontend/organizations/shared/components/groups_view_spec.js
index 663206fd62f..dd386135912 100644
--- a/spec/frontend/organizations/shared/components/groups_view_spec.js
+++ b/spec/frontend/organizations/shared/components/groups_view_spec.js
@@ -107,7 +107,7 @@ describe('GroupsView', () => {
const findGroupsList = () => wrapper.findComponent(GroupsList);
const findGroupsListByGroupId = (groupId) =>
findGroupsList()
- .props('groups')
+ .props('items')
.find((group) => group.id === groupId);
afterEach(() => {
@@ -189,7 +189,7 @@ describe('GroupsView', () => {
await waitForPromises();
expect(findGroupsList().props()).toMatchObject({
- groups: formatGroups(nodes),
+ items: formatGroups(nodes),
showGroupIcon: true,
listItemClass: defaultPropsData.listItemClass,
timestampType: TIMESTAMP_TYPE_CREATED_AT,
diff --git a/spec/frontend/organizations/shared/components/projects_view_spec.js b/spec/frontend/organizations/shared/components/projects_view_spec.js
index b5ab96ba7ea..b4779213a73 100644
--- a/spec/frontend/organizations/shared/components/projects_view_spec.js
+++ b/spec/frontend/organizations/shared/components/projects_view_spec.js
@@ -164,7 +164,7 @@ describe('ProjectsView', () => {
await waitForPromises();
expect(findProjectsList().props()).toMatchObject({
- projects: formatProjects(nodes),
+ items: formatProjects(nodes),
showProjectIcon: true,
listItemClass: defaultPropsData.listItemClass,
timestampType: TIMESTAMP_TYPE_CREATED_AT,
diff --git a/spec/frontend/profile/components/overview_tab_spec.js b/spec/frontend/profile/components/overview_tab_spec.js
index 28c99fec959..17dcf7353b6 100644
--- a/spec/frontend/profile/components/overview_tab_spec.js
+++ b/spec/frontend/profile/components/overview_tab_spec.js
@@ -86,7 +86,7 @@ describe('OverviewTab', () => {
wrapper
.findByTestId('personal-projects-section')
.findComponent(ProjectsList)
- .props('projects'),
+ .props('items'),
).toMatchObject(defaultPropsData.personalProjects);
});
});
diff --git a/spec/frontend/projects/your_work/components/app_spec.js b/spec/frontend/projects/your_work/components/app_spec.js
index 03d9f1a1cbd..197a0fe130b 100644
--- a/spec/frontend/projects/your_work/components/app_spec.js
+++ b/spec/frontend/projects/your_work/components/app_spec.js
@@ -1,5 +1,6 @@
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import YourWorkProjectsApp from '~/projects/your_work/components/app.vue';
+import { PROJECT_DASHBOARD_TABS } from '~/projects/your_work/constants';
import TabsWithList from '~/groups_projects/components/tabs_with_list.vue';
describe('YourWorkProjectsApp', () => {
@@ -13,7 +14,9 @@ describe('YourWorkProjectsApp', () => {
createComponent();
});
- it('renders TabsWithList component', () => {
- expect(wrapper.findComponent(TabsWithList).exists()).toBe(true);
+ it('renders TabsWithList component and passes correct props', () => {
+ expect(wrapper.findComponent(TabsWithList).props()).toEqual({
+ tabs: PROJECT_DASHBOARD_TABS,
+ });
});
});
diff --git a/spec/frontend/search/topbar/components/app_spec.js b/spec/frontend/search/topbar/components/app_spec.js
index da2d3e12ffc..49500411c4b 100644
--- a/spec/frontend/search/topbar/components/app_spec.js
+++ b/spec/frontend/search/topbar/components/app_spec.js
@@ -8,7 +8,7 @@ import { stubComponent } from 'helpers/stub_component';
import GlobalSearchTopbar from '~/search/topbar/components/app.vue';
import MarkdownDrawer from '~/vue_shared/components/markdown_drawer/markdown_drawer.vue';
import SearchTypeIndicator from '~/search/topbar/components/search_type_indicator.vue';
-import GlSearchBoxByType from '~/search/topbar/components/search_box_by_type.vue';
+import GlobalSearchInput from '~/search/topbar/components/global_search_input.vue';
import { ENTER_KEY } from '~/lib/utils/keys';
import {
SYNTAX_OPTIONS_ADVANCED_DOCUMENT,
@@ -54,7 +54,7 @@ describe('GlobalSearchTopbar', () => {
});
};
- const findGlSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
+ const findGlSearchBox = () => wrapper.findComponent(GlobalSearchInput);
const findSyntaxOptionButton = () => wrapper.findComponent(GlButton);
const findSyntaxOptionDrawer = () => wrapper.findComponent(MarkdownDrawer);
const findSearchTypeIndicator = () => wrapper.findComponent(SearchTypeIndicator);
@@ -208,7 +208,7 @@ describe('GlobalSearchTopbar', () => {
beforeEach(() => {
createComponent({
initialState: { query: { search }, searchType: 'zoekt' },
- stubs: { GlSearchBoxByType },
+ stubs: { GlobalSearchInput },
});
});
diff --git a/spec/frontend/search/topbar/components/search_box_by_type_spec.js b/spec/frontend/search/topbar/components/search_box_by_type_spec.js
index 80a18bfab3c..af1fbb726ff 100644
--- a/spec/frontend/search/topbar/components/search_box_by_type_spec.js
+++ b/spec/frontend/search/topbar/components/search_box_by_type_spec.js
@@ -6,16 +6,16 @@ import { mount, shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { GlLoadingIcon } from '@gitlab/ui';
import ClearIcon from '~/search/topbar/components/clear_icon_button.vue';
-import SearchBoxByType from '~/search/topbar/components/search_box_by_type.vue';
+import GlobalSearchInput from '~/search/topbar/components/global_search_input.vue';
-const modelEvent = SearchBoxByType.model.event;
+const modelEvent = GlobalSearchInput.model.event;
const newValue = 'new value';
describe('search box by type component', () => {
let wrapper;
const createComponent = ({ listeners, ...propsData }, mountFn = shallowMount) => {
- wrapper = mountFn(SearchBoxByType, { propsData, listeners });
+ wrapper = mountFn(GlobalSearchInput, { propsData, listeners });
};
const findClearIcon = () => wrapper.findComponent(ClearIcon);
diff --git a/spec/frontend/vue_shared/components/groups_list/groups_list_spec.js b/spec/frontend/vue_shared/components/groups_list/groups_list_spec.js
index 39ed03bd2b3..bda44a4bfdc 100644
--- a/spec/frontend/vue_shared/components/groups_list/groups_list_spec.js
+++ b/spec/frontend/vue_shared/components/groups_list/groups_list_spec.js
@@ -8,7 +8,7 @@ describe('GroupsList', () => {
let wrapper;
const defaultPropsData = {
- groups,
+ items: groups,
listItemClass: 'gl-px-5',
};
@@ -27,7 +27,7 @@ describe('GroupsList', () => {
);
expect(expectedProps).toEqual(
- defaultPropsData.groups.map((group) => ({
+ defaultPropsData.items.map((group) => ({
group,
showGroupIcon: false,
listItemClass: defaultPropsData.listItemClass,
@@ -37,7 +37,7 @@ describe('GroupsList', () => {
});
describe('when `GroupsListItem` emits `delete` event', () => {
- const [firstGroup] = defaultPropsData.groups;
+ const [firstGroup] = defaultPropsData.items;
beforeEach(() => {
createComponent();
diff --git a/spec/frontend/vue_shared/components/projects_list/projects_list_spec.js b/spec/frontend/vue_shared/components/projects_list/projects_list_spec.js
index f54f17de57f..6948941eda1 100644
--- a/spec/frontend/vue_shared/components/projects_list/projects_list_spec.js
+++ b/spec/frontend/vue_shared/components/projects_list/projects_list_spec.js
@@ -9,7 +9,7 @@ describe('ProjectsList', () => {
let wrapper;
const defaultPropsData = {
- projects: convertObjectPropsToCamelCase(projects, { deep: true }),
+ items: convertObjectPropsToCamelCase(projects, { deep: true }),
listItemClass: 'gl-px-5',
};
@@ -28,7 +28,7 @@ describe('ProjectsList', () => {
);
expect(expectedProps).toEqual(
- defaultPropsData.projects.map((project) => ({
+ defaultPropsData.items.map((project) => ({
project,
showProjectIcon: false,
listItemClass: defaultPropsData.listItemClass,
diff --git a/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js b/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
index 815198662cf..bb9d4f70b03 100644
--- a/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
+++ b/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
@@ -296,6 +296,52 @@ describe('Upload dropzone component', () => {
});
});
+ describe('file input change', () => {
+ // See note in the 'updates file input files value' test for more details
+ // on why this function exists.
+ const stubFileInputOnWrapper = (files = []) => {
+ Object.defineProperty(wrapper.vm.$refs.fileUpload, 'files', {
+ writable: true,
+ value: files,
+ });
+ };
+ const validFile = { type: 'image/jpg' };
+ const invalidFile = { type: 'audio/midi' };
+
+ describe('when all uploaded files are valid', () => {
+ it('emits change event with valid files', () => {
+ createComponent();
+
+ stubFileInputOnWrapper([validFile, validFile]);
+ findFileInput().trigger('change');
+
+ expect(wrapper.emitted('change')).toEqual([[[validFile, validFile]]]);
+ });
+
+ it('emits single file when singleFileSelection is true', () => {
+ createComponent({
+ props: { singleFileSelection: true },
+ });
+
+ stubFileInputOnWrapper([validFile]);
+ findFileInput().trigger('change');
+
+ expect(wrapper.emitted('change')).toEqual([[validFile]]);
+ });
+ });
+
+ describe('when some uploaded files are invalid', () => {
+ it('emits error event when some uploaded files are invalid', () => {
+ createComponent();
+
+ stubFileInputOnWrapper([validFile, invalidFile]);
+ findFileInput().trigger('change');
+
+ expect(wrapper.emitted('error')).toHaveLength(1);
+ });
+ });
+ });
+
describe('updates file input files value', () => {
// NOTE: the component assigns dropped files from the drop event to the
// input.files property. There's a restriction that nothing but a FileList
diff --git a/spec/lib/gitlab/grape_logging/loggers/response_logger_spec.rb b/spec/lib/gitlab/grape_logging/loggers/response_logger_spec.rb
deleted file mode 100644
index 449096a6faf..00000000000
--- a/spec/lib/gitlab/grape_logging/loggers/response_logger_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::GrapeLogging::Loggers::ResponseLogger do
- let(:logger) { described_class.new }
-
- describe '#parameters' do
- let(:response1) { 'response1' }
- let(:response) { [response1] }
-
- subject { logger.parameters(nil, response) }
-
- it { expect(subject).to eq({ response_bytes: response1.bytesize }) }
-
- context 'with multiple response parts' do
- let(:response2) { 'response2' }
- let(:response) { [response1, response2] }
-
- it { expect(subject).to eq({ response_bytes: response1.bytesize + response2.bytesize }) }
- end
-
- context 'with log_response_length disabled' do
- before do
- stub_feature_flags(log_response_length: false)
- end
-
- it { expect(subject).to eq({}) }
- end
-
- context 'when response is a String' do
- let(:response) { response1 }
-
- it { expect(subject).to eq({ response_bytes: response1.bytesize }) }
- end
- end
-end
diff --git a/spec/lib/gitlab/lograge/custom_options_spec.rb b/spec/lib/gitlab/lograge/custom_options_spec.rb
index 090b79c5d3c..58b05be6ff9 100644
--- a/spec/lib/gitlab/lograge/custom_options_spec.rb
+++ b/spec/lib/gitlab/lograge/custom_options_spec.rb
@@ -25,8 +25,7 @@ RSpec.describe Gitlab::Lograge::CustomOptions do
remote_ip: '192.168.1.2',
ua: 'Nyxt',
queue_duration_s: 0.2,
- etag_route: '/etag',
- response_bytes: 1234
+ etag_route: '/etag'
}
end
@@ -56,20 +55,6 @@ RSpec.describe Gitlab::Lograge::CustomOptions do
expect(subject[:user_id]).to eq('test')
end
- it 'adds the response length' do
- expect(subject[:response_bytes]).to eq(1234)
- end
-
- context 'with log_response_length disabled' do
- before do
- stub_feature_flags(log_response_length: false)
- end
-
- it 'does not add the response length' do
- expect(subject).not_to include(:response_bytes)
- end
- end
-
it 'adds Cloudflare headers' do
expect(subject[:cf_ray]).to eq(event.payload[:cf_ray])
expect(subject[:cf_request_id]).to eq(event.payload[:cf_request_id])
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index f5397bb73c6..433cf17ce2d 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -1779,7 +1779,18 @@ RSpec.describe ApplicationSetting, feature_category: :shared, type: :model do
describe '#vscode_extension_marketplace' do
let(:invalid_custom) { { enabled: false, preset: "custom", custom_values: {} } }
- let(:valid_open_vsx) { { enabled: true, preset: "open_vsx" } }
+ let(:invalid_custom_urls) do
+ {
+ enabled: true,
+ preset: "custom",
+ custom_values: {
+ item_url: "abc",
+ service_url: "def",
+ resource_url_template: "ghi"
+ }
+ }
+ end
+
let(:valid_custom) do
{
enabled: false,
@@ -1792,15 +1803,20 @@ RSpec.describe ApplicationSetting, feature_category: :shared, type: :model do
}
end
+ let(:valid_open_vsx) { { enabled: true, preset: "open_vsx" } }
+ let(:valid_open_vsx_with_custom) { valid_custom.merge(valid_open_vsx) }
+
# valid json
it { is_expected.to allow_value({}).for(:vscode_extension_marketplace) }
- it { is_expected.to allow_value({ enabled: true, preset: "open_vsx" }).for(:vscode_extension_marketplace) }
+ it { is_expected.to allow_value(valid_open_vsx).for(:vscode_extension_marketplace) }
+ it { is_expected.to allow_value(valid_open_vsx_with_custom).for(:vscode_extension_marketplace) }
it { is_expected.to allow_value(valid_custom).for(:vscode_extension_marketplace) }
# invalid json
it { is_expected.not_to allow_value({ enabled: false, preset: "foo" }).for(:vscode_extension_marketplace) }
it { is_expected.not_to allow_value({ enabled: true, preset: "custom" }).for(:vscode_extension_marketplace) }
it { is_expected.not_to allow_value(invalid_custom).for(:vscode_extension_marketplace) }
+ it { is_expected.not_to allow_value(invalid_custom_urls).for(:vscode_extension_marketplace) }
end
describe '#vscode_extension_marketplace_enabled' do
diff --git a/spec/support/known_rspec_metadata_keys.yml b/spec/support/known_rspec_metadata_keys.yml
index 8386cc9c81a..c3aef5d2484 100644
--- a/spec/support/known_rspec_metadata_keys.yml
+++ b/spec/support/known_rspec_metadata_keys.yml
@@ -101,11 +101,9 @@
- :quarantine
- :query_analyzers
- :rd_fast
-- :real_ai_request
- :redis
- :reestablished_active_record_base
- :request_store
-- :requires_custom_models_setup
- :rerun_file_path
- :retry
- :retry_attempts
diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml
index 2f2104bb8ad..bc7c0e7de11 100644
--- a/spec/support/rspec_order_todo.yml
+++ b/spec/support/rspec_order_todo.yml
@@ -5052,7 +5052,6 @@
- './spec/lib/gitlab/grape_logging/loggers/exception_logger_spec.rb'
- './spec/lib/gitlab/grape_logging/loggers/perf_logger_spec.rb'
- './spec/lib/gitlab/grape_logging/loggers/queue_duration_logger_spec.rb'
-- './spec/lib/gitlab/grape_logging/loggers/response_logger_spec.rb'
- './spec/lib/gitlab/grape_logging/loggers/token_logger_spec.rb'
- './spec/lib/gitlab/grape_logging/loggers/urgency_logger_spec.rb'
- './spec/lib/gitlab/graphs/commits_spec.rb'