From fcf155c6b7e7041af6f09831170bf6d2bc1f2889 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 3 Dec 2024 15:30:51 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .../access_tokens/components/constants.js | 8 ++ .../components/new_access_token_app.vue | 5 + .../vue_shared/components/crud_component.vue | 2 +- .../admin/impersonation_tokens_controller.rb | 2 +- .../concerns/access_tokens_actions.rb | 21 +++- .../concerns/integrations/params.rb | 1 + .../settings/access_tokens_controller.rb | 4 + .../settings/access_tokens_controller.rb | 4 + .../personal_access_tokens_controller.rb | 3 +- app/models/integrations/datadog.rb | 105 +++++++++++++++--- app/serializers/group_access_token_entity.rb | 10 ++ .../project_access_token_entity.rb | 12 ++ .../personal_access_tokens/create_service.rb | 3 +- .../resource_access_tokens/create_service.rb | 3 +- .../shared/access_tokens/_form.html.haml | 4 + .../development/issue_email_participants.yml | 2 +- .../service_desk_custom_email_reply.yml | 2 +- .../development/service_desk_ticket.yml | 2 +- config/routes/group.rb | 1 + config/routes/project.rb | 1 + config/sidekiq_queues.yml | 4 + .../15-9-ci-builds-column-validations.yml | 2 +- ...fications_on_issue_email_participant_id.rb | 2 + ...d_description_to_personal_access_tokens.rb | 20 ++++ ...ge_request_diffs_project_id_index_async.rb | 2 + ...dd_merge_request_diffs_project_id_index.rb | 2 + ...re_iid_namespace_unique_index_in_issues.rb | 2 + ...dd_iid_namespace_unique_index_to_issues.rb | 2 + ...hor_group_action_target_type_created_at.rb | 2 +- ..._with_project_id_on_vulnerability_reads.rb | 2 + ..._events_author_group_action_target_type.rb | 2 +- ...ndex_on_issues_table_tmp_epic_id_column.rb | 2 + ...dex_merge_requests_on_unmerged_state_id.rb | 2 + ...dex_merge_requests_on_unmerged_state_id.rb | 2 + ...rt_type_severity_traversal_ids_archived.rb | 2 + ...lity_reads_for_common_group_level_query.rb | 2 + ...14121644_replace_issues_milestone_index.rb | 2 +- ...ues_milestone_and_id_index_concurrently.rb | 2 +- ...ulnerability_occurences_on_prim_iden_id.rb | 2 +- ...ex_owasp_top_10_for_group_level_reports.rb | 2 + ...033346_tmp_index_on_vulnerability_reads.rb | 2 + ...lnerability_finding_links_on_project_id.rb | 2 + ..._index_for_owasp_on_vulnerability_reads.rb | 2 + ...dx_owasp_top_10_for_group_level_reports.rb | 2 + ...index_on_events_personal_namespace_id_2.rb | 2 +- ...ents_personal_namespace_id_self_managed.rb | 2 +- ...ulnerability_reads_for_filtered_removal.rb | 2 + ...es_by_project_correct_type_where_closed.rb | 2 + ...oject_health_id_desc_state_correct_type.rb | 2 + ...roject_health_id_asc_state_correct_type.rb | 2 + ...s_correct_type_project_created_at_state.rb | 2 + ...es_by_project_correct_type_where_closed.rb | 2 + ...oject_health_id_desc_state_correct_type.rb | 2 + ...roject_health_id_asc_state_correct_type.rb | 2 + ...s_correct_type_project_created_at_state.rb | 2 + ...te_sent_notifications_index_on_noteable.rb | 2 + ...cations_index_on_noteable_synchronously.rb | 2 + db/schema_migrations/20241121071110 | 1 + db/structure.sql | 2 + .../backup_restore/backup_gitlab.md | 6 +- doc/administration/cicd/job_logs.md | 7 +- .../geo/disaster_recovery/index.md | 4 +- doc/administration/geo/index.md | 11 +- .../geo/replication/troubleshooting/common.md | 4 +- .../geo/secondary_proxy/index.md | 9 +- .../gitaly/gitaly_geo_capabilities.md | 2 +- doc/administration/gitaly/index.md | 6 +- .../operations/fast_ssh_key_lookup.md | 2 +- .../settings/sign_in_restrictions.md | 8 +- doc/api/graphql/reference/index.md | 8 +- doc/api/integrations.md | 1 + doc/api/members.md | 9 +- doc/api/openapi/openapi_v2.yaml | 10 ++ doc/api/personal_access_tokens.md | 6 + doc/api/user_tokens.md | 9 ++ doc/ci/ci_cd_for_external_repos/index.md | 4 +- doc/ci/jobs/index.md | 4 +- doc/ci/resource_groups/index.md | 6 +- doc/ci/yaml/index.md | 2 +- doc/development/dangerbot.md | 4 +- .../database/pagination_guidelines.md | 4 +- doc/development/fe_guide/index.md | 2 +- doc/development/graphql_guide/pagination.md | 6 +- .../internal_analytics/service_ping/index.md | 2 +- doc/development/python_guide/index.md | 11 ++ .../testing_guide/frontend_testing.md | 6 +- doc/integration/datadog.md | 29 +++-- doc/update/deprecations.md | 2 +- doc/user/analytics/ai_impact_analytics.md | 4 +- .../browser/configuration/authentication.md | 6 +- .../experiment_libbehave_dependency.md | 11 +- doc/user/clusters/agent/vulnerabilities.md | 6 +- .../import/direct_transfer_migrations.md | 2 +- doc/user/group/import/troubleshooting.md | 2 +- doc/user/group/moderate_users.md | 2 +- doc/user/namespace/index.md | 15 +-- doc/user/profile/notifications.md | 12 +- doc/user/project/index.md | 4 +- .../ml/experiment_tracking/mlflow_client.md | 2 +- doc/user/project/working_with_projects.md | 2 +- doc/user/reserved_names.md | 2 +- lib/api/entities/personal_access_token.rb | 1 + lib/api/resource_access_tokens.rb | 4 + lib/api/users.rb | 3 + locale/gitlab.pot | 58 +++++++--- .../cop/migration/prevent_index_creation.rb | 2 +- rubocop/migration_helpers.rb | 8 +- .../personal_access_tokens_controller_spec.rb | 6 +- spec/factories/integrations.rb | 1 + spec/factories/personal_access_tokens.rb | 1 + .../groups/settings/access_tokens_spec.rb | 18 +++ .../projects/settings/access_tokens_spec.rb | 18 +++ .../personal_access_tokens_spec.rb | 8 +- .../public_api/v4/resource_access_token.json | 56 ++++++++-- .../components/access_token_table_app_spec.js | 82 ++++++++------ .../inactive_access_token_table_app_spec.js | 23 ++-- .../components/new_access_token_app_spec.js | 3 + .../entities/personal_access_token_spec.rb | 3 +- spec/models/integrations/datadog_spec.rb | 50 ++++++++- spec/models/personal_access_token_spec.rb | 1 + spec/requests/api/ci/runners_spec.rb | 4 +- spec/requests/api/users_spec.rb | 15 ++- .../settings/access_tokens_controller_spec.rb | 2 +- .../settings/access_tokens_controller_spec.rb | 2 +- .../migration/prevent_index_creation_spec.rb | 2 +- .../group_access_token_entity_spec.rb | 26 +++-- .../personal_access_token_entity_spec.rb | 1 + .../project_access_token_entity_spec.rb | 30 +++-- .../create_service_spec.rb | 12 +- .../create_service_spec.rb | 16 +++ .../authn/token_shared_examples.rb | 42 +++++++ .../integrations_actions_shared_examples.rb | 10 +- ...ccess_tokens_controller_shared_examples.rb | 1 + .../common_system_notes_shared_examples.rb | 24 ++-- 134 files changed, 820 insertions(+), 259 deletions(-) create mode 100644 db/migrate/20241121071110_add_description_to_personal_access_tokens.rb create mode 100644 db/schema_migrations/20241121071110 diff --git a/app/assets/javascripts/access_tokens/components/constants.js b/app/assets/javascripts/access_tokens/components/constants.js index 4efece86d02..f131b3d6dab 100644 --- a/app/assets/javascripts/access_tokens/components/constants.js +++ b/app/assets/javascripts/access_tokens/components/constants.js @@ -13,6 +13,14 @@ const BASE_FIELDS = [ label: __('Token name'), sortable: true, }, + { + formatter(description) { + return description ?? '-'; + }, + key: 'description', + label: __('Description'), + sortable: true, + }, { formatter(scopes) { return scopes?.length ? scopes.join(', ') : __('no scopes selected'); diff --git a/app/assets/javascripts/access_tokens/components/new_access_token_app.vue b/app/assets/javascripts/access_tokens/components/new_access_token_app.vue index fd1e055609a..d705b9a11ba 100644 --- a/app/assets/javascripts/access_tokens/components/new_access_token_app.vue +++ b/app/assets/javascripts/access_tokens/components/new_access_token_app.vue @@ -112,6 +112,11 @@ export default { this.form.querySelectorAll('input[type=text]:not([id$=expires_at])').forEach((el) => { el.value = ''; }); + + this.form.querySelectorAll('textarea').forEach((el) => { + el.value = ''; + }); + this.form.querySelectorAll('input[type=checkbox]').forEach((el) => { el.checked = false; }); diff --git a/app/assets/javascripts/vue_shared/components/crud_component.vue b/app/assets/javascripts/vue_shared/components/crud_component.vue index 327c5684935..b9f66fb7dad 100644 --- a/app/assets/javascripts/vue_shared/components/crud_component.vue +++ b/app/assets/javascripts/vue_shared/components/crud_component.vue @@ -194,7 +194,7 @@ export default { data-testid="crud-count" > diff --git a/app/controllers/admin/impersonation_tokens_controller.rb b/app/controllers/admin/impersonation_tokens_controller.rb index a8939edc433..e70de04da1b 100644 --- a/app/controllers/admin/impersonation_tokens_controller.rb +++ b/app/controllers/admin/impersonation_tokens_controller.rb @@ -59,7 +59,7 @@ class Admin::ImpersonationTokensController < Admin::ApplicationController end def impersonation_token_params - params.require(:personal_access_token).permit(:name, :expires_at, :impersonation, scopes: []) + params.require(:personal_access_token).permit(:name, :description, :expires_at, :impersonation, scopes: []) end def set_index_vars diff --git a/app/controllers/concerns/access_tokens_actions.rb b/app/controllers/concerns/access_tokens_actions.rb index 45b4180f111..b340d2800cf 100644 --- a/app/controllers/concerns/access_tokens_actions.rb +++ b/app/controllers/concerns/access_tokens_actions.rb @@ -6,6 +6,7 @@ module AccessTokensActions included do before_action -> { check_permission(:read_resource_access_tokens) }, only: [:index] before_action -> { check_permission(:destroy_resource_access_tokens) }, only: [:revoke] + before_action -> { check_permission(:manage_resource_access_tokens) }, only: [:rotate] before_action -> { check_permission(:create_resource_access_tokens) }, only: [:create] before_action do push_frontend_feature_flag(:retain_resource_access_token_user_after_revoke, resource.root_ancestor) @@ -56,6 +57,20 @@ module AccessTokensActions end # rubocop:enable Gitlab/ModuleWithInstanceVariables + def rotate + token = finder.find(rotate_params[:id]) + result = rotate_service.new(current_user, token, resource, keep_token_lifetime: true).execute + resource_access_token = result.payload[:personal_access_token] + + if result.success? + tokens, size = active_access_tokens + render json: { new_token: resource_access_token.token, + active_access_tokens: tokens, total: size }, status: :ok + else + render json: { message: result.message }, status: :unprocessable_entity + end + end + private def check_permission(action) @@ -63,7 +78,11 @@ module AccessTokensActions end def create_params - params.require(:resource_access_token).permit(:name, :expires_at, :access_level, scopes: []) + params.require(:resource_access_token).permit(:name, :expires_at, :description, :access_level, scopes: []) + end + + def rotate_params + params.permit(:id) end # rubocop:disable Gitlab/ModuleWithInstanceVariables diff --git a/app/controllers/concerns/integrations/params.rb b/app/controllers/concerns/integrations/params.rb index 02c2efd1333..6ae7452f7a8 100644 --- a/app/controllers/concerns/integrations/params.rb +++ b/app/controllers/concerns/integrations/params.rb @@ -35,6 +35,7 @@ module Integrations :datadog_env, :datadog_service, :datadog_tags, + :datadog_ci_visibility, :default_irc_uri, :device, :disable_diffs, diff --git a/app/controllers/groups/settings/access_tokens_controller.rb b/app/controllers/groups/settings/access_tokens_controller.rb index ff07e881bfa..e53d265d67c 100644 --- a/app/controllers/groups/settings/access_tokens_controller.rb +++ b/app/controllers/groups/settings/access_tokens_controller.rb @@ -20,6 +20,10 @@ module Groups def represent(tokens) ::GroupAccessTokenSerializer.new.represent(tokens, group: resource) end + + def rotate_service + GroupAccessTokens::RotateService + end end end end diff --git a/app/controllers/projects/settings/access_tokens_controller.rb b/app/controllers/projects/settings/access_tokens_controller.rb index af1527ba6a3..4e12a5a494e 100644 --- a/app/controllers/projects/settings/access_tokens_controller.rb +++ b/app/controllers/projects/settings/access_tokens_controller.rb @@ -20,6 +20,10 @@ module Projects def represent(tokens) ::ProjectAccessTokenSerializer.new.represent(tokens, project: resource) end + + def rotate_service + ProjectAccessTokens::RotateService + end end end end diff --git a/app/controllers/user_settings/personal_access_tokens_controller.rb b/app/controllers/user_settings/personal_access_tokens_controller.rb index 55d5afd5a14..d764e0ac741 100644 --- a/app/controllers/user_settings/personal_access_tokens_controller.rb +++ b/app/controllers/user_settings/personal_access_tokens_controller.rb @@ -15,6 +15,7 @@ module UserSettings scopes = params[:scopes].split(',').map(&:squish).select(&:present?).map(&:to_sym) unless params[:scopes].nil? @personal_access_token = finder.build( name: params[:name], + description: params[:description], scopes: scopes ) @@ -83,7 +84,7 @@ module UserSettings end def personal_access_token_params - params.require(:personal_access_token).permit(:name, :expires_at, scopes: []) + params.require(:personal_access_token).permit(:name, :expires_at, :description, scopes: []) end def set_index_vars diff --git a/app/models/integrations/datadog.rb b/app/models/integrations/datadog.rb index 7f4284f9ec1..727f5c0683b 100644 --- a/app/models/integrations/datadog.rb +++ b/app/models/integrations/datadog.rb @@ -7,32 +7,55 @@ module Integrations DEFAULT_DOMAIN = 'datadoghq.com' URL_TEMPLATE = 'https://webhook-intake.%{datadog_domain}/api/v2/webhook' URL_API_KEYS_DOCS = "https://docs.#{DEFAULT_DOMAIN}/account_management/api-app-keys/" + CI_LOGS_DOCS = "https://docs.#{DEFAULT_DOMAIN}/continuous_integration/pipelines/gitlab/?tab=gitlabcom#collect-job-logs" + CI_VISIBILITY_PRICING = "https://www.#{DEFAULT_DOMAIN}/pricing/?product=ci-pipeline-visibility#products" + SITES_DOCS = "https://docs.#{DEFAULT_DOMAIN}/getting_started/site/" SUPPORTED_EVENTS = %w[ - pipeline build archive_trace + pipeline build archive_trace push merge_request note tag_push subgroup project ].freeze TAG_KEY_VALUE_RE = %r{\A [\w-]+ : .*\S.* \z}x + # The config is divided in two sections: + # - General account configuration, which allows setting up a Datadog site and API key + # - CI Visibility configuration, which is specific to job & pipeline events + def sections + [ + { + type: SECTION_TYPE_CONNECTION, + title: s_('DatadogIntegration|Datadog account'), + description: help + }, + { + type: SECTION_TYPE_CONFIGURATION, + title: s_('DatadogIntegration|CI Visibility'), + description: s_('DatadogIntegration|Additionally, enable CI Visibility to send pipeline information to Datadog to monitor for job failures and troubleshoot performance issues.') + } + ] + end + + # General account configuration field :datadog_site, exposes_secrets: true, + section: SECTION_TYPE_CONNECTION, placeholder: DEFAULT_DOMAIN, help: -> do - ERB::Util.html_escape( - s_('DatadogIntegration|Datadog site to send data to. To send data to the EU site, use %{codeOpen}datadoghq.eu%{codeClose}.') - ) % { - codeOpen: ''.html_safe, - codeClose: ''.html_safe - } + docs_link = ActionController::Base.helpers.link_to('', SITES_DOCS, target: '_blank', rel: 'noopener noreferrer') + tag_pair_docs_link = tag_pair(docs_link, :link_start, :link_end) + + safe_format(s_('DatadogIntegration|Datadog site to send data to. Learn more about Datadog sites in the %{link_start}documentation%{link_end}.'), tag_pair_docs_link) end field :api_url, exposes_secrets: true, + section: SECTION_TYPE_CONNECTION, title: -> { s_('DatadogIntegration|API URL') }, - help: -> { s_('DatadogIntegration|Full URL of your Datadog site.') } + help: -> { s_('DatadogIntegration|Full URL of your Datadog site. Only required if you do not use a standard Datadog site.') } field :api_key, type: :password, + section: SECTION_TYPE_CONNECTION, title: -> { _('API key') }, non_empty_password_title: -> { s_('ProjectService|Enter new API key') }, non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current API key') }, @@ -44,25 +67,47 @@ module Integrations end, required: true + # CI Visibility section + field :datadog_ci_visibility, + type: :checkbox, + section: SECTION_TYPE_CONFIGURATION, + title: -> { s_('DatadogIntegration|Enabled') }, + checkbox_label: -> { s_('DatadogIntegration|Enable CI Visibility') }, + description: -> { _('Enable CI Visibility') }, + help: -> do + docs_link = ActionController::Base.helpers.link_to('', CI_VISIBILITY_PRICING, target: '_blank', rel: 'noopener noreferrer') + tag_pair_docs_link = tag_pair(docs_link, :link_start, :link_end) + + safe_format(s_('DatadogIntegration|When enabled, pipelines and jobs are collected, and Datadog will display pipeline execution traces. Note that CI Visibility is priced per committers, see our %{link_start}pricing page%{link_end}.'), tag_pair_docs_link) + end + field :archive_trace_events, storage: :attribute, type: :checkbox, + section: SECTION_TYPE_CONFIGURATION, title: -> { _('Logs') }, - checkbox_label: -> { _('Enable logs collection') }, - help: -> { s_('When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces.') } + checkbox_label: -> { _('Enable Pipeline Job logs collection') }, + help: -> do + docs_link = ActionController::Base.helpers.link_to('', CI_LOGS_DOCS, target: '_blank', rel: 'noopener noreferrer') + tag_pair_docs_link = tag_pair(docs_link, :link_start, :link_end) + + safe_format(s_('DatadogIntegration|When enabled, pipeline job logs are collected by Datadog and displayed along with pipeline execution traces. This requires CI Visibility to be enabled. Note that pipeline job logs are priced like regular Datadog logs. Learn more %{link_start}here%{link_end}.'), tag_pair_docs_link) + end field :datadog_service, title: -> { s_('DatadogIntegration|Service') }, + section: SECTION_TYPE_CONFIGURATION, placeholder: 'gitlab-ci', - help: -> { s_('DatadogIntegration|GitLab instance to tag all data from in Datadog. Can be used when managing several self-managed deployments.') } + help: -> { s_('DatadogIntegration|Tag all pipeline data from this GitLab instance in Datadog. Can be used when managing several self-managed deployments.') } field :datadog_env, title: -> { s_('DatadogIntegration|Environment') }, + section: SECTION_TYPE_CONFIGURATION, placeholder: 'ci', description: -> { _('For self-managed deployments, `env` tag for all the data sent to Datadog.') }, help: -> do ERB::Util.html_escape( - s_('DatadogIntegration|For self-managed deployments, set the %{codeOpen}env%{codeClose} tag for all the data sent to Datadog. %{linkOpen}How do I use tags?%{linkClose}') + s_('DatadogIntegration|For self-managed deployments, set the %{codeOpen}env%{codeClose} tag for all the pipeline data sent to Datadog. %{linkOpen}How do I use tags?%{linkClose}') ) % { codeOpen: ''.html_safe, codeClose: ''.html_safe, @@ -73,12 +118,13 @@ module Integrations field :datadog_tags, type: :textarea, + section: SECTION_TYPE_CONFIGURATION, title: -> { s_('DatadogIntegration|Tags') }, placeholder: "tag:value\nanother_tag:value", description: -> { _('Custom tags in Datadog. Specify one tag per line in the format `key:value\nkey2:value2`.') }, help: -> do ERB::Util.html_escape( - s_('DatadogIntegration|Custom tags in Datadog. Enter one tag per line in the %{codeOpen}key:value%{codeClose} format. %{linkOpen}How do I use tags?%{linkClose}') + s_('DatadogIntegration|Custom tags for pipeline data in Datadog. Enter one tag per line in the %{codeOpen}key:value%{codeClose} format. %{linkOpen}How do I use tags?%{linkClose}') ) % { codeOpen: ''.html_safe, codeClose: ''.html_safe, @@ -95,13 +141,34 @@ module Integrations validates :api_url, public_url: { allow_blank: true } validates :datadog_site, presence: true, unless: ->(obj) { obj.api_url.present? } validates :api_url, presence: true, unless: ->(obj) { obj.datadog_site.present? } + validates :datadog_ci_visibility, inclusion: [true, false] validate :datadog_tags_are_valid + validate :logs_requires_ci_vis end def initialize_properties super self.datadog_site ||= DEFAULT_DOMAIN + + # Previous versions of the integration don't have the datadog_ci_visibility boolean stored in the configuration. + # Since the previous default was for this to be enabled, we want this attribute to be initialized to true + # if the integration was previously active. Otherwise, it should default to false. + if datadog_ci_visibility.nil? + self.datadog_ci_visibility = active + end + end + + attribute :pipeline_events, default: false + attribute :job_events, default: false + before_save :update_pipeline_events + + def update_pipeline_events + # pipeline and job events are opt-in, controlled by a single datadog_ci_visibility checkbox + unless datadog_ci_visibility.nil? + self.job_events = datadog_ci_visibility + self.pipeline_events = datadog_ci_visibility + end end def self.supported_events @@ -109,7 +176,7 @@ module Integrations end def self.default_test_event - 'pipeline' + 'push' end def configurable_events @@ -122,13 +189,13 @@ module Integrations end def self.description - s_('DatadogIntegration|Trace your GitLab pipelines with Datadog.') + s_('DatadogIntegration|Connect your projects to Datadog and trace your GitLab pipelines.') end def self.help build_help_page_url( 'integration/datadog.md', - s_('DatadogIntegration|Send CI/CD pipeline information to Datadog to monitor for job failures and troubleshoot performance issues.'), + s_('DatadogIntegration|Connect your GitLab projects to your Datadog account to synchronize repository metadata and enrich telemetry on your Datadog account.'), _('How do I set up this integration?') ) end @@ -219,5 +286,11 @@ module Integrations end end.join(',') end + + def logs_requires_ci_vis + if archive_trace_events && !datadog_ci_visibility + errors.add(:archive_trace_events, s_("DatadogIntegration|requires CI Visibility to be enabled")) + end + end end end diff --git a/app/serializers/group_access_token_entity.rb b/app/serializers/group_access_token_entity.rb index 83e8284e4e2..26141a265b0 100644 --- a/app/serializers/group_access_token_entity.rb +++ b/app/serializers/group_access_token_entity.rb @@ -14,6 +14,16 @@ class GroupAccessTokenEntity < AccessTokenEntityBase group_id: group.full_path) end + expose :rotate_path do |token, options| + group = options.fetch(:group) + + next unless group + + rotate_group_settings_access_token_path( + id: token, + group_id: group.full_path) + end + expose :role do |token, options| group = options.fetch(:group) diff --git a/app/serializers/project_access_token_entity.rb b/app/serializers/project_access_token_entity.rb index 548fb24173a..d7ccd62df04 100644 --- a/app/serializers/project_access_token_entity.rb +++ b/app/serializers/project_access_token_entity.rb @@ -15,6 +15,18 @@ class ProjectAccessTokenEntity < AccessTokenEntityBase project_id: project.path) end + expose :rotate_path do |token, options| + project = options.fetch(:project) + + next unless project + + rotate_namespace_project_settings_access_token_path( + id: token, + namespace_id: project.namespace.full_path, + project_id: project.path + ) + end + expose :role do |token, options| project = options.fetch(:project) diff --git a/app/services/personal_access_tokens/create_service.rb b/app/services/personal_access_tokens/create_service.rb index 9fd9c135640..a978b58e8d0 100644 --- a/app/services/personal_access_tokens/create_service.rb +++ b/app/services/personal_access_tokens/create_service.rb @@ -38,7 +38,8 @@ module PersonalAccessTokens impersonation: params[:impersonation] || false, scopes: params[:scopes], expires_at: pat_expiration, - organization_id: organization_id + organization_id: organization_id, + description: params[:description] } end diff --git a/app/services/resource_access_tokens/create_service.rb b/app/services/resource_access_tokens/create_service.rb index 2540113fea0..c7cfd99af86 100644 --- a/app/services/resource_access_tokens/create_service.rb +++ b/app/services/resource_access_tokens/create_service.rb @@ -102,7 +102,8 @@ module ResourceAccessTokens name: params[:name] || "#{resource_type}_bot", impersonation: false, scopes: params[:scopes] || default_scopes, - expires_at: pat_expiration + expires_at: pat_expiration, + description: params[:description] } end diff --git a/app/views/shared/access_tokens/_form.html.haml b/app/views/shared/access_tokens/_form.html.haml index 7f7152419e2..a0ec50f4b4b 100644 --- a/app/views/shared/access_tokens/_form.html.haml +++ b/app/views/shared/access_tokens/_form.html.haml @@ -23,6 +23,10 @@ - else = s_("AccessTokens|For example, the application using the token or the purpose of the token.") + .form-group + = f.label :description, s_('AccessTokens|Token description'), class: 'label-bold', data: { testid: 'access-token-description-field' } + = f.text_area :description, class: 'form-control gl-form-input', maxlength: 255, rows: 4 + .js-access-tokens-expires-at{ data: expires_at_field_data } = f.text_field :expires_at, class: 'form-control gl-form-input', placeholder: 'YYYY-MM-DD', autocomplete: 'off', data: { js_name: 'expiresAt' } diff --git a/config/feature_flags/development/issue_email_participants.yml b/config/feature_flags/development/issue_email_participants.yml index dff31e9d258..2d4238e2e6f 100644 --- a/config/feature_flags/development/issue_email_participants.yml +++ b/config/feature_flags/development/issue_email_participants.yml @@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49264 rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350460 milestone: '13.8' type: development -group: group::project_management +group: group::project management default_enabled: true diff --git a/config/feature_flags/development/service_desk_custom_email_reply.yml b/config/feature_flags/development/service_desk_custom_email_reply.yml index 238d5d4c80b..520dac83368 100644 --- a/config/feature_flags/development/service_desk_custom_email_reply.yml +++ b/config/feature_flags/development/service_desk_custom_email_reply.yml @@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/130336 rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/423880 milestone: '16.4' type: development -group: group::project_management +group: group::project management default_enabled: true diff --git a/config/feature_flags/development/service_desk_ticket.yml b/config/feature_flags/development/service_desk_ticket.yml index cc3ab6cd5ef..14d3341ed50 100644 --- a/config/feature_flags/development/service_desk_ticket.yml +++ b/config/feature_flags/development/service_desk_ticket.yml @@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124681 rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/416343 milestone: '16.2' type: development -group: group::project_management +group: group::project management default_enabled: false diff --git a/config/routes/group.rb b/config/routes/group.rb index b0bef2363a6..1bdb1568d4f 100644 --- a/config/routes/group.rb +++ b/config/routes/group.rb @@ -50,6 +50,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do resources :access_tokens, only: [:index, :create] do member do put :revoke + put :rotate end end diff --git a/config/routes/project.rb b/config/routes/project.rb index 024c36eae67..7f464eecd7c 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -156,6 +156,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do resources :access_tokens, only: [:index, :create] do member do put :revoke + put :rotate end end diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml index 75324f86eb2..5303f781036 100644 --- a/config/sidekiq_queues.yml +++ b/config/sidekiq_queues.yml @@ -379,6 +379,10 @@ - 1 - - gitlab_subscriptions_add_on_purchases_cleanup_user_add_on_assignment - 1 +- - gitlab_subscriptions_add_on_purchases_create_user_add_on_assignment + - 1 +- - gitlab_subscriptions_add_on_purchases_destroy_user_add_on_assignment + - 1 - - gitlab_subscriptions_add_on_purchases_email_on_duo_bulk_user_assignments - 1 - - gitlab_subscriptions_add_on_purchases_refresh_user_assignments diff --git a/data/deprecations/15-9-ci-builds-column-validations.yml b/data/deprecations/15-9-ci-builds-column-validations.yml index b94200dce8d..a006b2cc00f 100644 --- a/data/deprecations/15-9-ci-builds-column-validations.yml +++ b/data/deprecations/15-9-ci-builds-column-validations.yml @@ -11,7 +11,7 @@ stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372770 # (required) Link to the deprecation issue in GitLab body: | # (required) Do not modify this line, instead modify the lines below. - While CI/CD [job names](https://docs.gitlab.com/ee/ci/jobs/index.html#job-name-limitations) have a strict 255 character limit, other CI/CD parameters do not yet have validations ensuring they also stay under the limit. + While CI/CD [job names](https://docs.gitlab.com/ee/ci/jobs/index.html#job-name) have a strict 255 character limit, other CI/CD parameters do not yet have validations ensuring they also stay under the limit. In GitLab 16.0, validation will be added to strictly limit the following to 255 characters as well: diff --git a/db/migrate/20240104142200_add_index_sent_notifications_on_issue_email_participant_id.rb b/db/migrate/20240104142200_add_index_sent_notifications_on_issue_email_participant_id.rb index c9b75529470..7a564f13fb0 100644 --- a/db/migrate/20240104142200_add_index_sent_notifications_on_issue_email_participant_id.rb +++ b/db/migrate/20240104142200_add_index_sent_notifications_on_issue_email_participant_id.rb @@ -8,7 +8,9 @@ class AddIndexSentNotificationsOnIssueEmailParticipantId < Gitlab::Database::Mig INDEX_NAME = 'index_sent_notifications_on_issue_email_participant_id' def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :sent_notifications, :issue_email_participant_id, name: INDEX_NAME + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/migrate/20241121071110_add_description_to_personal_access_tokens.rb b/db/migrate/20241121071110_add_description_to_personal_access_tokens.rb new file mode 100644 index 00000000000..eb46d90e460 --- /dev/null +++ b/db/migrate/20241121071110_add_description_to_personal_access_tokens.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class AddDescriptionToPersonalAccessTokens < Gitlab::Database::Migration[2.2] + disable_ddl_transaction! + milestone '17.7' + + def up + with_lock_retries do + add_column :personal_access_tokens, :description, :text, if_not_exists: true + end + + add_text_limit :personal_access_tokens, :description, 255 + end + + def down + with_lock_retries do + remove_column :personal_access_tokens, :description, if_exists: true + end + end +end diff --git a/db/post_migrate/20231114034507_add_merge_request_diffs_project_id_index_async.rb b/db/post_migrate/20231114034507_add_merge_request_diffs_project_id_index_async.rb index 1c783b922ae..a55e56e600e 100644 --- a/db/post_migrate/20231114034507_add_merge_request_diffs_project_id_index_async.rb +++ b/db/post_migrate/20231114034507_add_merge_request_diffs_project_id_index_async.rb @@ -7,7 +7,9 @@ class AddMergeRequestDiffsProjectIdIndexAsync < Gitlab::Database::Migration[2.2] INDEX_NAME = 'index_merge_request_diffs_on_project_id' def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration prepare_async_index :merge_request_diffs, :project_id, name: INDEX_NAME + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20231121040153_add_merge_request_diffs_project_id_index.rb b/db/post_migrate/20231121040153_add_merge_request_diffs_project_id_index.rb index 5576e9d534e..b71e03e20fb 100644 --- a/db/post_migrate/20231121040153_add_merge_request_diffs_project_id_index.rb +++ b/db/post_migrate/20231121040153_add_merge_request_diffs_project_id_index.rb @@ -7,7 +7,9 @@ class AddMergeRequestDiffsProjectIdIndex < Gitlab::Database::Migration[2.2] INDEX_NAME = 'index_merge_request_diffs_on_project_id' def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :merge_request_diffs, :project_id, name: INDEX_NAME + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20231207155340_prepare_iid_namespace_unique_index_in_issues.rb b/db/post_migrate/20231207155340_prepare_iid_namespace_unique_index_in_issues.rb index a0149a79f83..d5e4aadc5c3 100644 --- a/db/post_migrate/20231207155340_prepare_iid_namespace_unique_index_in_issues.rb +++ b/db/post_migrate/20231207155340_prepare_iid_namespace_unique_index_in_issues.rb @@ -7,7 +7,9 @@ class PrepareIidNamespaceUniqueIndexInIssues < Gitlab::Database::Migration[2.2] # TODO: Index to be created synchronously in https://gitlab.com/gitlab-org/gitlab/-/issues/435856 def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration prepare_async_index :issues, [:namespace_id, :iid], unique: true, name: INDEX_NAME + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20231207211418_add_iid_namespace_unique_index_to_issues.rb b/db/post_migrate/20231207211418_add_iid_namespace_unique_index_to_issues.rb index 4c2439f33ea..490d91ea131 100644 --- a/db/post_migrate/20231207211418_add_iid_namespace_unique_index_to_issues.rb +++ b/db/post_migrate/20231207211418_add_iid_namespace_unique_index_to_issues.rb @@ -8,7 +8,9 @@ class AddIidNamespaceUniqueIndexToIssues < Gitlab::Database::Migration[2.2] milestone '16.8' def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :issues, [:namespace_id, :iid], name: INDEX_NAME, unique: true + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20231215130625_schedule_index_to_events_author_group_action_target_type_created_at.rb b/db/post_migrate/20231215130625_schedule_index_to_events_author_group_action_target_type_created_at.rb index 1e3658aa697..bddecce9c05 100644 --- a/db/post_migrate/20231215130625_schedule_index_to_events_author_group_action_target_type_created_at.rb +++ b/db/post_migrate/20231215130625_schedule_index_to_events_author_group_action_target_type_created_at.rb @@ -7,7 +7,7 @@ class ScheduleIndexToEventsAuthorGroupActionTargetTypeCreatedAt < Gitlab::Databa COLUMNS = [:author_id, :group_id, :action, :target_type, :created_at] def up - prepare_async_index :events, COLUMNS, name: INDEX_NAME + prepare_async_index :events, COLUMNS, name: INDEX_NAME # rubocop:disable Migration/PreventIndexCreation -- Legacy migration end def down diff --git a/db/post_migrate/20240104223119_add_index_owasp_top_10_with_project_id_on_vulnerability_reads.rb b/db/post_migrate/20240104223119_add_index_owasp_top_10_with_project_id_on_vulnerability_reads.rb index 99a2dccc8f5..7af57a7f400 100644 --- a/db/post_migrate/20240104223119_add_index_owasp_top_10_with_project_id_on_vulnerability_reads.rb +++ b/db/post_migrate/20240104223119_add_index_owasp_top_10_with_project_id_on_vulnerability_reads.rb @@ -8,7 +8,9 @@ class AddIndexOwaspTop10WithProjectIdOnVulnerabilityReads < Gitlab::Database::Mi INDEX_NAME = 'index_vuln_reads_on_project_id_owasp_top_10' def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :vulnerability_reads, [:project_id, :owasp_top_10], name: INDEX_NAME + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20240112143548_add_index_to_events_author_group_action_target_type.rb b/db/post_migrate/20240112143548_add_index_to_events_author_group_action_target_type.rb index 88e5f95ef68..70d7c325a68 100644 --- a/db/post_migrate/20240112143548_add_index_to_events_author_group_action_target_type.rb +++ b/db/post_migrate/20240112143548_add_index_to_events_author_group_action_target_type.rb @@ -9,7 +9,7 @@ class AddIndexToEventsAuthorGroupActionTargetType < Gitlab::Database::Migration[ COLUMNS = [:author_id, :group_id, :action, :target_type, :created_at] def up - add_concurrent_index :events, COLUMNS, name: INDEX_NAME + add_concurrent_index :events, COLUMNS, name: INDEX_NAME # rubocop:disable Migration/PreventIndexCreation -- Legacy migration end def down diff --git a/db/post_migrate/20240201111294_add_index_on_issues_table_tmp_epic_id_column.rb b/db/post_migrate/20240201111294_add_index_on_issues_table_tmp_epic_id_column.rb index 76e8323973b..34dbd32d35a 100644 --- a/db/post_migrate/20240201111294_add_index_on_issues_table_tmp_epic_id_column.rb +++ b/db/post_migrate/20240201111294_add_index_on_issues_table_tmp_epic_id_column.rb @@ -7,7 +7,9 @@ class AddIndexOnIssuesTableTmpEpicIdColumn < Gitlab::Database::Migration[2.2] INDEX_NAME = "tmp_index_issues_on_tmp_epic_id" def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :issues, :tmp_epic_id, unique: true, name: INDEX_NAME + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20240213125429_schedule_index_merge_requests_on_unmerged_state_id.rb b/db/post_migrate/20240213125429_schedule_index_merge_requests_on_unmerged_state_id.rb index e7b1fbe68a4..ef25716edce 100644 --- a/db/post_migrate/20240213125429_schedule_index_merge_requests_on_unmerged_state_id.rb +++ b/db/post_migrate/20240213125429_schedule_index_merge_requests_on_unmerged_state_id.rb @@ -7,7 +7,9 @@ class ScheduleIndexMergeRequestsOnUnmergedStateId < Gitlab::Database::Migration[ TABLE_NAME = :merge_requests def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration prepare_async_index(TABLE_NAME, :id, name: INDEX_NAME, where: "state_id <> 3") + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20240325085542_add_index_merge_requests_on_unmerged_state_id.rb b/db/post_migrate/20240325085542_add_index_merge_requests_on_unmerged_state_id.rb index 800dc23e7e5..9e08088480e 100644 --- a/db/post_migrate/20240325085542_add_index_merge_requests_on_unmerged_state_id.rb +++ b/db/post_migrate/20240325085542_add_index_merge_requests_on_unmerged_state_id.rb @@ -9,7 +9,9 @@ class AddIndexMergeRequestsOnUnmergedStateId < Gitlab::Database::Migration[2.2] TABLE_NAME = :merge_requests def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index(TABLE_NAME, :id, name: INDEX_NAME, where: "state_id <> 3") + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20240410104838_index_vulnerability_reads_on_state_report_type_severity_traversal_ids_archived.rb b/db/post_migrate/20240410104838_index_vulnerability_reads_on_state_report_type_severity_traversal_ids_archived.rb index 6b750eb3fe0..599612f7201 100644 --- a/db/post_migrate/20240410104838_index_vulnerability_reads_on_state_report_type_severity_traversal_ids_archived.rb +++ b/db/post_migrate/20240410104838_index_vulnerability_reads_on_state_report_type_severity_traversal_ids_archived.rb @@ -8,7 +8,9 @@ class IndexVulnerabilityReadsOnStateReportTypeSeverityTraversalIdsArchived < Git COLUMNS = %i[resolved_on_default_branch state report_type severity traversal_ids vulnerability_id].freeze def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :vulnerability_reads, COLUMNS, name: INDEX_NAME, where: 'archived = false' + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20240502120047_index_vulnerability_reads_for_common_group_level_query.rb b/db/post_migrate/20240502120047_index_vulnerability_reads_for_common_group_level_query.rb index 7f1eb48e627..5f3ab47f2c2 100644 --- a/db/post_migrate/20240502120047_index_vulnerability_reads_for_common_group_level_query.rb +++ b/db/post_migrate/20240502120047_index_vulnerability_reads_for_common_group_level_query.rb @@ -8,7 +8,9 @@ class IndexVulnerabilityReadsForCommonGroupLevelQuery < Gitlab::Database::Migrat milestone '17.0' def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :vulnerability_reads, COLUMNS, name: INDEX_NAME, where: 'archived = false' + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20240514121644_replace_issues_milestone_index.rb b/db/post_migrate/20240514121644_replace_issues_milestone_index.rb index eb3d67ae8df..23f50215b4b 100644 --- a/db/post_migrate/20240514121644_replace_issues_milestone_index.rb +++ b/db/post_migrate/20240514121644_replace_issues_milestone_index.rb @@ -7,7 +7,7 @@ class ReplaceIssuesMilestoneIndex < Gitlab::Database::Migration[2.2] # TODO: Index to be created synchronously in https://gitlab.com/gitlab-org/gitlab/-/issues/461627 def up - prepare_async_index :issues, %i[milestone_id id], name: INDEX_NAME + prepare_async_index :issues, %i[milestone_id id], name: INDEX_NAME # rubocop:disable Migration/PreventIndexCreation -- Legacy migration end def down diff --git a/db/post_migrate/20240531140131_add_issues_milestone_and_id_index_concurrently.rb b/db/post_migrate/20240531140131_add_issues_milestone_and_id_index_concurrently.rb index 94f234f67b9..10fa634f215 100644 --- a/db/post_migrate/20240531140131_add_issues_milestone_and_id_index_concurrently.rb +++ b/db/post_migrate/20240531140131_add_issues_milestone_and_id_index_concurrently.rb @@ -8,7 +8,7 @@ class AddIssuesMilestoneAndIdIndexConcurrently < Gitlab::Database::Migration[2.2 disable_ddl_transaction! def up - add_concurrent_index :issues, %i[milestone_id id], name: INDEX_NAME + add_concurrent_index :issues, %i[milestone_id id], name: INDEX_NAME # rubocop:disable Migration/PreventIndexCreation -- Legacy migration end def down diff --git a/db/post_migrate/20240610125054_create_idx_vulnerability_occurences_on_prim_iden_id.rb b/db/post_migrate/20240610125054_create_idx_vulnerability_occurences_on_prim_iden_id.rb index e1ca68e1f40..5ab8fc80d75 100644 --- a/db/post_migrate/20240610125054_create_idx_vulnerability_occurences_on_prim_iden_id.rb +++ b/db/post_migrate/20240610125054_create_idx_vulnerability_occurences_on_prim_iden_id.rb @@ -9,7 +9,7 @@ class CreateIdxVulnerabilityOccurencesOnPrimIdenId < Gitlab::Database::Migration # -- This index was created async previously, check https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131647 def up - add_concurrent_index( + add_concurrent_index( # rubocop:disable Migration/PreventIndexCreation -- Legacy migration TABLE_NAME, [:primary_identifier_id, :vulnerability_id], name: NEW_INDEX_NAME ) diff --git a/db/post_migrate/20240703142511_add_index_owasp_top_10_for_group_level_reports.rb b/db/post_migrate/20240703142511_add_index_owasp_top_10_for_group_level_reports.rb index a2631fe43db..1f8082be506 100644 --- a/db/post_migrate/20240703142511_add_index_owasp_top_10_for_group_level_reports.rb +++ b/db/post_migrate/20240703142511_add_index_owasp_top_10_for_group_level_reports.rb @@ -8,7 +8,9 @@ class AddIndexOwaspTop10ForGroupLevelReports < Gitlab::Database::Migration[2.2] # -- Legacy migration def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :vulnerability_reads, [:owasp_top_10, :state, :report_type, + # rubocop:enable Migration/PreventIndexCreation :severity, :traversal_ids, :vulnerability_id, :resolved_on_default_branch], where: 'archived = false', name: INDEX_NAME diff --git a/db/post_migrate/20240719033346_tmp_index_on_vulnerability_reads.rb b/db/post_migrate/20240719033346_tmp_index_on_vulnerability_reads.rb index c7117461ac5..725dc037da6 100644 --- a/db/post_migrate/20240719033346_tmp_index_on_vulnerability_reads.rb +++ b/db/post_migrate/20240719033346_tmp_index_on_vulnerability_reads.rb @@ -13,7 +13,9 @@ class TmpIndexOnVulnerabilityReads < Gitlab::Database::Migration[2.2] # -- Legacy migration def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index TABLE_NAME, :id, name: INDEX_NAME, where: "state = 1" + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20240729133633_prepare_index_vulnerability_finding_links_on_project_id.rb b/db/post_migrate/20240729133633_prepare_index_vulnerability_finding_links_on_project_id.rb index 145fb53ad94..aec20205f5f 100644 --- a/db/post_migrate/20240729133633_prepare_index_vulnerability_finding_links_on_project_id.rb +++ b/db/post_migrate/20240729133633_prepare_index_vulnerability_finding_links_on_project_id.rb @@ -8,7 +8,9 @@ class PrepareIndexVulnerabilityFindingLinksOnProjectId < Gitlab::Database::Migra # -- Legacy migration def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration prepare_async_index :vulnerability_finding_links, :project_id, name: INDEX_NAME + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20240805205657_tmp_index_for_owasp_on_vulnerability_reads.rb b/db/post_migrate/20240805205657_tmp_index_for_owasp_on_vulnerability_reads.rb index 3158fc7a8e9..2db1881f74d 100644 --- a/db/post_migrate/20240805205657_tmp_index_for_owasp_on_vulnerability_reads.rb +++ b/db/post_migrate/20240805205657_tmp_index_for_owasp_on_vulnerability_reads.rb @@ -10,7 +10,9 @@ class TmpIndexForOwaspOnVulnerabilityReads < Gitlab::Database::Migration[2.2] # -- Legacy migration def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :vulnerability_reads, COLUMNS, name: INDEX_NAME, where: WHERE_CLAUSE + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20240828173211_add_revised_idx_owasp_top_10_for_group_level_reports.rb b/db/post_migrate/20240828173211_add_revised_idx_owasp_top_10_for_group_level_reports.rb index 7074e911f7b..d8a45208ed3 100644 --- a/db/post_migrate/20240828173211_add_revised_idx_owasp_top_10_for_group_level_reports.rb +++ b/db/post_migrate/20240828173211_add_revised_idx_owasp_top_10_for_group_level_reports.rb @@ -11,7 +11,9 @@ class AddRevisedIdxOwaspTop10ForGroupLevelReports < Gitlab::Database::Migration[ # -- Legacy migration def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :vulnerability_reads, [:owasp_top_10, :state, :report_type, :resolved_on_default_branch, + # rubocop:enable Migration/PreventIndexCreation :severity, :traversal_ids, :vulnerability_id], where: 'archived = false', name: INDEX_NAME diff --git a/db/post_migrate/20240905023750_async_add_index_on_events_personal_namespace_id_2.rb b/db/post_migrate/20240905023750_async_add_index_on_events_personal_namespace_id_2.rb index 7d1d9648d15..3ce6679f1c5 100644 --- a/db/post_migrate/20240905023750_async_add_index_on_events_personal_namespace_id_2.rb +++ b/db/post_migrate/20240905023750_async_add_index_on_events_personal_namespace_id_2.rb @@ -9,7 +9,7 @@ class AsyncAddIndexOnEventsPersonalNamespaceId2 < Gitlab::Database::Migration[2. def up return unless Gitlab.com_except_jh? - prepare_async_index :events, :personal_namespace_id, name: INDEX_NAME, + prepare_async_index :events, :personal_namespace_id, name: INDEX_NAME, # rubocop:disable Migration/PreventIndexCreation -- Legacy migration where: 'personal_namespace_id IS NOT NULL' end diff --git a/db/post_migrate/20240909230748_add_index_on_events_personal_namespace_id_self_managed.rb b/db/post_migrate/20240909230748_add_index_on_events_personal_namespace_id_self_managed.rb index a36498752de..c3b5de0fa1b 100644 --- a/db/post_migrate/20240909230748_add_index_on_events_personal_namespace_id_self_managed.rb +++ b/db/post_migrate/20240909230748_add_index_on_events_personal_namespace_id_self_managed.rb @@ -11,7 +11,7 @@ class AddIndexOnEventsPersonalNamespaceIdSelfManaged < Gitlab::Database::Migrati def up return if Gitlab.com_except_jh? - add_concurrent_index :events, + add_concurrent_index :events, # rubocop:disable Migration/PreventIndexCreation -- Legacy migration :personal_namespace_id, where: 'personal_namespace_id IS NOT NULL', name: INDEX diff --git a/db/post_migrate/20240923114603_add_index_on_vulnerability_reads_for_filtered_removal.rb b/db/post_migrate/20240923114603_add_index_on_vulnerability_reads_for_filtered_removal.rb index 1d3e5f10a62..daa6d7c1e66 100644 --- a/db/post_migrate/20240923114603_add_index_on_vulnerability_reads_for_filtered_removal.rb +++ b/db/post_migrate/20240923114603_add_index_on_vulnerability_reads_for_filtered_removal.rb @@ -9,7 +9,9 @@ class AddIndexOnVulnerabilityReadsForFilteredRemoval < Gitlab::Database::Migrati # -- Legacy migration def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :vulnerability_reads, %i[project_id resolved_on_default_branch], name: INDEX_NAME + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20241021221146_prepare_async_index_on_issues_by_project_correct_type_where_closed.rb b/db/post_migrate/20241021221146_prepare_async_index_on_issues_by_project_correct_type_where_closed.rb index 2f08cec6b02..00684157988 100644 --- a/db/post_migrate/20241021221146_prepare_async_index_on_issues_by_project_correct_type_where_closed.rb +++ b/db/post_migrate/20241021221146_prepare_async_index_on_issues_by_project_correct_type_where_closed.rb @@ -8,7 +8,9 @@ class PrepareAsyncIndexOnIssuesByProjectCorrectTypeWhereClosed < Gitlab::Databas def up # Temporary index to be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/500165 # TODO: Index to be created synchronously in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/170005 + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration prepare_async_index :issues, # -- Tmp index needed to fix work item type ids + # rubocop:enable Migration/PreventIndexCreation [:project_id, :correct_work_item_type_id, :closed_at], where: 'state_id = 2', name: INDEX_NAME diff --git a/db/post_migrate/20241021221626_prepare_async_index_on_issues_project_health_id_desc_state_correct_type.rb b/db/post_migrate/20241021221626_prepare_async_index_on_issues_project_health_id_desc_state_correct_type.rb index 4c20d1fe744..8503ccf31a8 100644 --- a/db/post_migrate/20241021221626_prepare_async_index_on_issues_project_health_id_desc_state_correct_type.rb +++ b/db/post_migrate/20241021221626_prepare_async_index_on_issues_project_health_id_desc_state_correct_type.rb @@ -9,7 +9,9 @@ class PrepareAsyncIndexOnIssuesProjectHealthIdDescStateCorrectType < Gitlab::Dat def up # Temporary index to be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/500165 # TODO: Index to be created synchronously in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/170005 + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration prepare_async_index :issues, # -- Tmp index needed to fix work item type ids + # rubocop:enable Migration/PreventIndexCreation [:project_id, :health_status, :id, :state_id, :correct_work_item_type_id], order: { health_status: 'DESC NULLS LAST', id: :desc }, name: INDEX_NAME diff --git a/db/post_migrate/20241021221755_prepare_async_index_on_issues_project_health_id_asc_state_correct_type.rb b/db/post_migrate/20241021221755_prepare_async_index_on_issues_project_health_id_asc_state_correct_type.rb index a32e782a7dd..add09338380 100644 --- a/db/post_migrate/20241021221755_prepare_async_index_on_issues_project_health_id_asc_state_correct_type.rb +++ b/db/post_migrate/20241021221755_prepare_async_index_on_issues_project_health_id_asc_state_correct_type.rb @@ -9,7 +9,9 @@ class PrepareAsyncIndexOnIssuesProjectHealthIdAscStateCorrectType < Gitlab::Data def up # Temporary index to be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/500165 # TODO: Index to be created synchronously in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/170005 + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration prepare_async_index :issues, # -- Tmp index needed to fix work item type ids + # rubocop:enable Migration/PreventIndexCreation [:project_id, :health_status, :id, :state_id, :correct_work_item_type_id], order: { health_status: 'ASC NULLS LAST', id: :desc }, name: INDEX_NAME diff --git a/db/post_migrate/20241021221938_prepare_async_index_on_issues_correct_type_project_created_at_state.rb b/db/post_migrate/20241021221938_prepare_async_index_on_issues_correct_type_project_created_at_state.rb index 3103ceebc8d..e4cf21a27ee 100644 --- a/db/post_migrate/20241021221938_prepare_async_index_on_issues_correct_type_project_created_at_state.rb +++ b/db/post_migrate/20241021221938_prepare_async_index_on_issues_correct_type_project_created_at_state.rb @@ -9,7 +9,9 @@ class PrepareAsyncIndexOnIssuesCorrectTypeProjectCreatedAtState < Gitlab::Databa def up # Temporary index to be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/500165 # TODO: Index to be created synchronously in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/170005 + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration prepare_async_index :issues, # -- Tmp index needed to fix work item type ids + # rubocop:enable Migration/PreventIndexCreation [:correct_work_item_type_id, :project_id, :created_at, :state_id], name: INDEX_NAME end diff --git a/db/post_migrate/20241105213841_create_tmp_index_on_issues_by_project_correct_type_where_closed.rb b/db/post_migrate/20241105213841_create_tmp_index_on_issues_by_project_correct_type_where_closed.rb index 17a47df2d91..688905c5da9 100644 --- a/db/post_migrate/20241105213841_create_tmp_index_on_issues_by_project_correct_type_where_closed.rb +++ b/db/post_migrate/20241105213841_create_tmp_index_on_issues_by_project_correct_type_where_closed.rb @@ -8,7 +8,9 @@ class CreateTmpIndexOnIssuesByProjectCorrectTypeWhereClosed < Gitlab::Database:: def up # Temporary index to be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/500165 + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :issues, # -- Tmp index needed to fix work item type ids + # rubocop:enable Migration/PreventIndexCreation [:project_id, :correct_work_item_type_id, :closed_at], where: 'state_id = 2', name: INDEX_NAME diff --git a/db/post_migrate/20241105215409_create_tmp_index_on_issues_project_health_id_desc_state_correct_type.rb b/db/post_migrate/20241105215409_create_tmp_index_on_issues_project_health_id_desc_state_correct_type.rb index c6e1e462b2b..12a24feff69 100644 --- a/db/post_migrate/20241105215409_create_tmp_index_on_issues_project_health_id_desc_state_correct_type.rb +++ b/db/post_migrate/20241105215409_create_tmp_index_on_issues_project_health_id_desc_state_correct_type.rb @@ -8,7 +8,9 @@ class CreateTmpIndexOnIssuesProjectHealthIdDescStateCorrectType < Gitlab::Databa def up # Temporary index to be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/500165 + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :issues, # -- Tmp index needed to fix work item type ids + # rubocop:enable Migration/PreventIndexCreation [:project_id, :health_status, :id, :state_id, :correct_work_item_type_id], order: { health_status: 'DESC NULLS LAST', id: :desc }, name: INDEX_NAME diff --git a/db/post_migrate/20241105215907_create_tmp_index_on_issues_project_health_id_asc_state_correct_type.rb b/db/post_migrate/20241105215907_create_tmp_index_on_issues_project_health_id_asc_state_correct_type.rb index a4091559d2c..edd2c1f6900 100644 --- a/db/post_migrate/20241105215907_create_tmp_index_on_issues_project_health_id_asc_state_correct_type.rb +++ b/db/post_migrate/20241105215907_create_tmp_index_on_issues_project_health_id_asc_state_correct_type.rb @@ -8,7 +8,9 @@ class CreateTmpIndexOnIssuesProjectHealthIdAscStateCorrectType < Gitlab::Databas def up # Temporary index to be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/500165 + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :issues, # -- Tmp index needed to fix work item type ids + # rubocop:enable Migration/PreventIndexCreation [:project_id, :health_status, :id, :state_id, :correct_work_item_type_id], order: { health_status: 'ASC NULLS LAST', id: :desc }, name: INDEX_NAME diff --git a/db/post_migrate/20241105220155_create_tmp_index_on_issues_correct_type_project_created_at_state.rb b/db/post_migrate/20241105220155_create_tmp_index_on_issues_correct_type_project_created_at_state.rb index 33dd9437262..99d46fc7e58 100644 --- a/db/post_migrate/20241105220155_create_tmp_index_on_issues_correct_type_project_created_at_state.rb +++ b/db/post_migrate/20241105220155_create_tmp_index_on_issues_correct_type_project_created_at_state.rb @@ -8,7 +8,9 @@ class CreateTmpIndexOnIssuesCorrectTypeProjectCreatedAtState < Gitlab::Database: def up # Temporary index to be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/500165 + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :issues, # -- Tmp index needed to fix work item type ids + # rubocop:enable Migration/PreventIndexCreation [:correct_work_item_type_id, :project_id, :created_at, :state_id], name: INDEX_NAME end diff --git a/db/post_migrate/20241106125627_update_sent_notifications_index_on_noteable.rb b/db/post_migrate/20241106125627_update_sent_notifications_index_on_noteable.rb index dc4e4232d6a..9354a8a79b3 100644 --- a/db/post_migrate/20241106125627_update_sent_notifications_index_on_noteable.rb +++ b/db/post_migrate/20241106125627_update_sent_notifications_index_on_noteable.rb @@ -15,7 +15,9 @@ class UpdateSentNotificationsIndexOnNoteable < Gitlab::Database::Migration[2.2] # "index_sent_notifications_on_noteable_type_noteable_id_id" btree (noteable_id, id) WHERE noteable_type = 'Issue' # to improve iterating over issue related sent notification records in batches. def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration prepare_async_index :sent_notifications, COLUMN_NAMES, where: "noteable_type = 'Issue'", name: INDEX_NAME + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/post_migrate/20241129104531_create_sent_notifications_index_on_noteable_synchronously.rb b/db/post_migrate/20241129104531_create_sent_notifications_index_on_noteable_synchronously.rb index 13cb20c5069..ac02f3da4e1 100644 --- a/db/post_migrate/20241129104531_create_sent_notifications_index_on_noteable_synchronously.rb +++ b/db/post_migrate/20241129104531_create_sent_notifications_index_on_noteable_synchronously.rb @@ -10,7 +10,9 @@ class CreateSentNotificationsIndexOnNoteableSynchronously < Gitlab::Database::Mi # Creating prepared index in 20241106125627_update_sent_notifications_index_on_noteable # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/171687 def up + # rubocop:disable Migration/PreventIndexCreation -- Legacy migration add_concurrent_index :sent_notifications, COLUMN_NAMES, where: "noteable_type = 'Issue'", name: INDEX_NAME + # rubocop:enable Migration/PreventIndexCreation end def down diff --git a/db/schema_migrations/20241121071110 b/db/schema_migrations/20241121071110 new file mode 100644 index 00000000000..e4739236cf9 --- /dev/null +++ b/db/schema_migrations/20241121071110 @@ -0,0 +1 @@ +d4e80c2d34ade6020600339620e5e39e59ff2bdd6625f6befb3ddca0e64deebc \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index ac07bab0df3..7ba8c783519 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -16911,6 +16911,8 @@ CREATE TABLE personal_access_tokens ( seven_days_notification_sent_at timestamp with time zone, thirty_days_notification_sent_at timestamp with time zone, sixty_days_notification_sent_at timestamp with time zone, + description text, + CONSTRAINT check_6d2ddc9355 CHECK ((char_length(description) <= 255)), CONSTRAINT check_aa95773861 CHECK ((char_length(advanced_scopes) <= 4096)) ); diff --git a/doc/administration/backup_restore/backup_gitlab.md b/doc/administration/backup_restore/backup_gitlab.md index e2cf3e2f7c2..34156fda0b0 100644 --- a/doc/administration/backup_restore/backup_gitlab.md +++ b/doc/administration/backup_restore/backup_gitlab.md @@ -607,14 +607,14 @@ sudo -u git -H bundle exec rake gitlab:backup:create GITLAB_BACKUP_MAX_CONCURREN :::TabTitle Helm chart (Kubernetes) -```yaml +```yaml toolbox: #... extra: {} extraEnv: GITLAB_BACKUP_MAX_CONCURRENCY: 4 GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY: 1 - + ``` ::EndTabs @@ -1376,7 +1376,7 @@ In the following cases, consider using file system data transfer or snapshots as - Your GitLab instance has a problem and using the regular backup and import Rake tasks isn't possible. WARNING: -Gitaly Cluster [does not support snapshot backups](../gitaly/index.md#snapshot-backup-and-recovery-limitations). +Gitaly Cluster [does not support snapshot backups](../gitaly/index.md#snapshot-backup-and-recovery). When considering using file system data transfer or snapshots: diff --git a/doc/administration/cicd/job_logs.md b/doc/administration/cicd/job_logs.md index acfdb466b48..7cebb654d32 100644 --- a/doc/administration/cicd/job_logs.md +++ b/doc/administration/cicd/job_logs.md @@ -231,7 +231,7 @@ have to be shared using NFS, which is not recommended. Instead: Before you enable the feature flag: -- Review [the limitations of incremental logging](#limitations). +- See [known issues](#known-issues). - [Enable object storage](job_artifacts.md#using-object-storage). To enable incremental logging: @@ -279,10 +279,11 @@ Here is the detailed data flow: 1. The Sidekiq worker archives the log to object storage and cleans up the log in Redis and a persistent store (object storage or the database). -### Limitations +### Known issues - [Redis Cluster is not supported](https://gitlab.com/gitlab-org/gitlab/-/issues/224171). - You must configure [object storage for CI/CD artifacts, logs, and builds](job_artifacts.md#using-object-storage) before you enable the feature flag. After the flag is enabled, files cannot be written to disk, and there is no protection against misconfiguration. -- There is [an epic tracking other potential limitations and improvements](https://gitlab.com/groups/gitlab-org/-/epics/3791). + +For more information, see [epic 3791](https://gitlab.com/groups/gitlab-org/-/epics/3791). diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md index 8f00a7db680..8d4a43c7b81 100644 --- a/doc/administration/geo/disaster_recovery/index.md +++ b/doc/administration/geo/disaster_recovery/index.md @@ -10,8 +10,8 @@ DETAILS: **Tier:** Premium, Ultimate **Offering:** Self-managed -Geo replicates your database, your Git repositories, and few other assets, -but there are some [limitations](../index.md#limitations). +Geo replicates your database, your Git repositories, and other assets. +Some [known issues](../index.md#known-issues) exist. WARNING: Multi-secondary configurations require the complete re-synchronization and re-configuration of all non-promoted secondaries and diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md index c41a311103f..d9096b79b5c 100644 --- a/doc/administration/geo/index.md +++ b/doc/administration/geo/index.md @@ -136,7 +136,7 @@ Keep in mind that: - The **primary** site talks to the **secondary** sites for viewing replication details. The **primary** does a GraphQL query against the **secondary** site for sync and verification data (API). - You can push directly to a **secondary** site (for both HTTP and SSH, including Git LFS), and it will proxy the requests to the **primary** site. -- There are [limitations](#limitations) when using Geo. +- Some [known issues](#known-issues) exist when using Geo. ### Architecture @@ -260,12 +260,12 @@ When something is marked to be updated in the tracking database instance, asynch This new architecture allows GitLab to be resilient to connectivity issues between the sites. It doesn't matter how long the **secondary** site is disconnected from the **primary** site as it is able to replay all the events in the correct order and become synchronized with the **primary** site again. -## Limitations +## Known issues WARNING: -This list of limitations only reflects the latest version of GitLab. If you are using an older version, extra limitations may be in place. +These known issues reflect only the latest version of GitLab. If you are using an older version, additional issues might exist. -- Pushing directly to a **secondary** site redirects (for HTTP) or proxies (for SSH) the request to the **primary** site instead of [handling it directly](https://gitlab.com/gitlab-org/gitlab/-/issues/1381). The limitation is that you cannot use Git over HTTP with credentials embedded in the URI, for example, `https://user:personal-access-token@secondary.tld`. For more information, see how to [use a Geo Site](replication/usage.md). +- Pushing directly to a **secondary** site redirects (for HTTP) or proxies (for SSH) the request to the **primary** site instead of [handling it directly](https://gitlab.com/gitlab-org/gitlab/-/issues/1381). You cannot use Git over HTTP with credentials embedded in the URI, for example, `https://user:personal-access-token@secondary.tld`. For more information, see how to [use a Geo Site](replication/usage.md). - The **primary** site has to be online for OAuth login to happen. Existing sessions and Git are not affected. Support for the **secondary** site to use an OAuth provider independent from the primary is [being planned](https://gitlab.com/gitlab-org/gitlab/-/issues/208465). - The installation takes multiple manual steps that together can take about an hour depending on circumstances. Consider using the [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/gitlab-environment-toolkit) Terraform and Ansible scripts to deploy and operate production @@ -275,7 +275,8 @@ This list of limitations only reflects the latest version of GitLab. If you are - [Selective synchronization](replication/selective_synchronization.md) only limits what repositories and files are replicated. The entire PostgreSQL data is still replicated. Selective synchronization is not built to accommodate compliance / export control use cases. - [Pages access control](../../user/project/pages/pages_access_control.md) doesn't work on secondaries. See [GitLab issue #9336](https://gitlab.com/gitlab-org/gitlab/-/issues/9336) for details. - [Disaster recovery](disaster_recovery/index.md) for deployments that have multiple secondary sites causes downtime due to the need to re-initialize PostgreSQL streaming replication on all non-promoted secondaries to follow the new primary site. -- For Git over SSH, to make the project clone URL display correctly regardless of which site you are browsing, secondary sites must use the same port as the primary. [GitLab issue #339262](https://gitlab.com/gitlab-org/gitlab/-/issues/339262) proposes to remove this limitation. +- For Git over SSH, to make the project clone URL display correctly regardless of which site you are browsing, secondary sites must use the same port as the primary. + For more information, see [issue 339262](https://gitlab.com/gitlab-org/gitlab/-/issues/339262). - Git push over SSH against a secondary site does not work for pushes over 1.86 GB. [GitLab issue #413109](https://gitlab.com/gitlab-org/gitlab/-/issues/413109) tracks this bug. - Backups [cannot be run on Geo secondary sites](replication/troubleshooting/postgresql_replication.md#message-error-canceling-statement-due-to-conflict-with-recovery). - Git push with options over SSH against a secondary site does not work and terminates the connection. For more information, see [issue 417186](https://gitlab.com/gitlab-org/gitlab/-/issues/417186). diff --git a/doc/administration/geo/replication/troubleshooting/common.md b/doc/administration/geo/replication/troubleshooting/common.md index 5b34d8ffa7a..68653b48cff 100644 --- a/doc/administration/geo/replication/troubleshooting/common.md +++ b/doc/administration/geo/replication/troubleshooting/common.md @@ -124,9 +124,9 @@ OpenSSH configured to use AuthorizedKeysCommand ... skipped doc/administration/operations/fast_ssh_key_lookup.md ``` -This issue may occur if: +This issue might occur if: -- You [use SELinux](../../../operations/fast_ssh_key_lookup.md#selinux-support-and-limitations). +- You use [SELinux](../../../operations/fast_ssh_key_lookup.md#selinux-support). - You don't use SELinux, and the `git` user cannot access the OpenSSH configuration file due to restricted file permissions. In the latter case, the following output shows that only the `root` user can read this file: diff --git a/doc/administration/geo/secondary_proxy/index.md b/doc/administration/geo/secondary_proxy/index.md index 860d59b0950..89bd3fbe104 100644 --- a/doc/administration/geo/secondary_proxy/index.md +++ b/doc/administration/geo/secondary_proxy/index.md @@ -20,7 +20,10 @@ This behavior enables use-cases including: - Geographically load-balancing traffic without worrying about write access. -For an overview, see: [Secondary proxying using geographic load-balancer and AWS Route53](https://www.youtube.com/watch?v=TALLy7__Na8). +For an overview, see [Geo proxying for secondary sites](https://www.youtube.com/watch?v=TALLy7__Na8). + + +For known issues, see [proxying-related items in the Geo documentation](../index.md#known-issues). ## Set up a unified URL for Geo sites @@ -175,10 +178,6 @@ If your secondary site uses the same external URL as the primary site: To allow the sites to talk to each other, [make sure the `Internal URL` field is unique for each site](../../geo_sites.md#set-up-the-internal-urls). If the desired URL is unique to this site, then you can clear the `Internal URL` field. On save, it defaults to the external URL. -## Known issues - -See proxying-related items in the consolidated list of [Geo Limitations](../index.md#limitations). - ## Behavior of secondary sites when the primary Geo site is down Considering that web traffic is proxied to the primary, the behavior of the secondary sites differs when the primary diff --git a/doc/administration/gitaly/gitaly_geo_capabilities.md b/doc/administration/gitaly/gitaly_geo_capabilities.md index b0374235e0c..73aff29005e 100644 --- a/doc/administration/gitaly/gitaly_geo_capabilities.md +++ b/doc/administration/gitaly/gitaly_geo_capabilities.md @@ -15,7 +15,7 @@ The following tables are intended to guide you to choose the right combination o | Capability | Availability | Recoverability | Data Resiliency | Performance | Risks/Trade-offs| |------------|--------------|----------------|-----------------|-------------|-----------------| -|Gitaly Cluster | Very high - tolerant of node failures | RTO for a single node of 10 s with no manual intervention | Data is stored on multiple nodes | Good - While writes may take slightly longer due to voting, read distribution improves read speeds | **Trade-off** - Slight decrease in write speed for redundant, strongly-consistent storage solution. **Risks** - [Does not support snapshot backups](../gitaly/index.md#snapshot-backup-and-recovery-limitations), GitLab backup task can be slow for large data sets | +|Gitaly Cluster | Very high - tolerant of node failures | RTO for a single node of 10 s with no manual intervention | Data is stored on multiple nodes | Good - While writes may take slightly longer due to voting, read distribution improves read speeds | **Trade-off** - Slight decrease in write speed for redundant, strongly-consistent storage solution. **Risks** - [Does not support snapshot backups](../gitaly/index.md#snapshot-backup-and-recovery), GitLab backup task can be slow for large data sets | |Gitaly Shards | Single storage location is a single point of failure | Would need to restore only shards which failed | Single point of failure | Good - can allocate repositories to shards to spread load | **Trade-off** - Need to manually configure repositories into different shards to balance loads / storage space **Risks** - Single point of failure relies on recovery process when single-node failure occurs | ## Geo capabilities diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md index b06f1897202..0cca04e759f 100644 --- a/doc/administration/gitaly/index.md +++ b/doc/administration/gitaly/index.md @@ -51,10 +51,10 @@ repository storage is either: ## Before deploying Gitaly Cluster Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. -Before deploying Gitaly Cluster, review: +Before deploying Gitaly Cluster, see: - Existing [known issues](#known-issues). -- [Snapshot limitations](#snapshot-backup-and-recovery-limitations). +- [Snapshot backup and recovery](#snapshot-backup-and-recovery). - [Configuration guidance](configure_gitaly.md) and [Repository storage options](../repository_storage_paths.md) to make sure that Gitaly Cluster is the best setup for you. @@ -77,7 +77,7 @@ the current status of these issues, refer to the referenced issues and epics. | Restoring a Gitaly Cluster node from a snapshot in a running cluster | Because the Gitaly Cluster runs with consistent state, introducing a single node that is behind results in the cluster not being able to reconcile the nodes data and other nodes data | Don't restore a single Gitaly Cluster node from a backup snapshot. If you must restore from backup:

1. [Shut down GitLab](../read_only_gitlab.md#shut-down-the-gitlab-ui).
2. Snapshot all Gitaly Cluster nodes at the same time.
3. Take a database dump of the Praefect database. | | Limitations when running in Kubernetes, Amazon ECS, or similar | Praefect (Gitaly Cluster) is not supported and Gitaly has known limitations. For more information, see [epic 6127](https://gitlab.com/groups/gitlab-org/-/epics/6127). | Use our [reference architectures](../reference_architectures/index.md). | -### Snapshot backup and recovery limitations +### Snapshot backup and recovery Gitaly Cluster does not support snapshot backups. Snapshot backups can cause issues where the Praefect database becomes out of sync with the disk storage. Because of how Praefect rebuilds the replication metadata of Gitaly disk information diff --git a/doc/administration/operations/fast_ssh_key_lookup.md b/doc/administration/operations/fast_ssh_key_lookup.md index a0a411e612c..f3523922848 100644 --- a/doc/administration/operations/fast_ssh_key_lookup.md +++ b/doc/administration/operations/fast_ssh_key_lookup.md @@ -157,7 +157,7 @@ This overview is brief. Refer to the above instructions for more context. from a Linux package installation. 1. Reload `sshd`: `sudo service sshd reload`. -## SELinux support and limitations +## SELinux support GitLab supports `authorized_keys` database lookups with [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux). diff --git a/doc/administration/settings/sign_in_restrictions.md b/doc/administration/settings/sign_in_restrictions.md index be247e69225..38f0ba21846 100644 --- a/doc/administration/settings/sign_in_restrictions.md +++ b/doc/administration/settings/sign_in_restrictions.md @@ -48,7 +48,7 @@ administrator access or use Admin Mode. With Admin Mode, your account does not have administrator access by default. You can continue to access groups and projects you're a member of. However, for administrative tasks, -you must authenticate (except for [certain features](#limitations-of-admin-mode)). +you must authenticate (except for [certain features](#known-issues)). When Admin Mode is enabled, it applies to all administrators on the instance. @@ -130,7 +130,7 @@ To turn off Admin Mode for your current session: 1. On the left sidebar, select your avatar. 1. Select **Leave Admin Mode**. -### Limitations of Admin Mode +### Known issues Admin Mode times out after six hours, and you cannot change this timeout limit. @@ -144,9 +144,7 @@ Git clients without additional authentication steps. To use the GitLab REST- or GraphQL API, administrators must [create a personal access token](../../user/profile/personal_access_tokens.md#create-a-personal-access-token) or [OAuth token](../../api/oauth2.md) with the [`admin_mode` scope](../../user/profile/personal_access_tokens.md#personal-access-token-scopes). If an administrator with a personal access token with the `admin_mode` scope loses their administrator access, that user cannot access the API as an administrator even though they still have the token with the `admin_mode` scope. - -We may address these limitations in the future. For more information see the following epic: -[Admin Mode for GitLab Administrators](https://gitlab.com/groups/gitlab-org/-/epics/2158). +For more information, see [epic 2158](https://gitlab.com/groups/gitlab-org/-/epics/2158). Also, when GitLab Geo is enabled, you can't view the replication status of projects and designs while on a secondary node. A fix is proposed when projects ([issue 367926](https://gitlab.com/gitlab-org/gitlab/-/issues/367926)) and designs ([issue 355660](https://gitlab.com/gitlab-org/gitlab/-/issues/355660)) move to the new Geo framework. diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 6a473531870..edde894e240 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -18558,21 +18558,25 @@ Self-hosted LLM servers. ### `AiUsageData` +Usage data for events stored in the default PostgreSQL database. Data retained for three months. + #### Fields | Name | Type | Description | | ---- | ---- | ----------- | -| `codeSuggestionEvents` | [`CodeSuggestionEventConnection`](#codesuggestioneventconnection) | Events related to code suggestions feature. (see [Connections](#connections)) | +| `codeSuggestionEvents` | [`CodeSuggestionEventConnection`](#codesuggestioneventconnection) | Events related to code suggestions. (see [Connections](#connections)) | ### `AiUserMetrics` +Pre-aggregated per-user metrics for GitLab Code Suggestions and GitLab Duo Chat. + #### Fields | Name | Type | Description | | ---- | ---- | ----------- | | `codeSuggestionsAcceptedCount` | [`Int`](#int) | Total count of code suggestions accepted by the user. | | `duoChatInteractionsCount` | [`Int`](#int) | Number of user interactions with GitLab Duo Chat. | -| `user` | [`UserCore!`](#usercore) | Metrics user. | +| `user` | [`UserCore!`](#usercore) | User metrics. | ### `AlertManagementAlert` diff --git a/doc/api/integrations.md b/doc/api/integrations.md index 87ea3545223..a0ff4dc6aa5 100644 --- a/doc/api/integrations.md +++ b/doc/api/integrations.md @@ -487,6 +487,7 @@ Parameters: | Parameter | Type | Required | Description | |------------------------|---------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `api_key` | string | yes | [API key](https://docs.datadoghq.com/account_management/api-app-keys/) used for authentication with Datadog. | +| `datadog_ci_visibility`| boolean | yes | Enables collection of pipeline and job events in Datadog to display pipeline execution traces. | | `api_url` | string | no | Full URL of your Datadog site. | | `datadog_env` | string | no | For self-managed deployments, `env%` tag for all the data sent to Datadog. | | `datadog_service` | string | no | GitLab instance to tag all data from in Datadog. Can be used when managing several self-managed deployments. | diff --git a/doc/api/members.md b/doc/api/members.md index 7835ce8e767..fc28b2f26c6 100644 --- a/doc/api/members.md +++ b/doc/api/members.md @@ -25,12 +25,11 @@ in the `Gitlab::Access` module as `access_level`. - Owner (`50`) - Admin (`60`) -## Limitations +## Known issues -The `group_saml_identity` attribute is only visible to group owners for [SSO-enabled groups](../user/group/saml_sso/index.md). - -The `email` attribute is only visible to group owners for [enterprise users](../user/enterprise_user/index.md) -of the group when an API request is sent to the group itself, or that group's subgroups or projects. +- The `group_saml_identity` attribute is only visible to group owners for [SSO-enabled groups](../user/group/saml_sso/index.md). +- The `email` attribute is only visible to group owners for [enterprise users](../user/enterprise_user/index.md) + of the group when an API request is sent to the group itself, or that group's subgroups or projects. ## List all members of a group or project diff --git a/doc/api/openapi/openapi_v2.yaml b/doc/api/openapi/openapi_v2.yaml index bebf59ef769..0719987e9e2 100644 --- a/doc/api/openapi/openapi_v2.yaml +++ b/doc/api/openapi/openapi_v2.yaml @@ -48590,6 +48590,10 @@ definitions: type: boolean description: When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces. + datadog_ci_visibility: + type: boolean + description: Whether to collect Pipeline and Job events in Datadog, to + display pipeline execution traces. datadog_service: type: string description: GitLab instance to tag all data from in Datadog. Can be used @@ -48614,6 +48618,7 @@ definitions: `false`. required: - api_key + - datadog_ci_visibility description: Create/Edit Datadog integration putApiV4ProjectsIdServicesDiffblueCover: type: object @@ -50468,6 +50473,10 @@ definitions: type: boolean description: When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces. + datadog_ci_visibility: + type: boolean + description: Whether to collect Pipeline and Job events in Datadog, to + display pipeline execution traces. datadog_service: type: string description: GitLab instance to tag all data from in Datadog. Can be used @@ -50492,6 +50501,7 @@ definitions: `false`. required: - api_key + - datadog_ci_visibility description: Create/Edit Datadog integration putApiV4ProjectsIdIntegrationsDiffblueCover: type: object diff --git a/doc/api/personal_access_tokens.md b/doc/api/personal_access_tokens.md index b83cf05b18f..c6e41721830 100644 --- a/doc/api/personal_access_tokens.md +++ b/doc/api/personal_access_tokens.md @@ -71,6 +71,7 @@ Example response: "name": "Test Token", "revoked": false, "created_at": "2020-07-23T14:31:47.729Z", + "description": "Test Token description", "scopes": [ "api" ], @@ -97,6 +98,7 @@ Example response: "name": "Test Token", "revoked": false, "created_at": "2020-07-23T14:31:47.729Z", + "description": "Test Token description", "scopes": [ "api" ], @@ -123,6 +125,7 @@ Example response: "name": "Revoked Test Token", "revoked": true, "created_at": "2022-01-01T14:31:47.729Z", + "description": "Test Token description", "scopes": [ "api" ], @@ -197,6 +200,7 @@ Example response: "name": "Test Token", "revoked": false, "created_at": "2020-07-23T14:31:47.729Z", + "description": "Test Token description", "scopes": [ "api" ], @@ -246,6 +250,7 @@ Example response: "name": "Rotated Token", "revoked": false, "created_at": "2023-08-01T15:00:00.000Z", + "description": "Test Token description", "scopes": ["api"], "user_id": 1337, "last_used_at": null, @@ -290,6 +295,7 @@ Example response: "name": "Rotated Token", "revoked": false, "created_at": "2023-08-01T15:00:00.000Z", + "description": "Test Token description", "scopes": ["api"], "user_id": 1337, "last_used_at": null, diff --git a/doc/api/user_tokens.md b/doc/api/user_tokens.md index 87c492c853f..606c95aac69 100644 --- a/doc/api/user_tokens.md +++ b/doc/api/user_tokens.md @@ -34,6 +34,7 @@ Supported attributes: |:-------------|:--------|:---------|:------------| | `user_id` | integer | yes | ID of the user. | | `name` | string | yes | Name of the personal access token. | +| `description`| string | no | Description of the personal access token. | | `expires_at` | date | no | Expiration date of the access token in ISO format (`YYYY-MM-DD`). If no date is set, the expiration is set to the [maximum allowable lifetime of an access token](../user/profile/personal_access_tokens.md#access-token-expiration). | | `scopes` | array | yes | Array of scopes of the personal access token. See [personal access token scopes](../user/profile/personal_access_tokens.md#personal-access-token-scopes) for possible values. | @@ -52,6 +53,7 @@ Example response: "name": "mytoken", "revoked": false, "created_at": "2020-10-14T11:58:53.526Z", + "description": "Test Token description", "scopes": [ "api" ], @@ -89,6 +91,7 @@ Supported attributes: | Attribute | Type | Required | Description | |:-------------|:-------|:---------|:------------| | `name` | string | yes | Name of the personal access token. | +| `description`| string | no | Description of the personal access token. | | `scopes` | array | yes | Array of scopes of the personal access token. Possible values are `k8s_proxy`. | | `expires_at` | array | no | Expiration date of the access token in ISO format (`YYYY-MM-DD`). If no date is set, the expiration is at the end of the current day. The expiration is subject to the [maximum allowable lifetime of an access token](../user/profile/personal_access_tokens.md#access-token-expiration). | @@ -106,6 +109,7 @@ Example response: "name": "mytoken", "revoked": false, "created_at": "2020-10-14T11:58:53.526Z", + "description": "Test Token description", "scopes": [ "k8s_proxy" ], @@ -154,6 +158,7 @@ Example response: ], "revoked" : false, "name" : "mytoken", + "description": "Test Token description", "id" : 2, "created_at" : "2017-03-17T17:18:09.283Z", "impersonation" : true, @@ -168,6 +173,7 @@ Example response: ], "revoked" : true, "name" : "mytoken2", + "description": "Test Token description", "created_at" : "2017-03-17T17:19:28.697Z", "id" : 3, "impersonation" : true, @@ -213,6 +219,7 @@ Example response: ], "revoked" : false, "name" : "mytoken", + "description": "Test Token description", "id" : 2, "created_at" : "2017-03-17T17:18:09.283Z", "impersonation" : true, @@ -241,6 +248,7 @@ Supported attributes: |:-------------|:--------|:---------|:------------| | `user_id` | integer | yes | ID of the user. | | `name` | string | yes | Name of the impersonation token. | +| `description`| string | no | Description of the personal access token. | | `expires_at` | date | yes | Expiration date of the impersonation token in ISO format (`YYYY-MM-DD`). | | `scopes` | array | yes | Array of scopes of the impersonation token (`api`, `read_user`). | @@ -265,6 +273,7 @@ Example response: "active" : true, "impersonation" : true, "name" : "mytoken", + "description": "Test Token description", "created_at" : "2017-03-17T17:18:09.283Z", "expires_at" : "2017-04-04" } diff --git a/doc/ci/ci_cd_for_external_repos/index.md b/doc/ci/ci_cd_for_external_repos/index.md index ae6d3149235..e1b73c1f78d 100644 --- a/doc/ci/ci_cd_for_external_repos/index.md +++ b/doc/ci/ci_cd_for_external_repos/index.md @@ -11,7 +11,7 @@ DETAILS: **Offering:** GitLab.com, Self-managed, GitLab Dedicated GitLab CI/CD can be used with [GitHub](github_integration.md), [Bitbucket Cloud](bitbucket_integration.md), -or any other Git server, though there are some [limitations](#limitations). +or any other Git server. Some [known issues](#known-issues) exist. Instead of moving your entire project to GitLab, you can connect your external repository to get the benefits of GitLab CI/CD. @@ -89,7 +89,7 @@ By using pipelines for external pull requests, GitLab exposes additional The variable names are prefixed with `CI_EXTERNAL_PULL_REQUEST_`. -### Limitations +### Known issues This feature does not support: diff --git a/doc/ci/jobs/index.md b/doc/ci/jobs/index.md index ba157e4bcf0..f28e2f5571d 100644 --- a/doc/ci/jobs/index.md +++ b/doc/ci/jobs/index.md @@ -91,7 +91,7 @@ To view the full list of jobs that ran in a project: 1. On the left sidebar, select **Search or go to** and find your project. 1. Select **Build > Jobs**. -You can filter the list by [job status](#view-jobs-in-a-pipeline) and [job name](#job-name-limitations). +You can filter the list by [job status](#view-jobs-in-a-pipeline) and [job name](#job-name). ## See why a job failed @@ -112,7 +112,7 @@ You can also see the reason it failed on the Job detail page. You can use GitLab Duo Root Cause Analysis in GitLab Duo Chat to [troubleshoot failed CI/CD jobs](../../user/gitlab_duo_chat/examples.md#troubleshoot-failed-cicd-jobs-with-root-cause-analysis). -## Job name limitations +## Job name You can't use these keywords as job names: diff --git a/doc/ci/resource_groups/index.md b/doc/ci/resource_groups/index.md index 85d7a77691a..b9657e27d52 100644 --- a/doc/ci/resource_groups/index.md +++ b/doc/ci/resource_groups/index.md @@ -20,6 +20,8 @@ the concurrency of the jobs for optimizing your continuous deployments workflow ## Add a resource group +You can add only one resource to a resource group. + Provided that you have the following pipeline configuration (`.gitlab-ci.yml` file in your repository): ```yaml @@ -62,10 +64,6 @@ can still run `build` jobs concurrently for maximizing the pipeline efficiency. - The basic knowledge of the [GitLab Environments and Deployments](../environments/index.md) - At least the Developer role for the project to configure CI/CD pipelines. -### Limitations - -Only one resource can be attached to a resource group. - ## Process modes You can choose a process mode to strategically control the job concurrency for your deployment preferences. diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md index f1adc4283c2..da8a6e847b0 100644 --- a/doc/ci/yaml/index.md +++ b/doc/ci/yaml/index.md @@ -3648,7 +3648,7 @@ deploystacks: [vultr, processing] - `parallel:matrix` jobs add the variable values to the job names to differentiate the jobs from each other, but [large values can cause names to exceed limits](https://gitlab.com/gitlab-org/gitlab/-/issues/362262): - - Job names must be [255 characters or fewer](../jobs/index.md#job-name-limitations). + - [Job names](../jobs/index.md#job-name) must be 255 characters or fewer. - When using [`needs`](#needs), job names must be 128 characters or fewer. - You cannot create multiple matrix configurations with the same variable values but different variable names. Job names are generated from the variable values, not the variable names, so matrix entries diff --git a/doc/development/dangerbot.md b/doc/development/dangerbot.md index 7f4577a7ae8..18ba878a50f 100644 --- a/doc/development/dangerbot.md +++ b/doc/development/dangerbot.md @@ -177,9 +177,9 @@ at GitLab so far: - [Reviewer roulette](code_review.md#reviewer-roulette) - Single codebase effort -## Limitations +## Known issues -If working on a personal fork, Danger is run but it's output is not added to a +When you work on a personal fork, Danger is run but its output is not added to a merge request comment and labels are not applied. This happens because the secret variable from the canonical project is not shared to forks. diff --git a/doc/development/database/pagination_guidelines.md b/doc/development/database/pagination_guidelines.md index da280497c97..3c58fad4336 100644 --- a/doc/development/database/pagination_guidelines.md +++ b/doc/development/database/pagination_guidelines.md @@ -150,7 +150,7 @@ By making the `id` column part of the index, the previous query reads maximum 20 NOTE: Here we're leveraging the ordered property of the b-tree database index. Values in the index are sorted so reading 20 rows does not require further sorting. -#### Limitations +#### Known issues ##### `COUNT(*)` on a large dataset @@ -262,7 +262,7 @@ Looking at the query execution plan, we can see that this query read only 5 rows (5 rows) ``` -#### Limitations +#### Known issues ##### No page numbers diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md index af6d212e20f..81b47835006 100644 --- a/doc/development/fe_guide/index.md +++ b/doc/development/fe_guide/index.md @@ -15,7 +15,7 @@ GitLab is built on top of [Ruby on Rails](https://rubyonrails.org). It uses [Ham -Be wary of [the limitations that come with using Hamlit](https://github.com/k0kubun/hamlit/blob/master/REFERENCE.md#limitations). +For more information, see [Hamlit](https://github.com/k0kubun/hamlit/blob/master/REFERENCE.md). diff --git a/doc/development/graphql_guide/pagination.md b/doc/development/graphql_guide/pagination.md index baa45f8a48b..ff6d2c1fc61 100644 --- a/doc/development/graphql_guide/pagination.md +++ b/doc/development/graphql_guide/pagination.md @@ -75,7 +75,7 @@ Some of the benefits and tradeoffs of keyset pagination are - It's the best way to do infinite scrolling. - It's more difficult to program and maintain. Easy for `updated_at` and - `sort_order`, complicated (or impossible) for [complex sorting scenarios](#limitations-of-query-complexity). + `sort_order`, complicated (or impossible) for [complex sorting scenarios](#query-complexity). ## Implementation @@ -137,7 +137,7 @@ Based on whether the main attribute field being sorted on is `NULL` in the curso condition is built. The last ordering field is considered to be unique (a primary key), meaning the column never contains `NULL` values. -#### Limitations of query complexity +#### Query complexity We only support two ordering fields, and one of those fields needs to be the primary key. @@ -245,7 +245,7 @@ incorrect sort order. ### Offset pagination -There are times when the [complexity of sorting](#limitations-of-query-complexity) +There are times when the [complexity of sorting](#query-complexity) is more than our keyset pagination can handle. For example, in [`ProjectIssuesResolver`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/resolvers/project_issues_resolver.rb), diff --git a/doc/development/internal_analytics/service_ping/index.md b/doc/development/internal_analytics/service_ping/index.md index a10fff92ef0..4d4a412208d 100644 --- a/doc/development/internal_analytics/service_ping/index.md +++ b/doc/development/internal_analytics/service_ping/index.md @@ -33,7 +33,7 @@ We use the following terminology to describe the Service Ping components: - **MAU**: monthly active users. - **WAU**: weekly active users. -### Limitations +### Known issues - Service Ping delivers only [metrics](../index.md#metric), not individual events. - A metric has to be present and instrumented in the codebase for a GitLab version to be delivered in Service Pings for that version. diff --git a/doc/development/python_guide/index.md b/doc/development/python_guide/index.md index fc0de6532d0..b2e713cabec 100644 --- a/doc/development/python_guide/index.md +++ b/doc/development/python_guide/index.md @@ -155,3 +155,14 @@ Brief guide provides a straightforward introduction to Python, covering all the 1. **[Learn X in Y Minutes: Python](https://learnxinyminutes.com/docs/python)** A very brief, high-level introduction cuts directly to the core syntax and features of Python, making it a valuable quick start for developers transitioning to Python. + +1. **[Exercism Python Track](https://exercism.io/tracks/python)** + Use Exercism's Python track as a foundation for learning Python concepts and best practices. Exercism provides hands-on practice with mentoring support, making it an excellent resource for mastering Python through coding exercises and feedback. + +When building Python APIs, we use FastAPI and Pydantic. To get started with building and reviewing these technologies, refer to the following resources: + +1. **[FastAPI Documentation](https://fastapi.tiangolo.com/)** + FastAPI is a modern web framework for building APIs with Python. This resource will help you learn how to create fast and efficient web applications and APIs. FastAPI is especially useful for building Python applications with high performance and scalability. + +1. **[Pydantic Documentation](https://pydantic-docs.helpmanual.io/)** + Pydantic is a Python library for data validation and settings management using Python type annotations. Learn how to integrate Pydantic into your Python projects for easier data validation and management, particularly when working with FastAPI. diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md index def4b5c42fe..ef7362d26da 100644 --- a/doc/development/testing_guide/frontend_testing.md +++ b/doc/development/testing_guide/frontend_testing.md @@ -30,10 +30,10 @@ Information on testing Vue 3 is contained in [this page](../testing_guide/testin We use Jest to write frontend unit and integration tests. Jest tests can be found in `/spec/frontend` and `/ee/spec/frontend` in EE. -### Limitations of jsdom +### `jsdom` -Jest uses jsdom instead of a browser for running tests. -This comes with a number of limitations, namely: +Jest uses `jsdom` instead of a browser for running tests. +Known issues include: - [No scrolling support](https://github.com/jsdom/jsdom/blob/15.1.1/lib/jsdom/browser/Window.js#L623-L625) - [No element sizes or positions](https://github.com/jsdom/jsdom/blob/15.1.1/lib/jsdom/living/nodes/Element-impl.js#L334-L371) diff --git a/doc/integration/datadog.md b/doc/integration/datadog.md index c79731b1f1d..a77d00eaeae 100644 --- a/doc/integration/datadog.md +++ b/doc/integration/datadog.md @@ -10,13 +10,10 @@ DETAILS: **Tier:** Free, Premium, Ultimate **Offering:** GitLab.com, Self-managed, GitLab Dedicated -The Datadog integration enables you to send CI/CD pipeline and job information to -[Datadog](https://www.datadoghq.com/). The [Datadog CI Pipeline Visibility](https://www.datadoghq.com/product/ci-cd-monitoring/) -product helps you monitor for job failures and performance issues, then troubleshoot them. -It's based on [Webhooks](../user/project/integrations/webhooks.md), -and only requires configuration on GitLab. +The Datadog integration enables you to connect your GitLab projects to [Datadog](https://www.datadoghq.com/), +synchronizing repository metadata to enrich your Datadog telemetry, have Datadog comment on Merge Requests, and send CI/CD pipeline and job information to Datadog. -## Configure the integration +## Connect your Datadog account Users with the **Administrator** role can configure the integration for the entire instance or for a specific project or group: @@ -34,10 +31,26 @@ or for a specific project or group: 1. Scroll to **Add an integration**, and select **Datadog**. 1. Select **Active** to enable the integration. 1. Specify the [**Datadog site**](https://docs.datadoghq.com/getting_started/site/) to send data to. -1. Provide your Datadog **API key**. -1. Optional. Select **Enable logs collection** to enable logs collection for the output of jobs. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346339) in GitLab 15.3.) 1. Optional. To override the API URL used to send data directly, provide an **API URL**. Used only in advanced scenarios. +1. Provide your Datadog **API key**. + +## Configure CI Visibility + +You can optionally enable [Datadog CI Visibility](https://www.datadoghq.com/product/ci-cd-monitoring/) +to send the CI/CD pipeline and job data to Datadog. Use this feature to monitor and troubleshoot job +failures and performance issues. + +For more information, see the [Datadog CI Visibility documentation](https://docs.datadoghq.com/continuous_integration/pipelines/?tab=gitlab). + +WARNING: +Datadog CI Visibility is priced per committer. Using this feature might affect your Datadog bill. +For details, see the [Datadog pricing page](https://www.datadoghq.com/pricing/?product=ci-pipeline-visibility#products). + +This feature is based on [Webhooks](../user/project/integrations/webhooks.md), +and only requires configuration in GitLab: + +1. Optional. Select **Enable Pipeline job logs collection** to enable logs collection for the output of jobs. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346339) in GitLab 15.3.) 1. Optional. If you use more than one GitLab instance, provide a unique **Service** name to differentiate between your GitLab instances. diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md index 84cd422e97a..faad8d43c24 100644 --- a/doc/update/deprecations.md +++ b/doc/update/deprecations.md @@ -4056,7 +4056,7 @@ We intend to replace this feature with the ability to [embed charts](https://git -While CI/CD [job names](https://docs.gitlab.com/ee/ci/jobs/index.html#job-name-limitations) have a strict 255 character limit, other CI/CD parameters do not yet have validations ensuring they also stay under the limit. +While CI/CD [job names](https://docs.gitlab.com/ee/ci/jobs/index.html#job-name) have a strict 255 character limit, other CI/CD parameters do not yet have validations ensuring they also stay under the limit. In GitLab 16.0, validation will be added to strictly limit the following to 255 characters as well: diff --git a/doc/user/analytics/ai_impact_analytics.md b/doc/user/analytics/ai_impact_analytics.md index 2d4e832b4ab..f2877b0f314 100644 --- a/doc/user/analytics/ai_impact_analytics.md +++ b/doc/user/analytics/ai_impact_analytics.md @@ -12,7 +12,7 @@ DETAILS: > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/443696) in GitLab 16.11 [with a flag](../../administration/feature_flags.md) named `ai_impact_analytics_dashboard`. Disabled by default. > - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/451873) in GitLab 17.2. Feature flag `ai_impact_analytics_dashboard` removed. -> - Changed to require GitLab Duo add-on in GitLab 17.6 and later. +> - Changed to require GitLab Duo add-on (GitLab Duo Pro for `AiUserMetrics`) in GitLab 17.6. AI Impact analytics displays software development lifecycle (SDLC) metrics for a project or group in the month-to-date and the past six months. @@ -59,6 +59,8 @@ The **Metric trends** table displays metrics for the last six months, with month Usage rate for Code Suggestions is calculated with data starting from GitLab 16.11. For more information, see [epic 12978](https://gitlab.com/groups/gitlab-org/-/epics/12978). +To retrieve AI Impact metrics, you can use the GraphQL API [`AiUserMetrics`](../../api/graphql/reference/index.md#aiusermetrics) and [`AiUsageData`](../../api/graphql/reference/index.md#aiusagedata). + ## View AI Impact analytics Prerequisites: diff --git a/doc/user/application_security/dast/browser/configuration/authentication.md b/doc/user/application_security/dast/browser/configuration/authentication.md index 33fec6b1d5d..5c5585cc9c9 100644 --- a/doc/user/application_security/dast/browser/configuration/authentication.md +++ b/doc/user/application_security/dast/browser/configuration/authentication.md @@ -55,7 +55,7 @@ To run a DAST authenticated scan: ### Prerequisites - You have the username and password of the user you would like to authenticate as during the scan. -- You have checked the [known limitations](#known-limitations) to ensure DAST can authenticate to your application. +- You have checked the [known issues](#known-issues) to ensure DAST can authenticate to your application. - You have satisfied the prerequisites if you're using [form authentication](#form-authentication). - You have thought about how you can [verify](#verifying-authentication-is-successful) whether or not authentication was successful. @@ -191,7 +191,7 @@ Even when an application uses Single Sign-on. Applications using SSO solutions s authentication using the [single-step](#configuration-for-a-single-step-login-form) or [multi-step](#configuration-for-a-multi-step-login-form) login form configuration guides. DAST supports authentication processes where a user is redirected to an external Identity Provider's site to sign in. -Check the [known limitations](#known-limitations) of DAST authentication to determine if your SSO authentication process is supported. +Check the [known issues](#known-issues) of DAST authentication to determine if your SSO authentication process is supported. ### Configuration for Windows integrated authentication (Kerberos) @@ -507,7 +507,7 @@ dast: DAST_AUTH_COOKIE_NAMES: "sessionID,refreshToken" ``` -## Known limitations +## Known issues - DAST cannot bypass a CAPTCHA if the authentication flow includes one. Turn these off in the testing environment for the application being scanned. - DAST cannot handle multi-factor authentication like one-time passwords (OTP) by using SMS, biometrics, or authenticator apps. Turn these off in the testing environment for the application being scanned. diff --git a/doc/user/application_security/dependency_scanning/experiment_libbehave_dependency.md b/doc/user/application_security/dependency_scanning/experiment_libbehave_dependency.md index 01d80453f72..47c41ba55d1 100644 --- a/doc/user/application_security/dependency_scanning/experiment_libbehave_dependency.md +++ b/doc/user/application_security/dependency_scanning/experiment_libbehave_dependency.md @@ -180,15 +180,12 @@ based on Semgrep, with a configured set of checks. In the case of Java and C#, an additional step is taken to decompile the binary artifacts prior to running static analysis. -### Limitations +### Known issues -Each language has its own set of limitations. Please review this section to determine if your -project is impacted. +Each language has its own known issues. -#### General limitations - -All package files such as `Gemfile.lock`, `requirements.txt` and so forth must provide explicit -versions. Version ranges are not supported. +All package files such as `Gemfile.lock` and `requirements.txt` must provide explicit versions. +Version ranges are not supported. diff --git a/doc/user/clusters/agent/vulnerabilities.md b/doc/user/clusters/agent/vulnerabilities.md index 60bef6795f6..de3844e15eb 100644 --- a/doc/user/clusters/agent/vulnerabilities.md +++ b/doc/user/clusters/agent/vulnerabilities.md @@ -188,12 +188,12 @@ You must have at least the Developer role. To scan private images, the scanner relies on the image pull secrets (direct references and from the service account) to pull the image. -## Limitations +## Known issues In GitLab agent 16.9 and later, operational container scanning: -- handles Trivy reports of up to 100MB. For previous releases this limit is 10MB. -- is [disabled](../../../development/fips_compliance.md#unsupported-features-in-fips-mode) when the GitLab agent runs in `fips` mode. +- Handles Trivy reports of up to 100 MB. For previous releases, this limit is 10 MB. +- Is [disabled](../../../development/fips_compliance.md#unsupported-features-in-fips-mode) when the GitLab agent runs in `fips` mode. ## Troubleshooting diff --git a/doc/user/group/import/direct_transfer_migrations.md b/doc/user/group/import/direct_transfer_migrations.md index 690934176aa..a95070bcffc 100644 --- a/doc/user/group/import/direct_transfer_migrations.md +++ b/doc/user/group/import/direct_transfer_migrations.md @@ -145,7 +145,7 @@ After you have authorized access to the source GitLab instance, you are redirect If you do not want to import all user memberships from the source instance, ensure the **Import user memberships** checkbox is cleared. For example, the source instance might have 200 members, but you might want to import 50 members only. After the import completes, you can add more members to groups and projects. -1. By default, the proposed group namespaces match the names as they exist in source instance, but based on your permissions, you can choose to edit these names before you proceed to import any of them. Group and project paths must conform to naming [limitations](../../reserved_names.md#limitations-on-usernames-project-and-group-names-and-slugs) and are normalized if necessary to avoid import failures. +1. By default, the proposed group namespaces match the names as they exist in source instance, but based on your permissions, you can choose to edit these names before you proceed to import any of them. Group and project paths must conform to [naming rules](../../reserved_names.md#rules-for-usernames-project-and-group-names-and-slugs) and are normalized if necessary to avoid import failures. 1. Next to the groups you want to import, select either: - **Import with projects**. If this is not available, see [prerequisites](#prerequisites). - **Import without projects**. diff --git a/doc/user/group/import/troubleshooting.md b/doc/user/group/import/troubleshooting.md index 7fe86cd481b..17c2caabcf1 100644 --- a/doc/user/group/import/troubleshooting.md +++ b/doc/user/group/import/troubleshooting.md @@ -134,7 +134,7 @@ This error indicates a problem transferring from the _source_ instance. To solve ## Mismatched group or project path names -If a source group or project path doesn't conform to naming [limitations](../../reserved_names.md#limitations-on-usernames-project-and-group-names-and-slugs), the path is normalized to +If a source group or project path doesn't conform to [naming rules](../../reserved_names.md#rules-for-usernames-project-and-group-names-and-slugs), the path is normalized to ensure it is valid. For example, `Destination-Project-Path` is normalized to `destination-project-path`. ## Error: `command exited with error code 15 and Unable to save [FILTERED] into [FILTERED]` diff --git a/doc/user/group/moderate_users.md b/doc/user/group/moderate_users.md index 3d5ac28d4da..6e3cb049d71 100644 --- a/doc/user/group/moderate_users.md +++ b/doc/user/group/moderate_users.md @@ -94,7 +94,7 @@ You can enable automatic removal of group members who either: 1. Expand **Permissions and group features**. 1. Scroll to **Dormant members**. 1. Select the **Remove dormant members after a period of inactivity** checkbox. -1. In the **Days of inactivity before removal** field, enter the number of days before removal. The minimum is 90 days. +1. In the **Days of inactivity before removal** field, enter the number of days before removal. The minimum is 90 days, the maximum is 1827 days (5 years). 1. Select **Save changes**. After the member has reached the days of inactivity and is removed from the group: diff --git a/doc/user/namespace/index.md b/doc/user/namespace/index.md index eec8e488f5c..a1278b00048 100644 --- a/doc/user/namespace/index.md +++ b/doc/user/namespace/index.md @@ -9,6 +9,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w Namespaces organize projects in GitLab. Because each namespace is separate, you can use the same project name in multiple namespaces. +When you choose a name for your namespace, keep in mind: + +- [Naming rules](../reserved_names.md#rules-for-usernames-project-and-group-names-and-slugs) +- [Reserved group names](../reserved_names.md#reserved-group-names) + +NOTE: +Namespaces with a period (`.`) cause issues with SSL certificate validation and the source path when [publishing Terraform modules](../packages/terraform_module_registry/index.md#publish-a-terraform-module). + ## Types of namespaces GitLab has two types of namespaces: @@ -35,10 +43,3 @@ To determine whether you're in a group or personal namespace, you can view the U | A user named `alex`. | `https://gitlab.example.com/alex` | `alex` | | A group named `alex-team`. | `https://gitlab.example.com/alex-team` | `alex-team` | | A group named `alex-team` with a subgroup named `marketing`. | `https://gitlab.example.com/alex-team/marketing` | `alex-team/marketing` | - -## Name limitations - -When you choose a name for your namespace, keep in mind the [character limitations](../reserved_names.md#limitations-on-usernames-project-and-group-names-and-slugs) and [reserved group names](../reserved_names.md#reserved-group-names). - -NOTE: -Namespaces with a period (`.`) cause issues with SSL certificate validation and the source path when [publishing Terraform modules](../packages/terraform_module_registry/index.md#publish-a-terraform-module). diff --git a/doc/user/profile/notifications.md b/doc/user/profile/notifications.md index f79304b7d70..aad5b25657c 100644 --- a/doc/user/profile/notifications.md +++ b/doc/user/profile/notifications.md @@ -208,7 +208,17 @@ to change their user notification settings to **Watch** instead. ### Edit notification settings for issues, merge requests, and epics To toggle notifications on an issue, merge request, or epic: on the right sidebar, -turn on or off the **Notifications** (**{notifications}**) toggle. +select the vertical ellipsis (**{ellipsis_v}**), then turn on or off the **Notifications** toggle. + +#### Moved notifications + +DETAILS: +**Offering:** Self-managed + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132678) in GitLab 16.5 [with a flag](../../administration/feature_flags.md) named `notifications_todos_buttons`. Disabled by default. + +FLAG: +The availability of this feature is controlled by a feature flag. For more information, see the history. Enabling this feature flag moves the notifications and to-do item buttons to the upper-right corner of the page. When you **turn on** notifications, you start receiving notifications on each update, even if you haven't participated in the discussion. diff --git a/doc/user/project/index.md b/doc/user/project/index.md index 1aed7a6e3a9..ec6e4ee839c 100644 --- a/doc/user/project/index.md +++ b/doc/user/project/index.md @@ -21,7 +21,7 @@ To create a blank project: 1. Select **Create blank project**. 1. Enter the project details: 1. **Project name**: Enter the name of your project. - See the [limitations on project names](../../user/reserved_names.md#limitations-on-usernames-project-and-group-names-and-slugs). + For more information, see [naming rules](../../user/reserved_names.md#rules-for-usernames-project-and-group-names-and-slugs). 1. **Project slug**: Enter the path to your project. GitLab uses the slug as the URL path. 1. **Project deployment target (optional)**: If you want to deploy your project to specific environment, select the relevant deployment target. @@ -157,5 +157,5 @@ encourage agencies to move away from SHA-1 earlier, if possible. - [Create a project with `git push`](../../topics/git/project.md) - [Reserved project and group names](../../user/reserved_names.md) -- [Limitations on project and group names](../../user/reserved_names.md#limitations-on-usernames-project-and-group-names-and-slugs) +- [Rules for project and group names](../../user/reserved_names.md#rules-for-usernames-project-and-group-names-and-slugs) - [Manage projects](working_with_projects.md) diff --git a/doc/user/project/ml/experiment_tracking/mlflow_client.md b/doc/user/project/ml/experiment_tracking/mlflow_client.md index 01233e8b310..b0a1e74cbdd 100644 --- a/doc/user/project/ml/experiment_tracking/mlflow_client.md +++ b/doc/user/project/ml/experiment_tracking/mlflow_client.md @@ -358,7 +358,7 @@ Other MLflowClient methods: | `create_registered_model` | Yes | 16.8 | | | `create_registered_model` | Yes | 16.8 | | -## Limitations +## Known issues - The API GitLab supports is the one defined at MLflow version 2.7.1. - MLflow client methods not listed above are not supported. diff --git a/doc/user/project/working_with_projects.md b/doc/user/project/working_with_projects.md index 7eaac33687c..66f9a371e11 100644 --- a/doc/user/project/working_with_projects.md +++ b/doc/user/project/working_with_projects.md @@ -523,4 +523,4 @@ repository. For example, if an administrator creates the alias `gitlab` for the - [Connect an external repository to GitLab CI/CD](../../ci/ci_cd_for_external_repos/index.md). - [Fork a project](repository/forking_workflow.md#create-a-fork). - Adjust [project visibility](../../user/public_access.md#change-project-visibility) and [permissions](settings/index.md#configure-project-features-and-permissions). -- [Limitations on project and group names](../../user/reserved_names.md#limitations-on-usernames-project-and-group-names-and-slugs) +- [Rules for project and group names](../../user/reserved_names.md#rules-for-usernames-project-and-group-names-and-slugs) diff --git a/doc/user/reserved_names.md b/doc/user/reserved_names.md index 04f48c33c58..3b32616938a 100644 --- a/doc/user/reserved_names.md +++ b/doc/user/reserved_names.md @@ -19,7 +19,7 @@ where: - `PROJECT_WILDCARD_ROUTES` are names reserved for subgroups or projects. - `GROUP_ROUTES` are names reserved for all groups or projects. -## Limitations on usernames, project and group names and slugs +## Rules for usernames, project and group names, and slugs - Usernames must start and end with a letter (`a-zA-Z`) or a digit (`0-9`). Additionally: - Usernames and group names can contain only letters (`a-zA-Z`), digits (`0-9`), emoji, underscores (`_`), dots (`.`), parentheses (`()`), dashes (`-`), or spaces. diff --git a/lib/api/entities/personal_access_token.rb b/lib/api/entities/personal_access_token.rb index b9f831021a1..864a04d4da5 100644 --- a/lib/api/entities/personal_access_token.rb +++ b/lib/api/entities/personal_access_token.rb @@ -7,6 +7,7 @@ module API expose :name, documentation: { type: 'string', example: 'John Doe' } expose :revoked, documentation: { type: 'boolean' } expose :created_at, documentation: { type: 'dateTime' } + expose :description, documentation: { type: 'string', example: 'Token to manage api' } expose :scopes, documentation: { type: 'array', example: ['api'] } expose :user_id, documentation: { type: 'integer', example: 3 } expose :last_used_at, documentation: { type: 'dateTime', example: '2020-08-31T15:53:00.073Z' } diff --git a/lib/api/resource_access_tokens.rb b/lib/api/resource_access_tokens.rb index eabf7c9fd5e..30b5d183989 100644 --- a/lib/api/resource_access_tokens.rb +++ b/lib/api/resource_access_tokens.rb @@ -112,6 +112,10 @@ module API desc: "The expiration date of the token", default: PersonalAccessToken::MAX_PERSONAL_ACCESS_TOKEN_LIFETIME_IN_DAYS.days.from_now, documentation: { example: '"2021-01-31' } + optional :description, + type: String, + desc: "Resource access token description", + documentation: { example: 'test description' } optional :access_level, type: Integer, values: ALLOWED_RESOURCE_ACCESS_LEVELS.values, diff --git a/lib/api/users.rb b/lib/api/users.rb index 2ab5d3abcc3..fd736f22fdf 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -1023,6 +1023,7 @@ module API end params do requires :name, type: String, desc: 'The name of the impersonation token' + optional :description, type: String, desc: 'The description of the personal access token' optional :expires_at, type: Date, desc: 'The expiration date in the format YEAR-MONTH-DAY of the impersonation token' optional :scopes, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The array of scopes of the impersonation token' end @@ -1080,6 +1081,7 @@ module API requires :name, type: String, desc: 'The name of the personal access token' requires :scopes, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, values: ::Gitlab::Auth.all_available_scopes.map(&:to_s), desc: 'The array of scopes of the personal access token' + optional :description, type: String, desc: 'The description of the personal access token' optional :expires_at, type: Date, desc: 'The expiration date in the format YEAR-MONTH-DAY of the personal access token' end post feature_category: :system_access do @@ -1496,6 +1498,7 @@ module API # and in https://gitlab.com/gitlab-org/gitlab/-/issues/425171 requires :scopes, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, values: [::Gitlab::Auth::K8S_PROXY_SCOPE].map(&:to_s), desc: 'The array of scopes of the personal access token' + optional :description, type: String, desc: 'The description of the personal access token' optional :expires_at, type: Date, default: -> { 1.day.from_now.to_date }, desc: 'The expiration date in the format YEAR-MONTH-DAY of the personal access token' end post feature_category: :system_access do diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 449f68c1e8a..92369d43989 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2943,6 +2943,9 @@ msgstr "" msgid "AccessTokens|Token already revoked" msgstr "" +msgid "AccessTokens|Token description" +msgstr "" + msgid "AccessTokens|Token name" msgstr "" @@ -17787,39 +17790,63 @@ msgstr "" msgid "DatadogIntegration|API URL" msgstr "" -msgid "DatadogIntegration|Custom tags in Datadog. Enter one tag per line in the %{codeOpen}key:value%{codeClose} format. %{linkOpen}How do I use tags?%{linkClose}" +msgid "DatadogIntegration|Additionally, enable CI Visibility to send pipeline information to Datadog to monitor for job failures and troubleshoot performance issues." msgstr "" -msgid "DatadogIntegration|Datadog site to send data to. To send data to the EU site, use %{codeOpen}datadoghq.eu%{codeClose}." +msgid "DatadogIntegration|CI Visibility" +msgstr "" + +msgid "DatadogIntegration|Connect your GitLab projects to your Datadog account to synchronize repository metadata and enrich telemetry on your Datadog account." +msgstr "" + +msgid "DatadogIntegration|Connect your projects to Datadog and trace your GitLab pipelines." +msgstr "" + +msgid "DatadogIntegration|Custom tags for pipeline data in Datadog. Enter one tag per line in the %{codeOpen}key:value%{codeClose} format. %{linkOpen}How do I use tags?%{linkClose}" +msgstr "" + +msgid "DatadogIntegration|Datadog account" +msgstr "" + +msgid "DatadogIntegration|Datadog site to send data to. Learn more about Datadog sites in the %{link_start}documentation%{link_end}." +msgstr "" + +msgid "DatadogIntegration|Enable CI Visibility" +msgstr "" + +msgid "DatadogIntegration|Enabled" msgstr "" msgid "DatadogIntegration|Environment" msgstr "" -msgid "DatadogIntegration|For self-managed deployments, set the %{codeOpen}env%{codeClose} tag for all the data sent to Datadog. %{linkOpen}How do I use tags?%{linkClose}" +msgid "DatadogIntegration|For self-managed deployments, set the %{codeOpen}env%{codeClose} tag for all the pipeline data sent to Datadog. %{linkOpen}How do I use tags?%{linkClose}" msgstr "" -msgid "DatadogIntegration|Full URL of your Datadog site." -msgstr "" - -msgid "DatadogIntegration|GitLab instance to tag all data from in Datadog. Can be used when managing several self-managed deployments." -msgstr "" - -msgid "DatadogIntegration|Send CI/CD pipeline information to Datadog to monitor for job failures and troubleshoot performance issues." +msgid "DatadogIntegration|Full URL of your Datadog site. Only required if you do not use a standard Datadog site." msgstr "" msgid "DatadogIntegration|Service" msgstr "" +msgid "DatadogIntegration|Tag all pipeline data from this GitLab instance in Datadog. Can be used when managing several self-managed deployments." +msgstr "" + msgid "DatadogIntegration|Tags" msgstr "" -msgid "DatadogIntegration|Trace your GitLab pipelines with Datadog." +msgid "DatadogIntegration|When enabled, pipeline job logs are collected by Datadog and displayed along with pipeline execution traces. This requires CI Visibility to be enabled. Note that pipeline job logs are priced like regular Datadog logs. Learn more %{link_start}here%{link_end}." +msgstr "" + +msgid "DatadogIntegration|When enabled, pipelines and jobs are collected, and Datadog will display pipeline execution traces. Note that CI Visibility is priced per committers, see our %{link_start}pricing page%{link_end}." msgstr "" msgid "DatadogIntegration|have an invalid format" msgstr "" +msgid "DatadogIntegration|requires CI Visibility to be enabled" +msgstr "" + msgid "Date" msgstr "" @@ -20924,6 +20951,9 @@ msgstr "" msgid "Enable Auto DevOps" msgstr "" +msgid "Enable CI Visibility" +msgstr "" + msgid "Enable ClickHouse" msgstr "" @@ -20942,6 +20972,9 @@ msgstr "" msgid "Enable Mailgun event receiver" msgstr "" +msgid "Enable Pipeline Job logs collection" +msgstr "" + msgid "Enable PlantUML" msgstr "" @@ -21026,9 +21059,6 @@ msgstr "" msgid "Enable integration" msgstr "" -msgid "Enable logs collection" -msgstr "" - msgid "Enable maintenance mode" msgstr "" diff --git a/rubocop/cop/migration/prevent_index_creation.rb b/rubocop/cop/migration/prevent_index_creation.rb index 88718865885..a1e84ad685d 100644 --- a/rubocop/cop/migration/prevent_index_creation.rb +++ b/rubocop/cop/migration/prevent_index_creation.rb @@ -74,7 +74,7 @@ module RuboCop private def forbidden_tables?(node) - FORBIDDEN_TABLES.include?(node.to_sym) || large_tables.include?(node.to_sym) + FORBIDDEN_TABLES.include?(node.to_sym) || large_or_over_limit_tables.include?(node.to_sym) end def offense?(node) diff --git a/rubocop/migration_helpers.rb b/rubocop/migration_helpers.rb index eb4d5491ff6..c8727aebc8c 100644 --- a/rubocop/migration_helpers.rb +++ b/rubocop/migration_helpers.rb @@ -32,8 +32,8 @@ module RuboCop @over_limit_table ||= rubocop_migrations_config.dig('Migration/UpdateLargeTable', 'OverLimitTables') end - def large_tables - @large_tables ||= rubocop_migrations_config.dig('Migration/UpdateLargeTable', 'LargeTables') + def large_or_over_limit_tables + @large_or_over_limit_tables ||= large_tables + over_limit_tables end # Returns true if the given node originated from the db/migrate directory. @@ -87,6 +87,10 @@ module RuboCop private + def large_tables + @large_tables ||= rubocop_migrations_config.dig('Migration/UpdateLargeTable', 'LargeTables') + end + def filepath(node) node.location.expression.source_buffer.name end diff --git a/spec/controllers/user_settings/personal_access_tokens_controller_spec.rb b/spec/controllers/user_settings/personal_access_tokens_controller_spec.rb index d150887e15c..21e3c1fabd2 100644 --- a/spec/controllers/user_settings/personal_access_tokens_controller_spec.rb +++ b/spec/controllers/user_settings/personal_access_tokens_controller_spec.rb @@ -90,14 +90,16 @@ RSpec.describe UserSettings::PersonalAccessTokensController, feature_category: : expect(assigns(:active_access_tokens).to_json).to eq(active_personal_access_tokens_detail.to_json) end - it "builds a PAT with name and scopes from params" do + it "builds a PAT with name, description and scopes from params" do name = 'My PAT' scopes = 'api,read_user' + description = 'My PAT description' - get :index, params: { name: name, scopes: scopes } + get :index, params: { name: name, scopes: scopes, description: description } expect(assigns(:personal_access_token)).to have_attributes( name: eq(name), + description: eq(description), scopes: contain_exactly(:api, :read_user) ) end diff --git a/spec/factories/integrations.rb b/spec/factories/integrations.rb index 72ebefb9ae4..f38fc5f864a 100644 --- a/spec/factories/integrations.rb +++ b/spec/factories/integrations.rb @@ -25,6 +25,7 @@ FactoryBot.define do factory :datadog_integration, class: 'Integrations::Datadog' do project active { true } + datadog_ci_visibility { false } datadog_site { 'datadoghq.com' } datadog_tags { 'key:value' } api_key { 'secret' } diff --git a/spec/factories/personal_access_tokens.rb b/spec/factories/personal_access_tokens.rb index c976730a788..28b922b604c 100644 --- a/spec/factories/personal_access_tokens.rb +++ b/spec/factories/personal_access_tokens.rb @@ -5,6 +5,7 @@ FactoryBot.define do user organization sequence(:name) { |n| "PAT #{n}" } + description { "Token description" } revoked { false } expires_at { 30.days.from_now } scopes { ['api'] } diff --git a/spec/features/groups/settings/access_tokens_spec.rb b/spec/features/groups/settings/access_tokens_spec.rb index 3babfccfea5..4ce9af45014 100644 --- a/spec/features/groups/settings/access_tokens_spec.rb +++ b/spec/features/groups/settings/access_tokens_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe 'Group > Settings > Access tokens', :js, feature_category: :system_access do include Spec::Support::Helpers::ModalHelpers + include Features::AccessTokenHelpers let_it_be(:user) { create(:user) } let_it_be(:bot_user) { create(:user, :project_bot) } @@ -47,4 +48,21 @@ RSpec.describe 'Group > Settings > Access tokens', :js, feature_category: :syste it_behaves_like 'inactive resource access tokens', 'This group has no active access tokens.' end + + describe 'rotating tokens' do + let!(:resource_access_token) { create_resource_access_token } + + it_behaves_like 'rotating token fails due to missing access rights', 'group' do + let_it_be(:resource) { group } + end + + context 'when user is owner of group' do + before do + group.add_owner(user) + end + + it_behaves_like 'rotating token succeeds', 'group' + it_behaves_like 'rotating already revoked token fails' + end + end end diff --git a/spec/features/projects/settings/access_tokens_spec.rb b/spec/features/projects/settings/access_tokens_spec.rb index f1b8a3afc34..1d1b4c068d3 100644 --- a/spec/features/projects/settings/access_tokens_spec.rb +++ b/spec/features/projects/settings/access_tokens_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe 'Project > Settings > access tokens', :js, feature_category: :user_management do include Spec::Support::Helpers::ModalHelpers + include Features::AccessTokenHelpers let_it_be(:user) { create(:user) } let_it_be(:bot_user) { create(:user, :project_bot) } @@ -85,6 +86,23 @@ RSpec.describe 'Project > Settings > access tokens', :js, feature_category: :use end end + describe 'rotating tokens' do + let!(:resource_access_token) { create_resource_access_token } + + it_behaves_like 'rotating token fails due to missing access rights', 'project' do + let_it_be(:resource) { project } + end + + context 'when user is owner of project' do + before do + project.add_owner(user) + end + + it_behaves_like 'rotating token succeeds', 'project' + it_behaves_like 'rotating already revoked token fails' + end + end + describe 'viewing tokens' do before_all do project.add_maintainer(user) diff --git a/spec/features/user_settings/personal_access_tokens_spec.rb b/spec/features/user_settings/personal_access_tokens_spec.rb index 167e5a06240..22ba1157c5c 100644 --- a/spec/features/user_settings/personal_access_tokens_spec.rb +++ b/spec/features/user_settings/personal_access_tokens_spec.rb @@ -19,6 +19,7 @@ RSpec.describe 'User Settings > Personal access tokens', :js, feature_category: describe "token creation" do it "allows creation of a personal access token" do name = 'My PAT' + description = 'My PAT description' create(:organization, :default) visit user_settings_personal_access_tokens_path @@ -26,6 +27,8 @@ RSpec.describe 'User Settings > Personal access tokens', :js, feature_category: click_button 'Add new token' fill_in "Token name", with: name + fill_in "Token description", with: description + # Set date to 1st of next month find_field("Expiration date").click find(".pika-next").click @@ -39,6 +42,7 @@ RSpec.describe 'User Settings > Personal access tokens', :js, feature_category: wait_for_all_requests expect(active_access_tokens).to have_text(name) + expect(active_access_tokens).to have_text(description) expect(active_access_tokens).to have_text('in') expect(active_access_tokens).to have_text('read_api') expect(active_access_tokens).to have_text('read_user') @@ -177,11 +181,13 @@ RSpec.describe 'User Settings > Personal access tokens', :js, feature_category: it "prefills token details" do name = 'My PAT' + description = 'My PAT description' scopes = 'api,read_user' - visit user_settings_personal_access_tokens_path({ name: name, scopes: scopes }) + visit user_settings_personal_access_tokens_path({ name: name, scopes: scopes, description: description }) expect(page).to have_field("Token name", with: name) + expect(page).to have_field("Token description", with: description) expect(find("#personal_access_token_scopes_api")).to be_checked expect(find("#personal_access_token_scopes_read_user")).to be_checked end diff --git a/spec/fixtures/api/schemas/public_api/v4/resource_access_token.json b/spec/fixtures/api/schemas/public_api/v4/resource_access_token.json index 3636c970e83..61a73ef89ce 100644 --- a/spec/fixtures/api/schemas/public_api/v4/resource_access_token.json +++ b/spec/fixtures/api/schemas/public_api/v4/resource_access_token.json @@ -3,6 +3,7 @@ "required": [ "id", "name", + "description", "user_id", "active", "created_at", @@ -13,19 +14,54 @@ "last_used_at" ], "properties": { - "id": { "type": "integer" }, - "name": { "type": "string" }, - "user_id": { "type": "integer" }, - "active": { "type": "boolean" }, - "created_at": { "type": "string", "format": "date-time" }, - "expires_at": { "type": ["string", "null"], "format": "date" }, - "revoked": { "type": "boolean" }, - "access_level": { "type": "integer" }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "user_id": { + "type": "integer" + }, + "active": { + "type": "boolean" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "expires_at": { + "type": [ + "string", + "null" + ], + "format": "date" + }, + "revoked": { + "type": "boolean" + }, + "access_level": { + "type": "integer" + }, "scopes": { "type": "array", - "items": { "type": "string" } + "items": { + "type": "string" + } }, - "last_used_at": { "type": ["string", "null"], "format": "date-time" } + "last_used_at": { + "type": [ + "string", + "null" + ], + "format": "date-time" + } }, "additionalProperties": false } diff --git a/spec/frontend/access_tokens/components/access_token_table_app_spec.js b/spec/frontend/access_tokens/components/access_token_table_app_spec.js index 2fc457305da..ca0b75856e5 100644 --- a/spec/frontend/access_tokens/components/access_token_table_app_spec.js +++ b/spec/frontend/access_tokens/components/access_token_table_app_spec.js @@ -21,6 +21,7 @@ describe('~/access_tokens/components/access_token_table_app', () => { const defaultActiveAccessTokens = [ { name: 'a', + description: 'Test description', scopes: ['api'], created_at: '2021-05-01T00:00:00.000Z', last_used_at: null, @@ -34,6 +35,7 @@ describe('~/access_tokens/components/access_token_table_app', () => { }, { name: 'b', + description: 'Test description', scopes: ['api', 'sudo'], created_at: '2022-04-21T00:00:00.000Z', last_used_at: '2022-04-21T00:00:00.000Z', @@ -131,6 +133,7 @@ describe('~/access_tokens/components/access_token_table_app', () => { const headers = findHeaders(); expect(headers.wrappers.map((header) => header.text())).toStrictEqual([ 'Token name', + 'Description', 'Scopes', 'Created', 'Last Used', @@ -145,6 +148,7 @@ describe('~/access_tokens/components/access_token_table_app', () => { const headers = findHeaders(); expect(headers.wrappers.map((header) => header.text())).toStrictEqual([ 'Token name', + 'Description', 'Scopes', 'Created', 'Last Used', @@ -159,7 +163,7 @@ describe('~/access_tokens/components/access_token_table_app', () => { createComponent({ backendPagination }); const headers = wrapper.findAll('th'); - const lastUsed = headers.at(3); + const lastUsed = headers.at(4); const anchor = lastUsed.find('a'); const assistiveElement = lastUsed.find('.gl-sr-only'); expect(anchor.exists()).toBe(true); @@ -174,16 +178,17 @@ describe('~/access_tokens/components/access_token_table_app', () => { await triggerSuccess(); const cells = findCells(); - expect(cells).toHaveLength(14); + expect(cells).toHaveLength(16); // First row expect(cells.at(0).text()).toBe('a'); - expect(cells.at(1).text()).toBe('api'); - expect(cells.at(2).text()).not.toBe('Never'); - expect(cells.at(3).text()).toBe('Never'); + expect(cells.at(1).text()).toBe('Test description'); + expect(cells.at(2).text()).toBe('api'); + expect(cells.at(3).text()).not.toBe('Never'); expect(cells.at(4).text()).toBe('Never'); - expect(cells.at(5).text()).toBe('Maintainer'); - let buttons = cells.at(6).findAllComponents(GlButton); + expect(cells.at(5).text()).toBe('Never'); + expect(cells.at(6).text()).toBe('Maintainer'); + let buttons = cells.at(7).findAllComponents(GlButton); expect(buttons).toHaveLength(2); expect(buttons.at(0).attributes()).toMatchObject({ 'aria-label': 'Revoke', @@ -208,13 +213,14 @@ describe('~/access_tokens/components/access_token_table_app', () => { expect(buttons.at(1).props('category')).toBe('tertiary'); // Second row - expect(cells.at(7).text()).toBe('b'); - expect(cells.at(8).text()).toBe('api, sudo'); - expect(cells.at(9).text()).not.toBe('Never'); - expect(cells.at(10).text()).not.toBe('Never'); - expect(cells.at(11).text()).toBe('Expired'); - expect(cells.at(12).text()).toBe('Maintainer'); - buttons = cells.at(13).findAllComponents(GlButton); + expect(cells.at(8).text()).toBe('b'); + expect(cells.at(9).text()).toBe('Test description'); + expect(cells.at(10).text()).toBe('api, sudo'); + expect(cells.at(11).text()).not.toBe('Never'); + expect(cells.at(12).text()).not.toBe('Never'); + expect(cells.at(13).text()).toBe('Expired'); + expect(cells.at(14).text()).toBe('Maintainer'); + buttons = cells.at(15).findAllComponents(GlButton); expect(buttons.at(0).attributes('href')).toBe( '/-/user_settings/personal_access_tokens/2/revoke', ); @@ -237,12 +243,18 @@ describe('~/access_tokens/components/access_token_table_app', () => { }); const headers = findHeaders(); - expect(headers).toHaveLength(6); - ['Token name', 'Scopes', 'Created', 'Last Used', 'Expires', 'Role'].forEach( - (text, index) => { - expect(headers.at(index).text()).toBe(text); - }, - ); + expect(headers).toHaveLength(7); + [ + 'Token name', + 'Description', + 'Scopes', + 'Created', + 'Last Used', + 'Expires', + 'Role', + ].forEach((text, index) => { + expect(headers.at(index).text()).toBe(text); + }); }); }); @@ -259,8 +271,8 @@ describe('~/access_tokens/components/access_token_table_app', () => { backendPagination, }); - expect(findHeaders().at(6).text()).toBe('Action'); - expect(findCells().at(6).findComponent(GlButton).exists()).toBe(false); + expect(findHeaders().at(7).text()).toBe('Action'); + expect(findCells().at(7).findComponent(GlButton).exists()).toBe(false); }); it.each([ @@ -276,8 +288,8 @@ describe('~/access_tokens/components/access_token_table_app', () => { backendPagination, }); - expect(findHeaders().at(6).text()).toBe('Action'); - expect(findCells().at(6).findComponent(GlButton).exists()).toBe(true); + expect(findHeaders().at(7).text()).toBe('Action'); + expect(findCells().at(7).findComponent(GlButton).exists()).toBe(true); }); }); }); @@ -290,7 +302,7 @@ describe('~/access_tokens/components/access_token_table_app', () => { // First and second rows expect(cells.at(0).text()).toBe('a'); - expect(cells.at(7).text()).toBe('b'); + expect(cells.at(8).text()).toBe('b'); const headers = findHeaders(); await headers.at(0).trigger('click'); @@ -298,7 +310,7 @@ describe('~/access_tokens/components/access_token_table_app', () => { // First and second rows have swapped expect(cells.at(0).text()).toBe('b'); - expect(cells.at(7).text()).toBe('a'); + expect(cells.at(8).text()).toBe('a'); }); it('sorts rows by date', async () => { @@ -307,15 +319,15 @@ describe('~/access_tokens/components/access_token_table_app', () => { const cells = findCells(); // First and second rows - expect(cells.at(3).text()).toBe('Never'); - expect(cells.at(10).text()).not.toBe('Never'); + expect(cells.at(4).text()).toBe('Never'); + expect(cells.at(12).text()).not.toBe('Never'); const headers = findHeaders(); - await headers.at(3).trigger('click'); + await headers.at(4).trigger('click'); // First and second rows have swapped - expect(cells.at(3).text()).not.toBe('Never'); - expect(cells.at(10).text()).toBe('Never'); + expect(cells.at(4).text()).not.toBe('Never'); + expect(cells.at(12).text()).toBe('Never'); }); describe('pagination', () => { @@ -342,11 +354,11 @@ describe('~/access_tokens/components/access_token_table_app', () => { describe('when clicked on the second page', () => { it('shows only one token in the table', async () => { - expect(findCells()).toHaveLength(PAGE_SIZE * 6); + expect(findCells()).toHaveLength(PAGE_SIZE * 7); await findPagination().vm.$emit('input', 2); await nextTick(); - expect(findCells()).toHaveLength(6); + expect(findCells()).toHaveLength(7); }); it('scrolls to the top', async () => { @@ -372,7 +384,7 @@ describe('~/access_tokens/components/access_token_table_app', () => { // First and second rows expect(cells.at(0).text()).toBe('a'); - expect(cells.at(7).text()).toBe('b'); + expect(cells.at(8).text()).toBe('b'); const headers = findHeaders(); await headers.at(0).trigger('click'); @@ -380,7 +392,7 @@ describe('~/access_tokens/components/access_token_table_app', () => { // First and second rows are not swapped expect(cells.at(0).text()).toBe('a'); - expect(cells.at(7).text()).toBe('b'); + expect(cells.at(8).text()).toBe('b'); }); it('change the busy state in the table', async () => { diff --git a/spec/frontend/access_tokens/components/inactive_access_token_table_app_spec.js b/spec/frontend/access_tokens/components/inactive_access_token_table_app_spec.js index d2e2081dae3..a7911543477 100644 --- a/spec/frontend/access_tokens/components/inactive_access_token_table_app_spec.js +++ b/spec/frontend/access_tokens/components/inactive_access_token_table_app_spec.js @@ -15,6 +15,7 @@ describe('~/access_tokens/components/inactive_access_token_table_app', () => { const defaultInactiveAccessTokens = [ { name: 'a', + description: 'Test description', scopes: ['api'], created_at: '2023-05-01T00:00:00.000Z', last_used_at: null, @@ -25,6 +26,7 @@ describe('~/access_tokens/components/inactive_access_token_table_app', () => { }, { name: 'b', + description: 'Test description', scopes: ['api', 'sudo'], created_at: '2024-04-21T00:00:00.000Z', last_used_at: '2024-04-21T00:00:00.000Z', @@ -81,6 +83,7 @@ describe('~/access_tokens/components/inactive_access_token_table_app', () => { const headers = findHeaders(); expect(headers.wrappers.map((header) => header.text())).toStrictEqual([ 'Token name', + 'Description', 'Scopes', 'Created', 'Last Used', @@ -94,7 +97,7 @@ describe('~/access_tokens/components/inactive_access_token_table_app', () => { createComponent(); const headers = wrapper.findAll('th'); - const lastUsed = headers.at(3); + const lastUsed = headers.at(4); const anchor = lastUsed.find('a'); const assistiveElement = lastUsed.find('.gl-sr-only'); expect(anchor.exists()).toBe(true); @@ -111,7 +114,7 @@ describe('~/access_tokens/components/inactive_access_token_table_app', () => { // First and second rows expect(cells.at(0).text()).toBe('a'); - expect(cells.at(6).text()).toBe('b'); + expect(cells.at(7).text()).toBe('b'); const headers = findHeaders(); await headers.at(0).trigger('click'); @@ -119,7 +122,7 @@ describe('~/access_tokens/components/inactive_access_token_table_app', () => { // First and second rows have swapped expect(cells.at(0).text()).toBe('b'); - expect(cells.at(6).text()).toBe('a'); + expect(cells.at(7).text()).toBe('a'); }); it('sorts rows by last used date', async () => { @@ -129,14 +132,14 @@ describe('~/access_tokens/components/inactive_access_token_table_app', () => { // First and second rows expect(cells.at(0).text()).toBe('a'); - expect(cells.at(6).text()).toBe('b'); + expect(cells.at(7).text()).toBe('b'); const headers = findHeaders(); - await headers.at(3).trigger('click'); + await headers.at(4).trigger('click'); // First and second rows have swapped expect(cells.at(0).text()).toBe('b'); - expect(cells.at(6).text()).toBe('a'); + expect(cells.at(7).text()).toBe('a'); }); it('sorts rows by expiry date', async () => { @@ -144,11 +147,11 @@ describe('~/access_tokens/components/inactive_access_token_table_app', () => { const cells = findCells(); const headers = findHeaders(); - await headers.at(4).trigger('click'); + await headers.at(5).trigger('click'); // First and second rows have swapped expect(cells.at(0).text()).toBe('b'); - expect(cells.at(6).text()).toBe('a'); + expect(cells.at(7).text()).toBe('a'); }); it('shows Revoked in expiry column when revoked', () => { @@ -157,8 +160,8 @@ describe('~/access_tokens/components/inactive_access_token_table_app', () => { const cells = findCells(); // First and second rows - expect(cells.at(4).text()).toBe('Revoked'); - expect(cells.at(10).text()).toBe('Expired just now'); + expect(cells.at(5).text()).toBe('Revoked'); + expect(cells.at(12).text()).toBe('Expired just now'); }); describe('pagination', () => { diff --git a/spec/frontend/access_tokens/components/new_access_token_app_spec.js b/spec/frontend/access_tokens/components/new_access_token_app_spec.js index 97229f11c50..66451827048 100644 --- a/spec/frontend/access_tokens/components/new_access_token_app_spec.js +++ b/spec/frontend/access_tokens/components/new_access_token_app_spec.js @@ -45,6 +45,7 @@ describe('~/access_tokens/components/new_access_token_app', () => { +