Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
8e805f1259
commit
e56bca3913
|
|
@ -1,5 +1,7 @@
|
|||
trigger-ai-gateway-tagging:
|
||||
stage: ai-gateway
|
||||
# We need the tagging process to be executed even if other jobs in the gitlab pipeline fails
|
||||
needs: []
|
||||
image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}curlimages/curl:latest
|
||||
script:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -3,10 +3,6 @@ include:
|
|||
inputs:
|
||||
gem_name: "mail-smtp_pool"
|
||||
gem_path_prefix: "vendor/gems/"
|
||||
- local: .gitlab/ci/templates/gem.gitlab-ci.yml
|
||||
inputs:
|
||||
gem_name: "attr_encrypted"
|
||||
gem_path_prefix: "vendor/gems/"
|
||||
- local: .gitlab/ci/templates/gem.gitlab-ci.yml
|
||||
inputs:
|
||||
gem_name: "microsoft_graph_mailer"
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ variables:
|
|||
LFS_VERSION: "2.9"
|
||||
NODE_VERSION: "20.12"
|
||||
OS_VERSION: "bookworm"
|
||||
RUBY_VERSION_DEFAULT: "3.2.6"
|
||||
RUBY_VERSION_NEXT: "3.3.7"
|
||||
RUBY_VERSION_DEFAULT: "3.2.8"
|
||||
RUBY_VERSION_NEXT: "3.3.8"
|
||||
RUBYGEMS_VERSION: "3.6"
|
||||
RUST_VERSION: "1.73"
|
||||
UBI_VERSION: "9.5"
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.3.7
|
||||
3.3.8
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
de68b7ae147073d828434bcace613bc4a324b8b9
|
||||
911b4a8ad2769faa16f732fcb7e381cdbc42902d
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="build-page gl-m-3">
|
||||
<div class="build-page">
|
||||
<log-viewer-top-bar :has-timestamps="hasTimestamps" />
|
||||
<log-viewer :log="log" :loading="loading" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ export default {
|
|||
:action-primary="$options.actionPrimary"
|
||||
:action-secondary="$options.actionSecondary"
|
||||
modal-class="set-user-status-modal"
|
||||
visible
|
||||
@primary="setStatus"
|
||||
@secondary="removeStatus"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -244,7 +244,8 @@ export default {
|
|||
onShow() {
|
||||
this.initBuyCIMinsCallout();
|
||||
},
|
||||
closeDropdown() {
|
||||
openStatusModal() {
|
||||
this.setStatusModalReady = true;
|
||||
this.$refs.userDropdown.close();
|
||||
},
|
||||
initBuyCIMinsCallout() {
|
||||
|
|
@ -314,11 +315,11 @@ export default {
|
|||
|
||||
<gl-disclosure-dropdown-group bordered>
|
||||
<gl-disclosure-dropdown-item
|
||||
v-if="setStatusModalReady && statusModalData"
|
||||
v-if="statusModalData"
|
||||
v-gl-modal="$options.SET_STATUS_MODAL_ID"
|
||||
:item="statusItem"
|
||||
data-testid="status-item"
|
||||
@action="closeDropdown"
|
||||
@action="openStatusModal"
|
||||
/>
|
||||
|
||||
<gl-disclosure-dropdown-item
|
||||
|
|
@ -383,10 +384,9 @@ export default {
|
|||
/>
|
||||
</gl-disclosure-dropdown>
|
||||
<set-status-modal
|
||||
v-if="statusModalData"
|
||||
v-if="setStatusModalReady"
|
||||
default-emoji="speech_balloon"
|
||||
v-bind="statusModalData"
|
||||
@mounted="setStatusModalReady = true"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -499,6 +499,7 @@ export default {
|
|||
})
|
||||
.finally(() => {
|
||||
this.isLockDiscussionUpdating = false;
|
||||
this.closeDropdown();
|
||||
});
|
||||
},
|
||||
async promoteToObjective() {
|
||||
|
|
@ -658,7 +659,7 @@ export default {
|
|||
>
|
||||
<template #list-item>
|
||||
<gl-loading-icon v-if="isLockDiscussionUpdating" class="gl-mr-2" inline />
|
||||
<gl-icon :name="lockDiscussionIcon" class="gl-mr-2" variant="subtle" />
|
||||
<gl-icon v-else :name="lockDiscussionIcon" class="gl-mr-2" variant="subtle" />
|
||||
{{ lockDiscussionText }}
|
||||
</template>
|
||||
</gl-disclosure-dropdown-item>
|
||||
|
|
|
|||
|
|
@ -14,9 +14,13 @@ module Mutations
|
|||
required: true,
|
||||
description: 'Full Path of the project the settings belong to.'
|
||||
|
||||
argument :group_runners_enabled, GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
description: 'Indicates whether group runners are enabled for the project.'
|
||||
|
||||
argument :keep_latest_artifact, GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
description: 'Indicates if the latest artifact should be kept for the project.'
|
||||
description: 'Indicates whether the latest artifact should be kept for the project.'
|
||||
|
||||
argument :job_token_scope_enabled, GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
|
|
@ -24,12 +28,12 @@ module Mutations
|
|||
reason: 'Outbound job token scope is being removed. This field can now only be set to false',
|
||||
milestone: '16.0'
|
||||
},
|
||||
description: 'Indicates CI/CD job tokens generated in this project ' \
|
||||
description: 'Indicates whether CI/CD job tokens generated in this project ' \
|
||||
'have restricted access to other projects.'
|
||||
|
||||
argument :inbound_job_token_scope_enabled, GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
description: 'Indicates CI/CD job tokens generated in other projects ' \
|
||||
description: 'Indicates whether CI/CD job tokens generated in other projects ' \
|
||||
'have restricted access to this project.'
|
||||
|
||||
argument :push_repository_for_job_token_allowed, GraphQL::Types::Boolean,
|
||||
|
|
@ -79,6 +83,7 @@ module Mutations
|
|||
|
||||
def project_update_params(_project, **args)
|
||||
{
|
||||
group_runners_enabled: args[:group_runners_enabled],
|
||||
keep_latest_artifact: args[:keep_latest_artifact],
|
||||
ci_outbound_job_token_scope_enabled: args[:job_token_scope_enabled],
|
||||
ci_inbound_job_token_scope_enabled: args[:inbound_job_token_scope_enabled],
|
||||
|
|
|
|||
|
|
@ -49,6 +49,14 @@ module ResolvesPipelines
|
|||
end
|
||||
|
||||
def resolve_pipelines(project, params = {})
|
||||
Ci::PipelinesFinder.new(project, context[:current_user], params).execute
|
||||
pipelines = Ci::PipelinesFinder.new(project, context[:current_user], params).execute
|
||||
|
||||
if %w[branches tags].include?(params[:scope])
|
||||
# `branches` and `tags` scopes are ordered in a complex way that is not supported by the keyset pagination.
|
||||
# We offset pagination here so we return the correct connection.
|
||||
offset_pagination(pipelines)
|
||||
else
|
||||
pipelines
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,30 +7,35 @@ module Types
|
|||
|
||||
authorize :manage_merge_request_settings
|
||||
|
||||
field :group_runners_enabled,
|
||||
GraphQL::Types::Boolean,
|
||||
null: true,
|
||||
description: 'Indicates whether group runners are enabled for the project.',
|
||||
authorize: :admin_project
|
||||
field :inbound_job_token_scope_enabled,
|
||||
GraphQL::Types::Boolean,
|
||||
null: true,
|
||||
description: 'Indicates CI/CD job tokens generated in other projects ' \
|
||||
description: 'Indicates whether CI/CD job tokens generated in other projects ' \
|
||||
'have restricted access to this project.',
|
||||
method: :inbound_job_token_scope_enabled?,
|
||||
authorize: :admin_project
|
||||
field :job_token_scope_enabled,
|
||||
GraphQL::Types::Boolean,
|
||||
null: true,
|
||||
description: 'Indicates CI/CD job tokens generated in this project ' \
|
||||
description: 'Indicates whether CI/CD job tokens generated in this project ' \
|
||||
'have restricted access to other projects.',
|
||||
method: :job_token_scope_enabled?,
|
||||
authorize: :admin_project
|
||||
field :keep_latest_artifact,
|
||||
GraphQL::Types::Boolean,
|
||||
null: true,
|
||||
description: 'Whether to keep the latest builds artifacts.',
|
||||
description: 'Indicates whether the latest artifact should be kept for the project.',
|
||||
method: :keep_latest_artifacts_available?,
|
||||
authorize: :admin_project
|
||||
field :merge_pipelines_enabled,
|
||||
GraphQL::Types::Boolean,
|
||||
null: true,
|
||||
description: 'Whether merged results pipelines are enabled.',
|
||||
description: 'Indicates whether merged results pipelines are enabled.',
|
||||
method: :merge_pipelines_enabled?
|
||||
field :pipeline_variables_minimum_override_role,
|
||||
GraphQL::Types::String,
|
||||
|
|
|
|||
|
|
@ -409,6 +409,7 @@ module Types
|
|||
|
||||
field :pipelines,
|
||||
null: true,
|
||||
calls_gitaly: true,
|
||||
description: 'Pipelines of the project.',
|
||||
extras: [:lookahead],
|
||||
resolver: Resolvers::Ci::ProjectPipelinesResolver
|
||||
|
|
|
|||
|
|
@ -136,6 +136,10 @@ module Ci
|
|||
.transform_values { |s| Ci::RunnerVersion.statuses.key(s).to_sym }
|
||||
end
|
||||
|
||||
def self.ip_address_exists?(ip_address)
|
||||
exists?(ip_address:)
|
||||
end
|
||||
|
||||
def uncached_contacted_at
|
||||
read_attribute(:contacted_at)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@ module ClickHouse
|
|||
reached_end_of_table: context.no_more_records?)
|
||||
|
||||
if context.last_processed_id
|
||||
ClickHouse::SyncCursor.update_cursor_for(model_class.table_name,
|
||||
context.last_processed_id)
|
||||
ClickHouse::SyncCursor.update_cursor_for(sync_cursor_identifier, context.last_processed_id)
|
||||
end
|
||||
end
|
||||
rescue Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError
|
||||
|
|
@ -46,7 +45,7 @@ module ClickHouse
|
|||
|
||||
def context
|
||||
@context ||= ClickHouse::RecordSyncContext.new(
|
||||
last_record_id: ClickHouse::SyncCursor.cursor_for(model_class.table_name),
|
||||
last_record_id: ClickHouse::SyncCursor.cursor_for(sync_cursor_identifier),
|
||||
max_records_per_batch: INSERT_BATCH_SIZE,
|
||||
runtime_limiter: Gitlab::Metrics::RuntimeLimiter.new(MAX_RUNTIME)
|
||||
)
|
||||
|
|
@ -118,6 +117,10 @@ module ClickHouse
|
|||
:id
|
||||
end
|
||||
|
||||
def sync_cursor_identifier
|
||||
model_class.table_name
|
||||
end
|
||||
|
||||
def csv_mapping
|
||||
raise NotImplementedError, "Subclasses must implement `csv_mapping`"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
- @no_container = true
|
||||
- @force_fluid_layout = true
|
||||
- add_to_breadcrumbs _("Jobs"), project_jobs_path(@project)
|
||||
- add_to_breadcrumbs "##{@build.id}", project_job_path(@project, @build)
|
||||
- breadcrumb_title s_("Job|Full log viewer")
|
||||
|
|
|
|||
|
|
@ -113,6 +113,16 @@
|
|||
:idempotent: false
|
||||
:tags: []
|
||||
:queue_namespace: :batched_background_migrations
|
||||
- :name: batched_background_migrations:database_batched_background_migration_sec_execution
|
||||
:worker_name: Database::BatchedBackgroundMigration::SecExecutionWorker
|
||||
:feature_category: :database
|
||||
:has_external_dependencies: false
|
||||
:urgency: :low
|
||||
:resource_boundary: :unknown
|
||||
:weight: 1
|
||||
:idempotent: false
|
||||
:tags: []
|
||||
:queue_namespace: :batched_background_migrations
|
||||
- :name: chaos:chaos_cpu_spin
|
||||
:worker_name: Chaos::CpuSpinWorker
|
||||
:feature_category: :not_owned
|
||||
|
|
@ -526,6 +536,16 @@
|
|||
:idempotent: true
|
||||
:tags: []
|
||||
:queue_namespace: :cronjob
|
||||
- :name: cronjob:database_batched_background_migration_sec_database
|
||||
:worker_name: Database::BatchedBackgroundMigration::SecDatabaseWorker
|
||||
:feature_category: :database
|
||||
:has_external_dependencies: false
|
||||
:urgency: :low
|
||||
:resource_boundary: :unknown
|
||||
:weight: 1
|
||||
:idempotent: true
|
||||
:tags: []
|
||||
:queue_namespace: :cronjob
|
||||
- :name: cronjob:database_ci_namespace_mirrors_consistency_check
|
||||
:worker_name: Database::CiNamespaceMirrorsConsistencyCheckWorker
|
||||
:feature_category: :cell
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Database # rubocop:disable Gitlab/BoundedContexts -- Doesn't make sense to put this elsewhere
|
||||
module BatchedBackgroundMigration
|
||||
class SecDatabaseWorker # rubocop:disable Scalability/IdempotentWorker -- SingleDatabaseWorker is idempotent!
|
||||
include SingleDatabaseWorker
|
||||
|
||||
def self.tracking_database
|
||||
@tracking_database ||= Gitlab::Database::SEC_DATABASE_NAME.to_sym
|
||||
end
|
||||
|
||||
def execution_worker_class
|
||||
@execution_worker_class ||= Database::BatchedBackgroundMigration::SecExecutionWorker
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Database # rubocop:disable Gitlab/BoundedContexts -- Doesn't make sense to put this elsewhere
|
||||
module BatchedBackgroundMigration
|
||||
class SecExecutionWorker # rubocop:disable Scalability/IdempotentWorker -- Not guaranteed to be idempotent
|
||||
include ExecutionWorker
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -32,6 +32,7 @@ domains:
|
|||
- code_suggestions # Also in CodeSuggestions
|
||||
- cloud_connector # Also in CloudConnector
|
||||
- duo_workflow
|
||||
- knowledge_graph
|
||||
|
||||
Analytics:
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
description: REST API endpoint requested from runner
|
||||
internal_events: true
|
||||
action: api_request_from_runner
|
||||
identifiers:
|
||||
- project
|
||||
- namespace
|
||||
additional_properties:
|
||||
label:
|
||||
description: The API endpoint of the request
|
||||
property:
|
||||
description: The token type used to authenticate
|
||||
cross_project_request:
|
||||
description: The request is cross-project
|
||||
product_group: authorization
|
||||
product_categories:
|
||||
- permissions
|
||||
milestone: '18.1'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/189430
|
||||
tiers:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -37,6 +37,7 @@
|
|||
- code_testing
|
||||
- compliance_management
|
||||
- component_catalog
|
||||
- configuration
|
||||
- consumables_cost_management
|
||||
- container_registry
|
||||
- container_scanning
|
||||
|
|
@ -57,6 +58,7 @@
|
|||
- disaster_recovery
|
||||
- dora_metrics
|
||||
- duo_chat
|
||||
- duo_setting
|
||||
- duo_workflow
|
||||
- dynamic_application_security_testing
|
||||
- editor_extensions
|
||||
|
|
@ -84,6 +86,7 @@
|
|||
- integrations
|
||||
- internationalization
|
||||
- job_artifacts
|
||||
- knowledge_graph
|
||||
- markdown
|
||||
- merge_trains
|
||||
- mlops
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
name: track_api_request_from_runner
|
||||
description: Track API requests from runners
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/525339
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/189430
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/538150
|
||||
milestone: '18.1'
|
||||
group: group::authorization
|
||||
type: gitlab_com_derisk
|
||||
default_enabled: false
|
||||
|
|
@ -513,6 +513,10 @@ p_ci_workloads:
|
|||
- table: projects
|
||||
column: project_id
|
||||
on_delete: async_delete
|
||||
p_knowledge_graph_replicas:
|
||||
- table: p_knowledge_graph_enabled_namespaces
|
||||
column: knowledge_graph_enabled_namespace_id
|
||||
on_delete: async_nullify
|
||||
packages_build_infos:
|
||||
- table: p_ci_pipelines
|
||||
column: pipeline_id
|
||||
|
|
|
|||
|
|
@ -681,6 +681,9 @@ Settings.cron_jobs['batched_background_migrations_worker']['job_class'] = 'Datab
|
|||
Settings.cron_jobs['batched_background_migration_worker_ci_database'] ||= {}
|
||||
Settings.cron_jobs['batched_background_migration_worker_ci_database']['cron'] ||= '* * * * *'
|
||||
Settings.cron_jobs['batched_background_migration_worker_ci_database']['job_class'] = 'Database::BatchedBackgroundMigration::CiDatabaseWorker'
|
||||
Settings.cron_jobs['batched_background_migration_worker_sec_database'] ||= {}
|
||||
Settings.cron_jobs['batched_background_migration_worker_sec_database']['cron'] ||= '* * * * *'
|
||||
Settings.cron_jobs['batched_background_migration_worker_sec_database']['job_class'] = 'Database::BatchedBackgroundMigration::SecDatabaseWorker'
|
||||
Settings.cron_jobs['issues_reschedule_stuck_issue_rebalances'] ||= {}
|
||||
Settings.cron_jobs['issues_reschedule_stuck_issue_rebalances']['cron'] ||= '*/15 * * * *'
|
||||
Settings.cron_jobs['issues_reschedule_stuck_issue_rebalances']['job_class'] = 'Issues::RescheduleStuckIssueRebalancesWorker'
|
||||
|
|
@ -914,6 +917,9 @@ Gitlab.ee do
|
|||
Settings.cron_jobs['vulnerability_orphaned_remediations_cleanup_worker'] ||= {}
|
||||
Settings.cron_jobs['vulnerability_orphaned_remediations_cleanup_worker']['job_class'] = 'Vulnerabilities::OrphanedRemediationsCleanupWorker'
|
||||
Settings.cron_jobs['vulnerability_orphaned_remediations_cleanup_worker']['cron'] ||= '15 3 * * */6'
|
||||
Settings.cron_jobs['security_analyzer_namespace_statuses_schedule_worker'] ||= {}
|
||||
Settings.cron_jobs['security_analyzer_namespace_statuses_schedule_worker']['cron'] ||= '0 8 * * 0'
|
||||
Settings.cron_jobs['security_analyzer_namespace_statuses_schedule_worker']['job_class'] = 'Security::AnalyzerNamespaceStatuses::ScheduleWorker'
|
||||
Settings.cron_jobs['security_create_orchestration_policy_worker'] ||= {}
|
||||
Settings.cron_jobs['security_create_orchestration_policy_worker']['cron'] ||= '*/10 * * * *'
|
||||
Settings.cron_jobs['security_create_orchestration_policy_worker']['job_class'] = 'Security::CreateOrchestrationPolicyWorker'
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@ if Gitlab.ee?
|
|||
Ai::TroubleshootJobEvent,
|
||||
Vulnerabilities::Archive,
|
||||
Vulnerabilities::ArchivedRecord,
|
||||
Vulnerabilities::ArchiveExport
|
||||
Vulnerabilities::ArchiveExport,
|
||||
Ai::KnowledgeGraph::EnabledNamespace,
|
||||
Ai::KnowledgeGraph::Replica
|
||||
])
|
||||
else
|
||||
Gitlab::Database::Partitioning.register_tables(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: redis_hll_counters.count_ci_job_tokens_from_api_request_from_runner
|
||||
description: Count of unique REST API endpoints requested from CI/CD runners
|
||||
product_group: authorization
|
||||
product_categories:
|
||||
- permissions
|
||||
performance_indicator_type: []
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: '18.1'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/189430
|
||||
time_frame:
|
||||
- 28d
|
||||
- 7d
|
||||
data_source: internal_events
|
||||
data_category: standard
|
||||
tiers:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
events:
|
||||
- name: api_request_from_runner
|
||||
filter:
|
||||
property: ci_job_token
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: redis_hll_counters.count_cluster_agent_tokens_from_api_request_from_runner
|
||||
description: Count of unique REST API endpoints requested from CI/CD runners
|
||||
product_group: authorization
|
||||
product_categories:
|
||||
- permissions
|
||||
performance_indicator_type: []
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: '18.1'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/189430
|
||||
time_frame:
|
||||
- 28d
|
||||
- 7d
|
||||
data_source: internal_events
|
||||
data_category: standard
|
||||
tiers:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
events:
|
||||
- name: api_request_from_runner
|
||||
filter:
|
||||
property: cluster_agent_token
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: redis_hll_counters.count_deploy_tokens_from_api_request_from_runner
|
||||
description: Count of unique REST API endpoints requested from CI/CD runners
|
||||
product_group: authorization
|
||||
product_categories:
|
||||
- permissions
|
||||
performance_indicator_type: []
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: '18.1'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/189430
|
||||
time_frame:
|
||||
- 28d
|
||||
- 7d
|
||||
data_source: internal_events
|
||||
data_category: standard
|
||||
tiers:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
events:
|
||||
- name: api_request_from_runner
|
||||
filter:
|
||||
property: deploy_token
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: redis_hll_counters.count_group_access_tokens_from_api_request_from_runner
|
||||
description: Count of unique REST API endpoints requested from CI/CD runners
|
||||
product_group: authorization
|
||||
product_categories:
|
||||
- permissions
|
||||
performance_indicator_type: []
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: '18.1'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/189430
|
||||
time_frame:
|
||||
- 28d
|
||||
- 7d
|
||||
data_source: internal_events
|
||||
data_category: standard
|
||||
tiers:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
events:
|
||||
- name: api_request_from_runner
|
||||
filter:
|
||||
property: group_access_token
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: redis_hll_counters.count_oauth_application_secrets_from_api_request_from_runner
|
||||
description: Count of unique REST API endpoints requested from CI/CD runners
|
||||
product_group: authorization
|
||||
product_categories:
|
||||
- permissions
|
||||
performance_indicator_type: []
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: '18.1'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/189430
|
||||
time_frame:
|
||||
- 28d
|
||||
- 7d
|
||||
data_source: internal_events
|
||||
data_category: standard
|
||||
tiers:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
events:
|
||||
- name: api_request_from_runner
|
||||
filter:
|
||||
property: oauth_application_secret
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: redis_hll_counters.count_personal_access_tokens_from_api_request_from_runner
|
||||
description: Count of unique REST API endpoints requested from CI/CD runners
|
||||
product_group: authorization
|
||||
product_categories:
|
||||
- permissions
|
||||
performance_indicator_type: []
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: '18.1'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/189430
|
||||
time_frame:
|
||||
- 28d
|
||||
- 7d
|
||||
data_source: internal_events
|
||||
data_category: standard
|
||||
tiers:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
events:
|
||||
- name: api_request_from_runner
|
||||
filter:
|
||||
property: personal_access_token
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: redis_hll_counters.count_project_access_tokens_from_api_request_from_runner
|
||||
description: Count of unique REST API endpoints requested from CI/CD runners
|
||||
product_group: authorization
|
||||
product_categories:
|
||||
- permissions
|
||||
performance_indicator_type: []
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: '18.1'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/189430
|
||||
time_frame:
|
||||
- 28d
|
||||
- 7d
|
||||
data_source: internal_events
|
||||
data_category: standard
|
||||
tiers:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
events:
|
||||
- name: api_request_from_runner
|
||||
filter:
|
||||
property: project_access_token
|
||||
|
|
@ -877,6 +877,8 @@
|
|||
- 1
|
||||
- - secrets_management_provision_project_secrets_manager
|
||||
- 1
|
||||
- - security_analyzer_namespace_statuses_adjustment
|
||||
- 1
|
||||
- - security_analyzers_status_process_archived_events
|
||||
- 1
|
||||
- - security_configuration_set_group_secret_push_protection
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
table_name: p_knowledge_graph_enabled_namespaces
|
||||
classes:
|
||||
- Ai::KnowledgeGraph::EnabledNamespace
|
||||
feature_categories:
|
||||
- knowledge_graph
|
||||
description: Represents a namespace with enabled knowledge graph
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/191162
|
||||
milestone: '18.1'
|
||||
gitlab_schema: gitlab_main_cell
|
||||
sharding_key:
|
||||
namespace_id: namespaces
|
||||
table_size: small
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
table_name: p_knowledge_graph_replicas
|
||||
classes:
|
||||
- Ai::KnowledgeGraph::Replica
|
||||
feature_categories:
|
||||
- knowledge_graph
|
||||
description: Represents a replica of a namespace on a Zoekt node
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/191162
|
||||
milestone: '18.1'
|
||||
gitlab_schema: gitlab_main_cell_local
|
||||
table_size: small
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddKnowledgeGraphEnabledNamespaces < Gitlab::Database::Migration[2.3]
|
||||
include Gitlab::Database::PartitioningMigrationHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
milestone '18.1'
|
||||
|
||||
TABLE_NAME = :p_knowledge_graph_enabled_namespaces
|
||||
PARTITION_SIZE = 2_000_000
|
||||
MIN_ID = Namespace.connection
|
||||
.select_value("select min_value from pg_sequences where sequencename = 'namespaces_id_seq'") || 1
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
create_table TABLE_NAME,
|
||||
options: 'PARTITION BY RANGE (namespace_id)',
|
||||
primary_key: [:id, :namespace_id], if_not_exists: true do |t|
|
||||
t.bigserial :id, null: false
|
||||
t.bigint :namespace_id, null: false
|
||||
t.timestamps_with_timezone null: false
|
||||
t.integer :state, null: false, default: 0, limit: 2, index: true
|
||||
t.index :namespace_id, unique: true
|
||||
end
|
||||
end
|
||||
|
||||
create_partitions
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table TABLE_NAME
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_partitions
|
||||
max_id = Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.with_suppressed do
|
||||
Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection.with_suppressed do
|
||||
define_batchable_model('namespaces', connection: connection).maximum(:id) || MIN_ID
|
||||
end
|
||||
end
|
||||
|
||||
create_int_range_partitions(TABLE_NAME, PARTITION_SIZE, MIN_ID, max_id)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddKnowledgeGraphReplicas < Gitlab::Database::Migration[2.3]
|
||||
include Gitlab::Database::PartitioningMigrationHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
milestone '18.1'
|
||||
|
||||
TABLE_NAME = :p_knowledge_graph_replicas
|
||||
PARTITION_SIZE = 2_000_000
|
||||
MIN_ID = Namespace.connection
|
||||
.select_value("select min_value from pg_sequences where sequencename = 'namespaces_id_seq'") || 1
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
create_table TABLE_NAME,
|
||||
options: 'PARTITION BY RANGE (namespace_id)',
|
||||
primary_key: [:id, :namespace_id], if_not_exists: true do |t|
|
||||
t.bigserial :id, null: false
|
||||
t.bigint :namespace_id, null: false
|
||||
t.bigint :knowledge_graph_enabled_namespace_id, null: true
|
||||
t.bigint :zoekt_node_id, null: false, index: true
|
||||
t.timestamps_with_timezone null: false
|
||||
t.integer :state, null: false, index: true, default: 0, limit: 2
|
||||
t.integer :retries_left, limit: 2, null: false
|
||||
t.index :namespace_id, unique: true,
|
||||
name: 'index_p_knowledge_graph_replicas_on_namespace_id', using: :btree
|
||||
t.check_constraint 'retries_left > 0 OR retries_left = 0 AND state >= 200',
|
||||
name: 'c_p_knowledge_graph_replicas_retries_status'
|
||||
end
|
||||
end
|
||||
|
||||
create_partitions
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table TABLE_NAME
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_partitions
|
||||
max_id = Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.with_suppressed do
|
||||
Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection.with_suppressed do
|
||||
define_batchable_model('namespaces', connection: connection).maximum(:id) || MIN_ID
|
||||
end
|
||||
end
|
||||
|
||||
create_int_range_partitions(TABLE_NAME, PARTITION_SIZE, MIN_ID, max_id)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateKnowledgeGraphNamespaceForeignKey < Gitlab::Database::Migration[2.3]
|
||||
include Gitlab::Database::PartitioningMigrationHelpers::ForeignKeyHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
milestone '18.1'
|
||||
|
||||
def up
|
||||
add_concurrent_partitioned_foreign_key :p_knowledge_graph_enabled_namespaces, :namespaces,
|
||||
column: :namespace_id, on_delete: :cascade
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key :p_knowledge_graph_enabled_namespaces, column: :namespace_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateKnowledgeGraphReplicaNodeForeignKey < Gitlab::Database::Migration[2.3]
|
||||
include Gitlab::Database::PartitioningMigrationHelpers::ForeignKeyHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
milestone '18.1'
|
||||
|
||||
def up
|
||||
add_concurrent_partitioned_foreign_key :p_knowledge_graph_replicas, :zoekt_nodes,
|
||||
column: :zoekt_node_id, on_delete: :cascade
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key :p_knowledge_graph_replicas, column: :zoekt_node_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateKnowledgeGraphReplicaNamespaceForeignKey < Gitlab::Database::Migration[2.3]
|
||||
include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
|
||||
|
||||
milestone '18.1'
|
||||
|
||||
def up
|
||||
track_record_deletions_override_table_name(:p_knowledge_graph_enabled_namespaces)
|
||||
end
|
||||
|
||||
def down
|
||||
untrack_record_deletions(:p_knowledge_graph_enabled_namespaces)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddKnowledgeGraphReplicasIndex < Gitlab::Database::Migration[2.3]
|
||||
include Gitlab::Database::PartitioningMigrationHelpers
|
||||
|
||||
milestone '18.1'
|
||||
disable_ddl_transaction!
|
||||
|
||||
TABLE_NAME = :p_knowledge_graph_replicas
|
||||
INDEX_NAME = :p_knowledge_graph_replicas_namespace_id_and_zoekt_node_id
|
||||
|
||||
def up
|
||||
add_concurrent_partitioned_index TABLE_NAME,
|
||||
[:knowledge_graph_enabled_namespace_id, :zoekt_node_id, :namespace_id], unique: true,
|
||||
name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_partitioned_index_by_name(TABLE_NAME, INDEX_NAME)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddIndexToCiRunnerMachinesOnIpAddress < Gitlab::Database::Migration[2.3]
|
||||
include Gitlab::Database::PartitioningMigrationHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
milestone '18.1'
|
||||
|
||||
INDEX_NAME = :index_ci_runner_machines_on_ip_address
|
||||
|
||||
def up
|
||||
add_concurrent_partitioned_index :ci_runner_machines, :ip_address, name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_partitioned_index_by_name :ci_runner_machines, INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
7e7bf46103dcffb6354e6f4aa27936cc48a3a8fa66b2e08ace18b8fd7e6d7036
|
||||
|
|
@ -0,0 +1 @@
|
|||
2dd1e12f140324e75d05581d5016749ad202045ecde8d983446c3e97cb2ef91c
|
||||
|
|
@ -0,0 +1 @@
|
|||
aa3ead0fab83df13bce2342c2b52f7f9cacbe69635995587e9db66b1a0dfbee5
|
||||
|
|
@ -0,0 +1 @@
|
|||
a78d3176900873832c9a584e8ccfdfa688a36b6fc45dfc9a3f07ac6f0054559d
|
||||
|
|
@ -0,0 +1 @@
|
|||
1807d47c2367f22d8979dcc3b08506771e5712ea688695a5ec37ce7abd815ae3
|
||||
|
|
@ -0,0 +1 @@
|
|||
cdbcfd9f7f540d5ad3cb02161feae24a919658709cbe70e021a25cdd7c5e428d
|
||||
|
|
@ -0,0 +1 @@
|
|||
313e66083d31bb2341052672ee2adc1f4d39f91844ae64fc4c639c8fe7a12ef8
|
||||
|
|
@ -4880,6 +4880,28 @@ CREATE TABLE p_ci_finished_pipeline_ch_sync_events (
|
|||
)
|
||||
PARTITION BY LIST (partition);
|
||||
|
||||
CREATE TABLE p_knowledge_graph_enabled_namespaces (
|
||||
id bigint NOT NULL,
|
||||
namespace_id bigint NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
state smallint DEFAULT 0 NOT NULL
|
||||
)
|
||||
PARTITION BY RANGE (namespace_id);
|
||||
|
||||
CREATE TABLE p_knowledge_graph_replicas (
|
||||
id bigint NOT NULL,
|
||||
namespace_id bigint NOT NULL,
|
||||
knowledge_graph_enabled_namespace_id bigint,
|
||||
zoekt_node_id bigint NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
state smallint DEFAULT 0 NOT NULL,
|
||||
retries_left smallint NOT NULL,
|
||||
CONSTRAINT c_p_knowledge_graph_replicas_retries_status CHECK (((retries_left > 0) OR ((retries_left = 0) AND (state >= 200))))
|
||||
)
|
||||
PARTITION BY RANGE (namespace_id);
|
||||
|
||||
CREATE TABLE project_audit_events (
|
||||
id bigint DEFAULT nextval('shared_audit_event_id_seq'::regclass) NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
|
|
@ -18896,6 +18918,24 @@ CREATE SEQUENCE p_ci_workloads_id_seq
|
|||
|
||||
ALTER SEQUENCE p_ci_workloads_id_seq OWNED BY p_ci_workloads.id;
|
||||
|
||||
CREATE SEQUENCE p_knowledge_graph_enabled_namespaces_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
ALTER SEQUENCE p_knowledge_graph_enabled_namespaces_id_seq OWNED BY p_knowledge_graph_enabled_namespaces.id;
|
||||
|
||||
CREATE SEQUENCE p_knowledge_graph_replicas_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
ALTER SEQUENCE p_knowledge_graph_replicas_id_seq OWNED BY p_knowledge_graph_replicas.id;
|
||||
|
||||
CREATE TABLE packages_build_infos (
|
||||
id bigint NOT NULL,
|
||||
package_id bigint NOT NULL,
|
||||
|
|
@ -27669,6 +27709,10 @@ ALTER TABLE ONLY p_ci_builds_metadata ALTER COLUMN id SET DEFAULT nextval('ci_bu
|
|||
|
||||
ALTER TABLE ONLY p_ci_workloads ALTER COLUMN id SET DEFAULT nextval('p_ci_workloads_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY p_knowledge_graph_enabled_namespaces ALTER COLUMN id SET DEFAULT nextval('p_knowledge_graph_enabled_namespaces_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY p_knowledge_graph_replicas ALTER COLUMN id SET DEFAULT nextval('p_knowledge_graph_replicas_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY packages_build_infos ALTER COLUMN id SET DEFAULT nextval('packages_build_infos_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY packages_conan_file_metadata ALTER COLUMN id SET DEFAULT nextval('packages_conan_file_metadata_id_seq'::regclass);
|
||||
|
|
@ -30433,6 +30477,12 @@ ALTER TABLE ONLY p_ci_stages
|
|||
ALTER TABLE ONLY p_ci_workloads
|
||||
ADD CONSTRAINT p_ci_workloads_pkey PRIMARY KEY (id, partition_id);
|
||||
|
||||
ALTER TABLE ONLY p_knowledge_graph_enabled_namespaces
|
||||
ADD CONSTRAINT p_knowledge_graph_enabled_namespaces_pkey PRIMARY KEY (id, namespace_id);
|
||||
|
||||
ALTER TABLE ONLY p_knowledge_graph_replicas
|
||||
ADD CONSTRAINT p_knowledge_graph_replicas_pkey PRIMARY KEY (id, namespace_id);
|
||||
|
||||
ALTER TABLE ONLY packages_build_infos
|
||||
ADD CONSTRAINT packages_build_infos_pkey PRIMARY KEY (id);
|
||||
|
||||
|
|
@ -33672,6 +33722,10 @@ CREATE INDEX index_ci_runner_machines_on_executor_type ON ONLY ci_runner_machine
|
|||
|
||||
CREATE INDEX index_012094097c ON instance_type_ci_runner_machines USING btree (executor_type);
|
||||
|
||||
CREATE INDEX index_ci_runner_machines_on_ip_address ON ONLY ci_runner_machines USING btree (ip_address);
|
||||
|
||||
CREATE INDEX index_053d12f7ee ON project_type_ci_runner_machines USING btree (ip_address);
|
||||
|
||||
CREATE INDEX index_p_ci_builds_on_execution_config_id ON ONLY p_ci_builds USING btree (execution_config_id) WHERE (execution_config_id IS NOT NULL);
|
||||
|
||||
CREATE INDEX index_0928d9f200 ON ci_builds USING btree (execution_config_id) WHERE (execution_config_id IS NOT NULL);
|
||||
|
|
@ -34772,6 +34826,8 @@ CREATE UNIQUE INDEX index_customer_relations_contacts_on_unique_email_per_group
|
|||
|
||||
CREATE UNIQUE INDEX index_cycle_analytics_stage_event_hashes_on_org_id_sha_256 ON analytics_cycle_analytics_stage_event_hashes USING btree (organization_id, hash_sha256);
|
||||
|
||||
CREATE INDEX index_d2746151f0 ON instance_type_ci_runner_machines USING btree (ip_address);
|
||||
|
||||
CREATE INDEX index_d58435d85e ON project_type_ci_runner_machines USING btree (executor_type);
|
||||
|
||||
CREATE INDEX p_ci_pipelines_trigger_id_id_desc_idx ON ONLY p_ci_pipelines USING btree (trigger_id, id DESC);
|
||||
|
|
@ -35044,6 +35100,8 @@ CREATE INDEX index_early_access_program_tracking_events_on_event_name ON early_a
|
|||
|
||||
CREATE INDEX index_early_access_program_tracking_events_on_user_id ON early_access_program_tracking_events USING btree (user_id);
|
||||
|
||||
CREATE INDEX index_ee7c87e634 ON group_type_ci_runner_machines USING btree (ip_address);
|
||||
|
||||
CREATE UNIQUE INDEX index_elastic_index_settings_on_alias_name ON elastic_index_settings USING btree (alias_name);
|
||||
|
||||
CREATE INDEX index_elastic_reindexing_subtasks_on_elastic_reindexing_task_id ON elastic_reindexing_subtasks USING btree (elastic_reindexing_task_id);
|
||||
|
|
@ -36436,6 +36494,16 @@ CREATE INDEX index_p_ci_runner_machine_builds_on_runner_machine_id ON ONLY p_ci_
|
|||
|
||||
CREATE INDEX index_p_ci_workloads_on_project_id ON ONLY p_ci_workloads USING btree (project_id);
|
||||
|
||||
CREATE UNIQUE INDEX index_p_knowledge_graph_enabled_namespaces_on_namespace_id ON ONLY p_knowledge_graph_enabled_namespaces USING btree (namespace_id);
|
||||
|
||||
CREATE INDEX index_p_knowledge_graph_enabled_namespaces_on_state ON ONLY p_knowledge_graph_enabled_namespaces USING btree (state);
|
||||
|
||||
CREATE UNIQUE INDEX index_p_knowledge_graph_replicas_on_namespace_id ON ONLY p_knowledge_graph_replicas USING btree (namespace_id);
|
||||
|
||||
CREATE INDEX index_p_knowledge_graph_replicas_on_state ON ONLY p_knowledge_graph_replicas USING btree (state);
|
||||
|
||||
CREATE INDEX index_p_knowledge_graph_replicas_on_zoekt_node_id ON ONLY p_knowledge_graph_replicas USING btree (zoekt_node_id);
|
||||
|
||||
CREATE INDEX index_packages_build_infos_on_pipeline_id ON packages_build_infos USING btree (pipeline_id);
|
||||
|
||||
CREATE INDEX index_packages_build_infos_on_project_id ON packages_build_infos USING btree (project_id);
|
||||
|
|
@ -38428,6 +38496,8 @@ CREATE INDEX p_ci_stages_project_id_idx ON ONLY p_ci_stages USING btree (project
|
|||
|
||||
CREATE UNIQUE INDEX p_ci_workloads_pipeline_id_idx ON ONLY p_ci_workloads USING btree (pipeline_id, partition_id);
|
||||
|
||||
CREATE UNIQUE INDEX p_knowledge_graph_replicas_namespace_id_and_zoekt_node_id ON ONLY p_knowledge_graph_replicas USING btree (knowledge_graph_enabled_namespace_id, zoekt_node_id, namespace_id);
|
||||
|
||||
CREATE INDEX package_name_index ON packages_packages USING btree (name);
|
||||
|
||||
CREATE INDEX packages_packages_failed_verification ON packages_package_files USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
|
||||
|
|
@ -40768,6 +40838,8 @@ ALTER INDEX index_uploads_9ba88c4165_on_uploader_and_path ATTACH PARTITION impor
|
|||
|
||||
ALTER INDEX index_ci_runner_machines_on_executor_type ATTACH PARTITION index_012094097c;
|
||||
|
||||
ALTER INDEX index_ci_runner_machines_on_ip_address ATTACH PARTITION index_053d12f7ee;
|
||||
|
||||
ALTER INDEX index_p_ci_builds_on_execution_config_id ATTACH PARTITION index_0928d9f200;
|
||||
|
||||
ALTER INDEX index_ci_runner_machines_on_executor_type ATTACH PARTITION index_aa3b4fe8c6;
|
||||
|
|
@ -40850,10 +40922,14 @@ ALTER INDEX p_ci_pipelines_user_id_id_idx ATTACH PARTITION index_ci_pipelines_on
|
|||
|
||||
ALTER INDEX p_ci_pipelines_user_id_id_idx1 ATTACH PARTITION index_ci_pipelines_on_user_id_and_id_desc_and_user_not_verified;
|
||||
|
||||
ALTER INDEX index_ci_runner_machines_on_ip_address ATTACH PARTITION index_d2746151f0;
|
||||
|
||||
ALTER INDEX index_ci_runner_machines_on_executor_type ATTACH PARTITION index_d58435d85e;
|
||||
|
||||
ALTER INDEX p_ci_pipelines_trigger_id_id_desc_idx ATTACH PARTITION index_d8ae6ea3f3;
|
||||
|
||||
ALTER INDEX index_ci_runner_machines_on_ip_address ATTACH PARTITION index_ee7c87e634;
|
||||
|
||||
ALTER INDEX p_ci_builds_user_id_name_idx ATTACH PARTITION index_partial_ci_builds_on_user_id_name_parser_features;
|
||||
|
||||
ALTER INDEX p_ci_builds_user_id_name_created_at_idx ATTACH PARTITION index_secure_ci_builds_on_user_id_name_created_at;
|
||||
|
|
@ -41288,6 +41364,8 @@ CREATE TRIGGER p_ci_pipelines_loose_fk_trigger AFTER DELETE ON p_ci_pipelines RE
|
|||
|
||||
CREATE TRIGGER p_ci_workloads_loose_fk_trigger AFTER DELETE ON p_ci_workloads REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records_override_table('p_ci_workloads');
|
||||
|
||||
CREATE TRIGGER p_knowledge_graph_enabled_namespaces_loose_fk_trigger AFTER DELETE ON p_knowledge_graph_enabled_namespaces REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records_override_table('p_knowledge_graph_enabled_namespaces');
|
||||
|
||||
CREATE TRIGGER plans_loose_fk_trigger AFTER DELETE ON plans REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
|
||||
|
||||
CREATE TRIGGER pool_repositories_loose_fk_trigger AFTER DELETE ON pool_repositories REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
|
||||
|
|
@ -44550,6 +44628,9 @@ ALTER TABLE ONLY duo_workflows_checkpoint_writes
|
|||
ALTER TABLE ONLY issuable_resource_links
|
||||
ADD CONSTRAINT fk_rails_3f0ec6b1cf FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE p_knowledge_graph_replicas
|
||||
ADD CONSTRAINT fk_rails_3f20642c2f FOREIGN KEY (zoekt_node_id) REFERENCES zoekt_nodes(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY analytics_cycle_analytics_stage_aggregations
|
||||
ADD CONSTRAINT fk_rails_3f409802fc FOREIGN KEY (stage_id) REFERENCES analytics_cycle_analytics_group_stages(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
@ -45054,6 +45135,9 @@ ALTER TABLE ONLY personal_access_token_last_used_ips
|
|||
ALTER TABLE ONLY clusters_kubernetes_namespaces
|
||||
ADD CONSTRAINT fk_rails_7e7688ecaf FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE p_knowledge_graph_enabled_namespaces
|
||||
ADD CONSTRAINT fk_rails_801c561c42 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY security_policies
|
||||
ADD CONSTRAINT fk_rails_802ceea0c8 FOREIGN KEY (security_orchestration_policy_configuration_id) REFERENCES security_orchestration_policy_configurations(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
---
|
||||
stage: Tenant Scale
|
||||
group: Organizations
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
gitlab_dedicated: yes
|
||||
title: Dormant project deletion
|
||||
---
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Tier: Free, Premium, Ultimate
|
||||
- Offering: GitLab Self-Managed, GitLab Dedicated
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
{{< history >}}
|
||||
|
||||
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0 [with a flag](feature_flags.md) named `inactive_projects_deletion`. Disabled by default.
|
||||
- [Feature flag `inactive_projects_deletion`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96803) removed in GitLab 15.4.
|
||||
- Configuration through GitLab UI [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85575) in GitLab 15.1.
|
||||
- [Renamed](https://gitlab.com/gitlab-org/gitlab/-/work_items/533275) from inactive project deletion in GitLab 18.1.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
Over time, projects in large GitLab instances can become dormant and use unnecessary disk space.
|
||||
|
||||
You can configure GitLab to automatically delete dormant projects after a specific period of inactivity.
|
||||
When a project has no activity within this defined period:
|
||||
|
||||
- Maintainers receive notifications that warn about the scheduled deletion.
|
||||
- If no activity occurs in the project, GitLab deletes it when the timeframe expires.
|
||||
- When deletion occurs, GitLab generates an audit event that shows @GitLab-Admin-Bot performed the deletion.
|
||||
|
||||
For the default setting on GitLab.com, see [GitLab.com settings](../user/gitlab_com/_index.md#dormant-project-deletion).
|
||||
|
||||
## Configure dormant project deletion
|
||||
|
||||
To configure deletion of dormant projects:
|
||||
|
||||
1. On the left sidebar, at the bottom, select **Admin**.
|
||||
1. Select **Settings > Repository**.
|
||||
1. Expand **Repository maintenance**.
|
||||
1. In the **Dormant project deletion** section, select **Delete dormant projects**.
|
||||
1. Configure the settings.
|
||||
- The warning email is sent to users who have the Owner and Maintainer role for the dormant project.
|
||||
- The email duration must be less than the **Delete project after** duration.
|
||||
1. Select **Save changes**.
|
||||
|
||||
Dormant projects that meet the criteria are scheduled for deletion and a warning email is sent. If the
|
||||
projects remain dormant, they are deleted after the specified duration. These projects are deleted even if
|
||||
[the project is archived](../user/project/working_with_projects.md#archive-a-project).
|
||||
|
||||
### Configuration example
|
||||
|
||||
#### Example 1
|
||||
|
||||
If you use these settings:
|
||||
|
||||
- **Delete dormant projects** enabled.
|
||||
- **Delete dormant projects that exceed** set to `50`.
|
||||
- **Delete project after** set to `12`.
|
||||
- **Send warning email** set to `6`.
|
||||
|
||||
If a project is less than 50 MB, the project is not considered dormant.
|
||||
|
||||
If a project is more than 50 MB and it is dormant for:
|
||||
|
||||
- More than 6 months: A deletion warning email is sent. This email includes the date at which the project will be scheduled for deletion.
|
||||
- More than 12 months: The project is scheduled for deletion.
|
||||
|
||||
#### Example 2
|
||||
|
||||
If you use these settings:
|
||||
|
||||
- **Delete dormant projects** enabled.
|
||||
- **Delete dormant projects that exceed** set to `0`.
|
||||
- **Delete project after** set to `12`.
|
||||
- **Send warning email** set to `11`.
|
||||
|
||||
Because the size limit has been set to 0 MB, all projects in an instance are covered.
|
||||
If a project is dormant for:
|
||||
|
||||
- More than 11 months: A deletion warning email is sent. This email includes the date at which the project will be scheduled for deletion.
|
||||
- More than 12 months: The project is scheduled for deletion.
|
||||
|
||||
If a project exists that has already been dormant for more than 12 months when you configure these settings:
|
||||
|
||||
- A deletion warning email is sent immediately. This email includes the date at which the project will be scheduled for deletion.
|
||||
- The project is scheduled for deletion 1 month (12 months - 11 months) after the warning email has been sent.
|
||||
|
||||
## Determine when a project was last active
|
||||
|
||||
You can view a project's activities and determine when the project was last active in the following ways:
|
||||
|
||||
- Go to the [activity page](../user/project/working_with_projects.md#view-project-activity) for the project and view
|
||||
the date of the latest event.
|
||||
- View the `last_activity_at` attribute for the project using the [Projects API](../api/projects.md).
|
||||
- List the visible events for the project using the [Events API](../api/events.md#list-all-visible-events-for-a-project).
|
||||
View the `created_at` attribute of the latest event.
|
||||
|
|
@ -176,7 +176,7 @@ To trigger a manual prune of unreachable objects:
|
|||
|
||||
While GitLab automatically performs housekeeping tasks based on the number of
|
||||
pushes, it does not maintain repositories that don't receive any pushes at all.
|
||||
As a result, inactive repositories or repositories that are only getting read
|
||||
As a result, dormant repositories or repositories that are only getting read
|
||||
requests may not benefit from improvements in the repository housekeeping
|
||||
strategy.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,91 +1,13 @@
|
|||
---
|
||||
stage: Tenant Scale
|
||||
group: Organizations
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
gitlab_dedicated: yes
|
||||
title: Dormant project deletion
|
||||
redirect_to: 'dormant_project_deletion.md'
|
||||
remove_date: '2025-08-20'
|
||||
---
|
||||
|
||||
{{< details >}}
|
||||
<!-- markdownlint-disable -->
|
||||
|
||||
- Tier: Free, Premium, Ultimate
|
||||
- Offering: GitLab Self-Managed, GitLab Dedicated
|
||||
This document was moved to [another location](dormant_project_deletion.md).
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
{{< history >}}
|
||||
|
||||
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0 [with a flag](feature_flags.md) named `inactive_projects_deletion`. Disabled by default.
|
||||
- [Feature flag `inactive_projects_deletion`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96803) removed in GitLab 15.4.
|
||||
- Configuration through GitLab UI [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85575) in GitLab 15.1.
|
||||
- [Renamed](https://gitlab.com/gitlab-org/gitlab/-/work_items/533275) from inactive project deletion in GitLab 18.1.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
Administrators of large GitLab instances can find that over time, projects become dormant and are no longer used.
|
||||
These projects take up unnecessary disk space.
|
||||
|
||||
With dormant project deletion, you can identify these projects, warn the maintainers ahead of time, and then delete the
|
||||
projects if they remain dormant. When an dormant project is deleted, the action generates an audit event that it was
|
||||
performed by the @GitLab-Admin-Bot.
|
||||
|
||||
For the default setting on GitLab.com, see the [GitLab.com settings page](../user/gitlab_com/_index.md#inactive-project-deletion).
|
||||
|
||||
## Configure dormant project deletion
|
||||
|
||||
To configure deletion of dormant projects:
|
||||
|
||||
1. On the left sidebar, at the bottom, select **Admin**.
|
||||
1. Select **Settings > Repository**.
|
||||
1. Expand **Repository maintenance**.
|
||||
1. In the **Dormant project deletion** section, select **Delete dormant projects**.
|
||||
1. Configure the settings.
|
||||
- The warning email is sent to users who have the Owner and Maintainer role for the dormant project.
|
||||
- The email duration must be less than the **Delete project after** duration.
|
||||
1. Select **Save changes**.
|
||||
|
||||
Dormant projects that meet the criteria are scheduled for deletion and a warning email is sent. If the
|
||||
projects remain dormant, they are deleted after the specified duration. These projects are deleted even if
|
||||
[the project is archived](../user/project/working_with_projects.md#archive-a-project).
|
||||
|
||||
### Configuration example
|
||||
|
||||
#### Example 1
|
||||
|
||||
If you use these settings:
|
||||
|
||||
- **Delete dormant projects** enabled.
|
||||
- **Delete dormant projects that exceed** set to `50`.
|
||||
- **Delete project after** set to `12`.
|
||||
- **Send warning email** set to `6`.
|
||||
|
||||
If a project is less than 50 MB, the project is not considered dormant.
|
||||
|
||||
If a project is more than 50 MB and it is dormant for:
|
||||
|
||||
- More than 6 months: A deletion warning email is sent. This mail includes the date that the project will be deleted.
|
||||
- More than 12 months: The project is scheduled for deletion.
|
||||
|
||||
#### Example 2
|
||||
|
||||
If you use these settings:
|
||||
|
||||
- **Delete dormant projects** enabled.
|
||||
- **Delete dormant projects that exceed** set to `0`.
|
||||
- **Delete project after** set to `12`.
|
||||
- **Send warning email** set to `11`.
|
||||
|
||||
If a project exists that has already been dormant for more than 12 months when you configure these settings:
|
||||
|
||||
- A deletion warning email is sent immediately. This email includes the date that the project will be deleted.
|
||||
- The project is scheduled for deletion 1 month (12 months - 11 months) after warning email.
|
||||
|
||||
## Determine when a project was last active
|
||||
|
||||
You can view a project's activities and determine when the project was last active in the following ways:
|
||||
|
||||
- Go to the [activity page](../user/project/working_with_projects.md#view-project-activity) for the project and view
|
||||
the date of the latest event.
|
||||
- View the `last_activity_at` attribute for the project using the [Projects API](../api/projects.md).
|
||||
- List the visible events for the project using the [Events API](../api/events.md#list-all-visible-events-for-a-project).
|
||||
View the `created_at` attribute of the latest event.
|
||||
<!-- This redirect file can be deleted after <2025-08-20>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/development/documentation/redirects -->
|
||||
|
|
@ -58,7 +58,7 @@ is an internal user that cannot be accessed or modified by regular users and is
|
|||
projects.
|
||||
- [Automatically deactivating dormant users](moderate_users.md#automatically-deactivate-dormant-users).
|
||||
- [Automatically deleting unconfirmed users](moderate_users.md#automatically-delete-unconfirmed-users).
|
||||
- [Deleting inactive projects](inactive_project_deletion.md).
|
||||
- [Deleting dormant projects](dormant_project_deletion.md).
|
||||
- [Locking users](../security/unlock_user.md).
|
||||
|
||||
## GitLab Security Bot
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ Keep your GitLab instance up and running.
|
|||
- [Enable encrypted configuration](../encrypted_configuration.md)
|
||||
- [Rake tasks](../../raketasks/_index.md)
|
||||
- [Backup and restore](../backup_restore/_index.md)
|
||||
- [Inactive project deletion](../inactive_project_deletion.md)
|
||||
- [Dormant project deletion](../dormant_project_deletion.md)
|
||||
- [Move repositories](moving_repositories.md)
|
||||
- [Read-only state](../read_only_gitlab.md)
|
||||
- [Restart GitLab](../restart_gitlab.md)
|
||||
|
|
|
|||
|
|
@ -9263,9 +9263,10 @@ Input type: `ProjectCiCdSettingsUpdateInput`
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationprojectcicdsettingsupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationprojectcicdsettingsupdatefullpath"></a>`fullPath` | [`ID!`](#id) | Full Path of the project the settings belong to. |
|
||||
| <a id="mutationprojectcicdsettingsupdateinboundjobtokenscopeenabled"></a>`inboundJobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI/CD job tokens generated in other projects have restricted access to this project. |
|
||||
| <a id="mutationprojectcicdsettingsupdategrouprunnersenabled"></a>`groupRunnersEnabled` | [`Boolean`](#boolean) | Indicates whether group runners are enabled for the project. |
|
||||
| <a id="mutationprojectcicdsettingsupdateinboundjobtokenscopeenabled"></a>`inboundJobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates whether CI/CD job tokens generated in other projects have restricted access to this project. |
|
||||
| <a id="mutationprojectcicdsettingsupdatejobtokenscopeenabled"></a>`jobTokenScopeEnabled` {{< icon name="warning-solid" >}} | [`Boolean`](#boolean) | **Deprecated**: Outbound job token scope is being removed. This field can now only be set to false. Deprecated in GitLab 16.0. |
|
||||
| <a id="mutationprojectcicdsettingsupdatekeeplatestartifact"></a>`keepLatestArtifact` | [`Boolean`](#boolean) | Indicates if the latest artifact should be kept for the project. |
|
||||
| <a id="mutationprojectcicdsettingsupdatekeeplatestartifact"></a>`keepLatestArtifact` | [`Boolean`](#boolean) | Indicates whether the latest artifact should be kept for the project. |
|
||||
| <a id="mutationprojectcicdsettingsupdatemergepipelinesenabled"></a>`mergePipelinesEnabled` | [`Boolean`](#boolean) | Indicates if merged results pipelines are enabled for the project. |
|
||||
| <a id="mutationprojectcicdsettingsupdatemergetrainsenabled"></a>`mergeTrainsEnabled` | [`Boolean`](#boolean) | Indicates if merge trains are enabled for the project. |
|
||||
| <a id="mutationprojectcicdsettingsupdatemergetrainsskiptrainallowed"></a>`mergeTrainsSkipTrainAllowed` | [`Boolean`](#boolean) | Indicates whether an option is allowed to merge without refreshing the merge train. Ignored unless the `merge_trains_skip_train` feature flag is also enabled. |
|
||||
|
|
@ -37792,10 +37793,11 @@ four standard [pagination arguments](#pagination-arguments):
|
|||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="projectcicdsettinginboundjobtokenscopeenabled"></a>`inboundJobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI/CD job tokens generated in other projects have restricted access to this project. |
|
||||
| <a id="projectcicdsettingjobtokenscopeenabled"></a>`jobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates CI/CD job tokens generated in this project have restricted access to other projects. |
|
||||
| <a id="projectcicdsettingkeeplatestartifact"></a>`keepLatestArtifact` | [`Boolean`](#boolean) | Whether to keep the latest builds artifacts. |
|
||||
| <a id="projectcicdsettingmergepipelinesenabled"></a>`mergePipelinesEnabled` | [`Boolean`](#boolean) | Whether merged results pipelines are enabled. |
|
||||
| <a id="projectcicdsettinggrouprunnersenabled"></a>`groupRunnersEnabled` | [`Boolean`](#boolean) | Indicates whether group runners are enabled for the project. |
|
||||
| <a id="projectcicdsettinginboundjobtokenscopeenabled"></a>`inboundJobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates whether CI/CD job tokens generated in other projects have restricted access to this project. |
|
||||
| <a id="projectcicdsettingjobtokenscopeenabled"></a>`jobTokenScopeEnabled` | [`Boolean`](#boolean) | Indicates whether CI/CD job tokens generated in this project have restricted access to other projects. |
|
||||
| <a id="projectcicdsettingkeeplatestartifact"></a>`keepLatestArtifact` | [`Boolean`](#boolean) | Indicates whether the latest artifact should be kept for the project. |
|
||||
| <a id="projectcicdsettingmergepipelinesenabled"></a>`mergePipelinesEnabled` | [`Boolean`](#boolean) | Indicates whether merged results pipelines are enabled. |
|
||||
| <a id="projectcicdsettingmergetrainsenabled"></a>`mergeTrainsEnabled` | [`Boolean`](#boolean) | Whether merge trains are enabled. |
|
||||
| <a id="projectcicdsettingmergetrainsskiptrainallowed"></a>`mergeTrainsSkipTrainAllowed` | [`Boolean!`](#boolean) | Whether merge immediately is allowed for merge trains. |
|
||||
| <a id="projectcicdsettingpipelinevariablesminimumoverriderole"></a>`pipelineVariablesMinimumOverrideRole` | [`String!`](#string) | Minimum role required to set variables when creating a pipeline or running a job. |
|
||||
|
|
@ -49576,6 +49578,7 @@ see the associated mutation type above.
|
|||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="aidescriptioncomposerinputdescription"></a>`description` | [`String!`](#string) | Current description. |
|
||||
| <a id="aidescriptioncomposerinputpreviousresponse"></a>`previousResponse` | [`String`](#string) | Previously AI-generated description content used for context in iterative refinements or follow-up prompts. |
|
||||
| <a id="aidescriptioncomposerinputresourceid"></a>`resourceId` | [`AiModelID!`](#aimodelid) | Global ID of the resource to mutate. |
|
||||
| <a id="aidescriptioncomposerinputsourcebranch"></a>`sourceBranch` | [`String`](#string) | Source branch of the changes. |
|
||||
| <a id="aidescriptioncomposerinputsourceprojectid"></a>`sourceProjectId` | [`ID`](#id) | ID of the project where the changes are from. |
|
||||
|
|
|
|||
|
|
@ -796,16 +796,16 @@ to configure other related settings. These requirements are
|
|||
| `secret_push_protection_available` | boolean | no | Allow projects to enable secret push protection. This does not enable secret push protection. Ultimate only. |
|
||||
| `disable_invite_members` | boolean | no | Disable invite members functionality for group. |
|
||||
|
||||
### Inactive project settings
|
||||
### Dormant project settings
|
||||
|
||||
You can configure inactive projects deletion or turn it off.
|
||||
You can configure dormant projects deletion or turn it off.
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
|------------------------------------------|------------------|:------------------------------------:|-------------|
|
||||
| `delete_inactive_projects` | boolean | no | Enable [inactive project deletion](../administration/inactive_project_deletion.md). Default is `false`. [Became operational without feature flag](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96803) in GitLab 15.4. |
|
||||
| `inactive_projects_delete_after_months` | integer | no | If `delete_inactive_projects` is `true`, the time (in months) to wait before deleting inactive projects. Default is `2`. [Became operational](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0. |
|
||||
| `delete_inactive_projects` | boolean | no | Enable [dormant project deletion](../administration/dormant_project_deletion.md). Default is `false`. [Became operational without feature flag](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96803) in GitLab 15.4. |
|
||||
| `inactive_projects_delete_after_months` | integer | no | If `delete_inactive_projects` is `true`, the time (in months) to wait before deleting dormant projects. Default is `2`. [Became operational](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0. |
|
||||
| `inactive_projects_min_size_mb` | integer | no | If `delete_inactive_projects` is `true`, the minimum repository size for projects to be checked for inactivity. Default is `0`. [Became operational](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0. |
|
||||
| `inactive_projects_send_warning_email_after_months` | integer | no | If `delete_inactive_projects` is `true`, sets the time (in months) to wait before emailing maintainers that the project is scheduled be deleted because it is inactive. Default is `1`. [Became operational](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0. |
|
||||
| `inactive_projects_send_warning_email_after_months` | integer | no | If `delete_inactive_projects` is `true`, sets the time (in months) to wait before emailing Maintainers that the project is scheduled be deleted because it is dormant. Default is `1`. [Became operational](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0. |
|
||||
|
||||
### Housekeeping settings
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ To instrument an audit event, the following attributes should be provided:
|
|||
| Attribute | Type | Required? | Description |
|
||||
|:-------------|:------------------------------------|:----------|:------------------------------------------------------------------|
|
||||
| `name` | String | false | Action name to be audited. Represents the [type of the event](#event-type-definitions). Used for error tracking |
|
||||
| `author` | User | true | User who authors the change. Can be an [internal user](../../administration/internal_users.md). For example, [inactive project deletion](../../administration/inactive_project_deletion.md) audit events are authored by `GitLab-Admin-Bot`. |
|
||||
| `author` | User | true | User who authors the change. Can be an [internal user](../../administration/internal_users.md). For example, [dormant project deletion](../../administration/dormant_project_deletion.md) audit events are authored by `GitLab-Admin-Bot`. |
|
||||
| `scope` | User, Project, Group, or Instance | true | Scope which the audit event belongs to |
|
||||
| `target` | Object | true | Target object being audited |
|
||||
| `message` | String | true | Message describing the action ([not translated](#i18n-and-the-audit-event-message-attribute)) |
|
||||
|
|
|
|||
|
|
@ -140,7 +140,6 @@ Read more about [Gems development guidelines](gems.md).
|
|||
|
||||
When upgrading the Rails gem and its dependencies, you also should update the following:
|
||||
|
||||
- The [`activerecord_version` in the vendored `attr_encrypted` gemspec](https://gitlab.com/gitlab-org/gitlab/-/blob/master/vendor/gems/attr_encrypted/attr_encrypted.gemspec).
|
||||
- The [`Gemfile` in the `qa` directory](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/Gemfile).
|
||||
|
||||
You should also update npm packages that follow the current version of Rails:
|
||||
|
|
|
|||
|
|
@ -80,19 +80,22 @@ a minimum implementation of `AbstractReferenceFilter` should define:
|
|||
|
||||
### Add a new reference prefix and filter
|
||||
|
||||
For reference filters for new objects, use a prefix format following the pattern
|
||||
`^<object_type>#`, because:
|
||||
For reference filters for new objects, use a format following the pattern
|
||||
`[object_type:identifier]`, because:
|
||||
|
||||
1. Varied single-character prefixes are hard for users to track. Especially for
|
||||
lower-use object types, this can diminish value for the feature.
|
||||
1. Suitable single-character prefixes are limited.
|
||||
1. Suitable single-character prefixes are limited and no longer allowed for new references.
|
||||
1. Following a consistent pattern allows users to infer the existence of new features.
|
||||
|
||||
To add a reference prefix for a new object `apple`,which has both a name and ID,
|
||||
The [Extensible reference filters](https://gitlab.com/groups/gitlab-org/-/epics/7563)
|
||||
epic discusses the use of this format.
|
||||
|
||||
To add a reference prefix for a new object `apple`, which has both a name and ID,
|
||||
format the reference as:
|
||||
|
||||
- `^apple#123` for identification by ID.
|
||||
- `^apple#"Granny Smith"` for identification by name.
|
||||
- `[apple:123]` for identification by ID.
|
||||
- `[apple:"Granny Smith"]` for identification by name.
|
||||
|
||||
### Performance
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ We strive to run GitLab using the latest Rails releases to benefit from performa
|
|||
1. For major and minor version updates, run `bin/rails app:update` and check if any of the suggested changes should be applied.
|
||||
1. Update the `activesupport` version in `qa/Gemfile`.
|
||||
1. Run `bundle update --conservative activesupport` in the `qa` folder.
|
||||
1. Update the `activerecord_version` version in `vendor/gems/attr_encrypted/attr_encrypted.gemspec`.
|
||||
1. Run `bundle update --conservative activerecord` in the `vendor/gems/attr_encrypted` folder.
|
||||
1. Run `find gems -name Gemfile -exec bundle update --gemfile {} activesupport --patch --conservative \;` and replace `--patch` in the command with `--minor` or `--major` as needed.
|
||||
1. Resolve any Bundler conflicts.
|
||||
1. Ensure that `@rails/ujs` and `@rails/actioncable` npm packages match the new rails version in [`package.json`](https://gitlab.com/gitlab-org/gitlab/blob/master/package.json).
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ default keyboard shortcuts to avoid conflicts with your existing Visual Studio c
|
|||
| Command name | Default keyboard shortcut | Description |
|
||||
|---------------------------------------|---------------------------------------------|-------------|
|
||||
| `GitLab.ToggleCodeSuggestions` | None | Turn on or turn off Code Suggestions. |
|
||||
| `GitLab.OpenDuoChat` | None | Open Duo Chat. |
|
||||
| `GitLab.OpenDuoChat` | None | Open GitLab Duo Chat. |
|
||||
| `GitLab.GitLabDuoNextSuggestions` | <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>N</kbd> | Switch to the next code suggestion. |
|
||||
| `GitLab.GitLabDuoPreviousSuggestions` | None | Switch to the previous code suggestion. |
|
||||
| `GitLab.GitLabExplainTerminalWithDuo` | <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>E</kbd> | Explain selected text in the terminal. |
|
||||
|
|
|
|||
|
|
@ -93,12 +93,12 @@ For more information about simplifying this process, see
|
|||
[issue 577](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/577)
|
||||
in the `gitlab-vscode-extension` project.
|
||||
|
||||
## Known issue: Duo Chat fails to initialize in remote environments
|
||||
## Known issue: GitLab Duo Chat fails to initialize in remote environments
|
||||
|
||||
When using GitLab Duo Chat in remote development environments (such as browser-based VS Code or remote
|
||||
SSH connections), you might encounter initialization failures like:
|
||||
|
||||
- Blank or non-loading Duo Chat panel.
|
||||
- Blank or non-loading Chat panel.
|
||||
- Errors in logs: `The webview didn't initialize in 10000ms`.
|
||||
- Extension attempting to connect to inaccessible local URLs.
|
||||
|
||||
|
|
|
|||
|
|
@ -579,7 +579,7 @@ For details on saving and transporting Docker images as a file, see the Docker d
|
|||
```
|
||||
|
||||
1. If your local Docker container registry is running securely over `HTTPS`, but you're using a
|
||||
self-signed certificate, then you must set `CS_DOCKER_INSECURE: "true"` in the above
|
||||
self-signed certificate, then you must set `CS_DOCKER_INSECURE: "true"` in the
|
||||
`container_scanning` section of your `.gitlab-ci.yml`.
|
||||
|
||||
#### Automating container scanning vulnerability database updates with a pipeline
|
||||
|
|
@ -606,7 +606,7 @@ update-scanner-image:
|
|||
- docker push $TARGET_IMAGE
|
||||
```
|
||||
|
||||
The above template works for a GitLab Docker registry running on a local installation. However, if
|
||||
The previous template works for a GitLab Docker registry running on a local installation. However, if
|
||||
you're using a non-GitLab Docker registry, you must change the `$CI_REGISTRY` value and the
|
||||
`docker login` credentials to match your local registry's details.
|
||||
|
||||
|
|
@ -663,7 +663,7 @@ mirror trivy java db:
|
|||
The vulnerability database is not a regular Docker image, so it is not possible to pull it by using `docker pull`.
|
||||
The image shows an error if you go to it in the GitLab UI.
|
||||
|
||||
If the above container registry is `gitlab.example.com/trivy-java-db-mirror`, then the container scanning job should be configured in the following way. Do not add the tag `:1` at the end, it is added by `trivy`:
|
||||
If the container registry is `gitlab.example.com/trivy-java-db-mirror`, then the container scanning job should be configured in the following way. Do not add the tag `:1` at the end, it is added by `trivy`:
|
||||
|
||||
```yaml
|
||||
include:
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ It is recommended that a two cookie based approach is taken, as outlined in the
|
|||
of the RFC.
|
||||
|
||||
If the application is using a common framework, there is a chance that Anti-CSRF protection
|
||||
is built in but needs to be enabled. Consult your application framework documentation for
|
||||
is built-in but needs to be enabled. Consult your application framework documentation for
|
||||
details.
|
||||
|
||||
If neither of the above are applicable, it is **strongly** recommended that a third party library is used.
|
||||
If neither of these options are applicable, it is **strongly** recommended that a third party library is used.
|
||||
Implementing a secure Anti-CSRF system is a significant investment and difficult to do correctly.
|
||||
|
||||
## Details
|
||||
|
|
|
|||
|
|
@ -94,8 +94,8 @@ hosted within your network.
|
|||
|
||||
## Specific scanner instructions
|
||||
|
||||
Each individual scanner may be slightly different than the steps described
|
||||
above. You can find more information at each of the pages below:
|
||||
Each individual scanner may be slightly different than the steps previously described.
|
||||
You can find more information at each of the pages below:
|
||||
|
||||
- [Container scanning offline directions](../container_scanning/_index.md#running-container-scanning-in-an-offline-environment)
|
||||
- [SAST offline directions](../sast/_index.md#running-sast-in-an-offline-environment)
|
||||
|
|
@ -184,7 +184,7 @@ template:
|
|||
|
||||
### Alternate way without the official template
|
||||
|
||||
If it's not possible to follow the above method, the images can be transferred manually instead:
|
||||
If it's not possible to follow the previous method, the images can be transferred manually instead:
|
||||
|
||||
#### Example image packager script
|
||||
|
||||
|
|
@ -235,12 +235,12 @@ these steps:
|
|||
|
||||
1. Load the container images into the local registry. GitLab Secure leverages analyzer container
|
||||
images to do the various scans. These images must be available as part of running AutoDevOps.
|
||||
Before running AutoDevOps, follow the [above steps](#using-the-official-gitlab-template)
|
||||
Before running AutoDevOps, follow the steps in the [official GitLab template](#using-the-official-gitlab-template)
|
||||
to load those container images into the local container registry.
|
||||
|
||||
1. Set the CI/CD variable to ensure that AutoDevOps looks in the right place for those images.
|
||||
The AutoDevOps templates leverage the `SECURE_ANALYZERS_PREFIX` variable to identify the location
|
||||
of analyzer images. This variable is discussed above in [Using the secure bundle created](#using-the-secure-bundle-created).
|
||||
of analyzer images. For more information about this see [Using the secure bundle created](#using-the-secure-bundle-created).
|
||||
Ensure that you set this variable to the correct value for where you loaded the analyzer images.
|
||||
You could consider doing this with a project CI/CD variable or by [modifying](../../../topics/autodevops/customize.md#customize-gitlab-ciyml)
|
||||
the `.gitlab-ci.yml` file directly.
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ pipelines, each of which may contain a security scan.
|
|||
If a project uses [merge request pipelines](../../../ci/pipelines/merge_request_pipelines.md), you must set the CI/CD variable `AST_ENABLE_MR_PIPELINES` to `"true"` for the security scanning jobs to be present in the pipeline.
|
||||
For more information see [Use security scanning tools with merge request pipelines](../detect/roll_out_security_scanning.md#use-security-scanning-tools-with-merge-request-pipelines).
|
||||
|
||||
For projects where many pipelines have run on the latest commit (for example, inactive projects), policy evaluation considers a maximum of 1,000 pipelines from both the source and target branches of the merge request.
|
||||
For projects where many pipelines have run on the latest commit (for example, dormant projects), policy evaluation considers a maximum of 1,000 pipelines from both the source and target branches of the merge request.
|
||||
|
||||
For parent-child pipelines, policy evaluation considers a maximum of 1,000 child pipelines.
|
||||
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ If your scheduled pipelines are not running as expected, follow these troublesho
|
|||
- Ensure the configuration includes appropriate workflow rules for scheduled pipelines.
|
||||
1. **Verify policy configuration**:
|
||||
- Ensure the policy is enabled (`enabled: true`).
|
||||
- Verify taht the schedule configuration has the correct format and valid values.
|
||||
- Verify that the schedule configuration has the correct format and valid values.
|
||||
- Verify that the time zone setting is correct (if specified).
|
||||
1. **Review logs and activity**:
|
||||
- Check the security policy project's CI/CD pipeline logs for any errors.
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ To enable GitLab Advanced SAST by using the pipeline editor:
|
|||
- In GitLab 17.1, you must manually copy the contents of the GitLab Advanced SAST job into your CI/CD pipeline definition.
|
||||
- Set the CI/CD variable `GITLAB_ADVANCED_SAST_ENABLED` to `true`.
|
||||
|
||||
See the [minimal YAML example above](#edit-the-cicd-pipeline-definition-manually).
|
||||
See the [minimal YAML example](#edit-the-cicd-pipeline-definition-manually).
|
||||
1. Select the **Validate** tab, then select **Validate pipeline**.
|
||||
|
||||
The message **Simulation completed successfully** confirms the file is valid.
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ variables:
|
|||
SECRET_DETECTION_RULESET_GIT_REFERENCE: "gitlab.com/example-group/remote-ruleset-project"
|
||||
```
|
||||
|
||||
Pipeline secret detection assumes the configuration is defined in `.gitlab/secret-detection-ruleset.toml` file in the repository referenced by the CI variable where the remote ruleset is stored. If that file doesn't exist, make sure to [create one](#create-a-ruleset-configuration-file) and follow the steps to [override](#override-a-rule) or [disable](#disable-a-rule) a predefined rule as outlined above.
|
||||
Pipeline secret detection assumes the configuration is defined in `.gitlab/secret-detection-ruleset.toml` file in the repository referenced by the CI variable where the remote ruleset is stored. If that file doesn't exist, make sure to [create one](#create-a-ruleset-configuration-file) and follow the steps to [override](#override-a-rule) or [disable](#disable-a-rule) a predefined rule as previously outlined.
|
||||
|
||||
{{< alert type="note" >}}
|
||||
|
||||
|
|
@ -316,7 +316,7 @@ regex = '''Custom Raw Ruleset T[est]{3}'''
|
|||
"""
|
||||
```
|
||||
|
||||
The above example replaces the default ruleset with a rule that checks for the regex defined - `Custom Raw Ruleset T` with a suffix of 3 characters from either one of `e`, `s`, or `t` letters.
|
||||
The previous example replaces the default ruleset with a rule that checks for the regex defined - `Custom Raw Ruleset T` with a suffix of 3 characters from either one of `e`, `s`, or `t` letters.
|
||||
|
||||
For more information on the passthrough syntax to use, see [Schema](custom_rulesets_schema.md#schema).
|
||||
|
||||
|
|
@ -473,7 +473,7 @@ To do that with a `git` passthrough, add the following to `.gitlab/secret-detect
|
|||
|
||||
Pipeline secret detection assumes the remote ruleset configuration file is called `gitleaks.toml`, and is stored in `config` directory on the `main` branch of the referenced repository.
|
||||
|
||||
To extend the default ruleset, the `gitleaks.toml` file should use `[extend]` directive similar to the example above:
|
||||
To extend the default ruleset, the `gitleaks.toml` file should use `[extend]` directive similar to the previous example:
|
||||
|
||||
```toml
|
||||
# https://gitlab.com/user_group/central_repository_with_shared_ruleset/-/raw/main/config/gitleaks.toml
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ spotbugs-sast:
|
|||
- merge_requests
|
||||
```
|
||||
|
||||
To transition the above configuration to the new `rules` syntax, the override
|
||||
To transition the previous configuration to the new `rules` syntax, the override
|
||||
would be written as follows:
|
||||
|
||||
```yaml
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ can be one of the following:
|
|||
| [CVSS v3.1 Qualitative Severity Rating](https://www.first.org/cvss/v3.1/specification-document#Qualitative-Severity-Rating-Scale) | `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H` |
|
||||
|
||||
To provide consistent vulnerability severity level values, the GitLab vulnerability analyzers
|
||||
convert from the above values to a standardized GitLab vulnerability severity level, as outlined in
|
||||
convert from the previous values to a standardized GitLab vulnerability severity level, as outlined in
|
||||
the following tables:
|
||||
|
||||
## Container Scanning
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ You can leave it out if your compliance pipeline only ever runs in labeled proje
|
|||
|
||||
#### Compliance pipelines and custom pipeline configuration hosted externally
|
||||
|
||||
The example above assumes that all projects host their pipeline configuration in the same project.
|
||||
The previous example assumes that all projects host their pipeline configuration in the same project.
|
||||
If any projects use [configuration hosted externally](../../ci/pipelines/settings.md#specify-a-custom-cicd-configuration-file),
|
||||
the example configuration does not work. See [issue 393960](https://gitlab.com/gitlab-org/gitlab/-/issues/393960)
|
||||
for more details.
|
||||
|
|
@ -242,7 +242,7 @@ With projects that use externally hosted configuration, you can try the this wor
|
|||
#### Compliance pipelines in merge requests originating in project forks
|
||||
|
||||
When a merge request originates in a fork, the branch to be merged usually only exists in the fork.
|
||||
When creating such a merge request against a project with compliance pipelines, the above snippet fails with a
|
||||
When creating such a merge request against a project with compliance pipelines, the previous snippet fails with a
|
||||
`Project <project-name> reference <branch-name> does not exist!` error message.
|
||||
This error occurs because in the context of the target project, `$CI_COMMIT_REF_NAME` evaluates to a non-existing
|
||||
branch name.
|
||||
|
|
@ -270,7 +270,7 @@ include: # Execute individual project's configuration (if project contains .git
|
|||
|
||||
#### Compliance pipelines in projects with no configuration file
|
||||
|
||||
The [example configuration](#example-configuration) above assumes that all projects contain
|
||||
The [example configuration](#example-configuration) assumes that all projects contain
|
||||
a pipeline configuration file (`.gitlab-ci.yml` by default). However, in projects
|
||||
with no configuration file (and therefore no pipelines by default), the compliance pipeline
|
||||
fails because the file specified in `include:project` is required.
|
||||
|
|
@ -295,7 +295,7 @@ In this example, a configuration file is only included if it exists for the give
|
|||
in the project in `exists:project: $CI_PROJECT_PATH'`.
|
||||
|
||||
If `exists:project` is not specified in the compliance pipeline configuration, it searches for files in the project
|
||||
in which the `include` is defined. In compliance pipelines, the `include` from the example above
|
||||
in which the `include` is defined. In compliance pipelines, the `include` from the previous example
|
||||
is defined in the project hosting the compliance pipeline configuration file, not the project
|
||||
running the pipeline.
|
||||
|
||||
|
|
|
|||
|
|
@ -420,9 +420,9 @@ Projects are permanently deleted after a seven-day delay.
|
|||
|
||||
See how to [view and restore projects marked for deletion](../project/working_with_projects.md#restore-a-project).
|
||||
|
||||
### Inactive project deletion
|
||||
### Dormant project deletion
|
||||
|
||||
[Inactive project deletion](../../administration/inactive_project_deletion.md) is disabled on GitLab.com.
|
||||
[Dormant project deletion](../../administration/dormant_project_deletion.md) is disabled on GitLab.com.
|
||||
|
||||
## Package registry limits
|
||||
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ To display the deploy boards for a specific [environment](../../ci/environments/
|
|||
|
||||

|
||||
|
||||
Once all of the above are set up and the pipeline has run at least once,
|
||||
Once all of these previous instructions are set up and the pipeline has run at least once,
|
||||
go to the environments page under **Operate > Environments**.
|
||||
|
||||
Deploy boards are visible by default. You can explicitly select
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ module API
|
|||
|
||||
use AdminModeMiddleware
|
||||
use ResponseCoercerMiddleware
|
||||
use TrackAPIRequestFromRunnerMiddleware
|
||||
|
||||
helpers HelperMethods
|
||||
|
||||
|
|
@ -276,6 +277,63 @@ module API
|
|||
nil
|
||||
end
|
||||
end
|
||||
|
||||
class TrackAPIRequestFromRunnerMiddleware < ::Grape::Middleware::Base
|
||||
delegate :request, :endpoint_id, :current_user, :current_token, to: :context
|
||||
|
||||
def after
|
||||
return unless success? && current_project && current_token
|
||||
return unless Feature.enabled?(:track_api_request_from_runner, current_project)
|
||||
return unless request_from_runner?
|
||||
|
||||
::Gitlab::InternalEvents.track_event(
|
||||
'api_request_from_runner',
|
||||
project: current_project,
|
||||
additional_properties: {
|
||||
label: endpoint_id,
|
||||
property: token_type,
|
||||
cross_project_request: cross_project_request?.to_s
|
||||
}
|
||||
)
|
||||
|
||||
# Explicit nil is needed or the api call return value will be overwritten
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_project
|
||||
project = context.instance_variable_get(:@project)
|
||||
return unless project.is_a?(Project)
|
||||
|
||||
project
|
||||
end
|
||||
|
||||
def success?
|
||||
return unless @app_response
|
||||
|
||||
(200..299).cover?(@app_response[0])
|
||||
end
|
||||
|
||||
def request_from_runner?
|
||||
return unless request
|
||||
|
||||
::Ci::RunnerManager.ip_address_exists?(request.ip)
|
||||
end
|
||||
|
||||
def token_type
|
||||
return unless current_token
|
||||
|
||||
::Authn::AgnosticTokenIdentifier.name(current_token.to_s)
|
||||
end
|
||||
|
||||
def cross_project_request?
|
||||
return unless current_project
|
||||
return unless current_user&.from_ci_job_token?
|
||||
|
||||
!current_user.ci_job_token_scope.self_referential?(current_project)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ module API
|
|||
bad_request!('Found more than one set of credentials') if found.size > 1
|
||||
|
||||
location, raw = found.first
|
||||
set_current_token(raw)
|
||||
find_token_from_raw_credentials(strategies[location], raw)
|
||||
end
|
||||
|
||||
|
|
@ -59,6 +60,10 @@ module API
|
|||
|
||||
private
|
||||
|
||||
def set_current_token(raw)
|
||||
self.current_token = raw.password
|
||||
end
|
||||
|
||||
def find_token_from_raw_credentials(token_types, raw)
|
||||
token_types.each do |token_type|
|
||||
# Resolve a token from the raw credentials
|
||||
|
|
|
|||
|
|
@ -4,6 +4,15 @@ module API
|
|||
module Helpers
|
||||
module Packages
|
||||
module Nuget
|
||||
extend ::Gitlab::Utils::Override
|
||||
|
||||
override :render_api_error!
|
||||
def render_api_error!(message, status)
|
||||
header('X-NuGet-Warning', "GitLab: #{message}") if message.present?
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def find_packages
|
||||
packages = package_finder(params[:package_name]).execute
|
||||
|
||||
|
|
|
|||
|
|
@ -29,5 +29,13 @@ module Authn
|
|||
def self.token_type(plaintext)
|
||||
TOKEN_TYPES.find { |x| x.prefix?(plaintext) }
|
||||
end
|
||||
|
||||
def self.name(plaintext)
|
||||
type = token_type(plaintext)
|
||||
type = type.new(plaintext, nil).resource_name if type == ::Authn::Tokens::PersonalAccessToken
|
||||
return unless type
|
||||
|
||||
type.to_s.demodulize.underscore
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -32,6 +32,13 @@ module Authn
|
|||
service.execute
|
||||
end
|
||||
|
||||
def resource_name
|
||||
return revocable.class.name if revocable.user.human?
|
||||
return unless resource
|
||||
|
||||
"#{resource.class.name}AccessToken"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :current_user
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ module Gitlab
|
|||
DEPLOY_TOKEN_HEADER
|
||||
].freeze
|
||||
|
||||
attr_accessor :current_token
|
||||
|
||||
# Check the Rails session for valid authentication details
|
||||
def find_user_from_warden
|
||||
current_request.env['warden']&.authenticate if verified_request?
|
||||
|
|
@ -148,13 +150,13 @@ module Gitlab
|
|||
return unless route_authentication_setting[:deploy_token_allowed]
|
||||
return unless Gitlab::ExternalAuthorization.allow_deploy_tokens_and_deploy_keys?
|
||||
|
||||
token = current_request.env[DEPLOY_TOKEN_HEADER].presence || parsed_oauth_token
|
||||
self.current_token = current_request.env[DEPLOY_TOKEN_HEADER].presence || parsed_oauth_token
|
||||
|
||||
if has_basic_credentials?(current_request)
|
||||
_, token = user_name_and_password(current_request)
|
||||
_, self.current_token = user_name_and_password(current_request)
|
||||
end
|
||||
|
||||
deploy_token = DeployToken.active.find_by_token(token.to_s)
|
||||
deploy_token = DeployToken.active.find_by_token(current_token.to_s)
|
||||
@current_authenticated_deploy_token = deploy_token # rubocop:disable Gitlab/ModuleWithInstanceVariables
|
||||
|
||||
deploy_token
|
||||
|
|
@ -167,15 +169,15 @@ module Gitlab
|
|||
# agents, `Gitlab-Agentk-Api-Request`. Both must be supported until KAS has
|
||||
# been updated to use the new header, and then this first lookup can be removed.
|
||||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/406582.
|
||||
token, _ = if current_request.authorization.present?
|
||||
token_and_options(current_request)
|
||||
else
|
||||
current_request.headers[Gitlab::Kas::INTERNAL_API_AGENTK_REQUEST_HEADER]
|
||||
end
|
||||
self.current_token, _ = if current_request.authorization.present?
|
||||
token_and_options(current_request)
|
||||
else
|
||||
current_request.headers[Gitlab::Kas::INTERNAL_API_AGENTK_REQUEST_HEADER]
|
||||
end
|
||||
|
||||
return unless token.present?
|
||||
return unless current_token.present?
|
||||
|
||||
::Clusters::AgentToken.active.find_by_token(token.to_s)
|
||||
::Clusters::AgentToken.active.find_by_token(current_token.to_s)
|
||||
end
|
||||
|
||||
def find_runner_from_token
|
||||
|
|
@ -259,10 +261,10 @@ module Gitlab
|
|||
def find_user_from_job_bearer_token
|
||||
return unless route_authentication_setting[:job_token_allowed]
|
||||
|
||||
token = parsed_oauth_token
|
||||
return unless token
|
||||
self.current_token = parsed_oauth_token
|
||||
return unless current_token
|
||||
|
||||
job = ::Ci::AuthJobFinder.new(token: token).execute
|
||||
job = ::Ci::AuthJobFinder.new(token: current_token).execute
|
||||
return unless job
|
||||
|
||||
@current_authenticated_job = job # rubocop:disable Gitlab/ModuleWithInstanceVariables
|
||||
|
|
@ -300,24 +302,24 @@ module Gitlab
|
|||
end
|
||||
|
||||
def find_personal_access_token
|
||||
token = extract_personal_access_token
|
||||
return unless token
|
||||
self.current_token = extract_personal_access_token
|
||||
return unless current_token
|
||||
|
||||
# The runner sends the job token for PUT /api/jobs/:id in the PRIVATE-TOKEN header
|
||||
# and the token JSON parameter. Ignore this personal access token so
|
||||
# that the job token can be authenticated.
|
||||
return if api_request? && token.start_with?(::Ci::Build::TOKEN_PREFIX)
|
||||
return if api_request? && current_token.start_with?(::Ci::Build::TOKEN_PREFIX)
|
||||
|
||||
# Expiration, revocation and scopes are verified in `validate_access_token!`
|
||||
PersonalAccessToken.find_by_token(token.to_s) || raise(UnauthorizedError)
|
||||
PersonalAccessToken.find_by_token(current_token.to_s) || raise(UnauthorizedError)
|
||||
end
|
||||
|
||||
def find_oauth_access_token
|
||||
token = parsed_oauth_token
|
||||
return unless token
|
||||
self.current_token = parsed_oauth_token
|
||||
return unless current_token
|
||||
|
||||
# Expiration, revocation and scopes are verified in `validate_access_token!`
|
||||
oauth_token = OauthAccessToken.by_token(token)
|
||||
oauth_token = OauthAccessToken.by_token(current_token)
|
||||
raise UnauthorizedError unless oauth_token
|
||||
|
||||
oauth_token.revoke_previous_refresh_token!
|
||||
|
|
@ -333,8 +335,8 @@ module Gitlab
|
|||
return unless route_authentication_setting[:basic_auth_personal_access_token]
|
||||
return unless has_basic_credentials?(current_request)
|
||||
|
||||
_username, password = user_name_and_password(current_request)
|
||||
PersonalAccessToken.find_by_token(password.to_s)
|
||||
_username, self.current_token = user_name_and_password(current_request)
|
||||
PersonalAccessToken.find_by_token(current_token.to_s)
|
||||
end
|
||||
|
||||
def find_feed_token_user(token)
|
||||
|
|
@ -373,12 +375,12 @@ module Gitlab
|
|||
end
|
||||
|
||||
def find_user_from_job_token_query_params_or_header
|
||||
token = current_request.params[JOB_TOKEN_PARAM].presence ||
|
||||
self.current_token = current_request.params[JOB_TOKEN_PARAM].presence ||
|
||||
current_request.params[RUNNER_JOB_TOKEN_PARAM].presence ||
|
||||
current_request.env[JOB_TOKEN_HEADER].presence
|
||||
return unless token
|
||||
return unless current_token
|
||||
|
||||
job = find_valid_running_job_by_token!(token.to_s)
|
||||
job = find_valid_running_job_by_token!(current_token.to_s)
|
||||
@current_authenticated_job = job # rubocop:disable Gitlab/ModuleWithInstanceVariables
|
||||
|
||||
job.user
|
||||
|
|
@ -387,11 +389,11 @@ module Gitlab
|
|||
def find_user_from_job_token_basic_auth
|
||||
return unless has_basic_credentials?(current_request)
|
||||
|
||||
login, password = user_name_and_password(current_request)
|
||||
return unless login.present? && password.present?
|
||||
login, self.current_token = user_name_and_password(current_request)
|
||||
return unless login.present? && current_token.present?
|
||||
return unless ::Gitlab::Auth::CI_JOB_USER == login
|
||||
|
||||
job = find_valid_running_job_by_token!(password.to_s)
|
||||
job = find_valid_running_job_by_token!(current_token.to_s)
|
||||
@current_authenticated_job = job # rubocop:disable Gitlab/ModuleWithInstanceVariables
|
||||
|
||||
job.user
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ module Gitlab
|
|||
module Database
|
||||
MAIN_DATABASE_NAME = 'main'
|
||||
CI_DATABASE_NAME = 'ci'
|
||||
SEC_DATABASE_NAME = 'sec'
|
||||
DEFAULT_POOL_HEADROOM = 10
|
||||
|
||||
# This constant is used when renaming tables concurrently.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ ARG QA_BUILD_TARGET=ee
|
|||
ARG RUBY_VERSION=3.3.7
|
||||
ARG RUST_VERSION=1.73
|
||||
|
||||
FROM registry.gitlab.com/gitlab-org/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}-rust-${RUST_VERSION}:git-${GIT_VERSION}-lfs-${LFS_VERSION}-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-gcloud-${GCLOUD_VERSION}-kubectl-${KUBECTL_VERSION}-helm-${HELM_VERSION} AS foss
|
||||
FROM registry.gitlab.com/gitlab-org/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}:git-${GIT_VERSION}-lfs-${LFS_VERSION}-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-gcloud-${GCLOUD_VERSION}-kubectl-${KUBECTL_VERSION}-helm-${HELM_VERSION} AS foss
|
||||
LABEL maintainer="GitLab Quality Department <quality@gitlab.com>"
|
||||
|
||||
ENV DEBIAN_FRONTEND="noninteractive"
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ class ApplicationSettingsAnalysis
|
|||
DOC_API_SETTINGS_FILE_PATH = File.expand_path('../../doc/api/settings.md', __dir__)
|
||||
DOC_API_SETTINGS_TABLE_REGEX = Regexp.new(
|
||||
"## Available settings(?:.*?)(?:--\|\n)+?(?<rows>.+)" \
|
||||
"### Inactive project settings", Regexp::MULTILINE
|
||||
"### Dormant project settings", Regexp::MULTILINE
|
||||
)
|
||||
|
||||
DOC_PAGE_HEADERS = [
|
||||
|
|
|
|||
|
|
@ -253,7 +253,9 @@ RSpec.describe 'Database schema',
|
|||
subscription_user_add_on_assignment_versions: %w[item_id user_id purchase_id], # Managed by paper_trail gem, no need for FK on the historical data
|
||||
virtual_registries_packages_maven_cache_entries: %w[group_id], # We can't use a foreign key due to object storage references
|
||||
# system_defined_status_id reference to fixed items model which is stored in code
|
||||
work_item_current_statuses: %w[system_defined_status_id]
|
||||
work_item_current_statuses: %w[system_defined_status_id],
|
||||
# we can't use a foreign key reference because we want to preserve namespace_id for asynchronous deletion
|
||||
p_knowledge_graph_replicas: %w[namespace_id]
|
||||
}.with_indifferent_access.freeze
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -530,6 +530,6 @@ FactoryBot.define do
|
|||
trait :instance do
|
||||
project { nil }
|
||||
instance { true }
|
||||
organization { association(:organization, :default) }
|
||||
organization { association(:organization) }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -209,8 +209,8 @@
|
|||
- "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/143433\n" # Submit MR URL
|
||||
- "instrumentation" # Filters to the analytics instrumentation group
|
||||
- "\n" # Accept analytics:monitor:analytics_instrumentation
|
||||
- "se " # Select product category: service_ping
|
||||
- "tt \n" # Select additional product category: settings
|
||||
- "service_ " # Select product category: service_ping
|
||||
- "d \n" # Select additional product category: service_desk
|
||||
- "1\n" # Select: [free, premium, ultimate]
|
||||
- "y\n" # Create file
|
||||
- "4\n" # Exit
|
||||
|
|
@ -257,8 +257,8 @@
|
|||
- "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/143433\n" # Submit MR URL
|
||||
- "instrumentation" # Filters to the analytics instrumentation group
|
||||
- "\n" # Accept analytics:monitor:analytics_instrumentation
|
||||
- "se " # Select product category: service_ping
|
||||
- "tt \n" # Select additional product category: settings
|
||||
- "service_ " # Select product category: service_ping
|
||||
- "d \n" # Select additional product category: service_desk
|
||||
- "1\n" # Select: [free, premium, ultimate]
|
||||
- "y\n" # Create file
|
||||
- "1\n" # Create another event
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ identifiers:
|
|||
- user
|
||||
product_group: analytics_instrumentation
|
||||
product_categories:
|
||||
- service_desk
|
||||
- service_ping
|
||||
- settings
|
||||
milestone: '16.6'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/143433
|
||||
tiers:
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ describe('UserMenu component', () => {
|
|||
describe('User status item', () => {
|
||||
let item;
|
||||
|
||||
const setItem = async ({
|
||||
const setItem = ({
|
||||
can_update: canUpdate = false,
|
||||
busy = false,
|
||||
customized = false,
|
||||
|
|
@ -119,13 +119,6 @@ describe('UserMenu component', () => {
|
|||
{ status: { ...userMenuMockStatus, can_update: canUpdate, busy, customized } },
|
||||
stubs,
|
||||
);
|
||||
// Mock mounting the modal if we can update
|
||||
if (canUpdate) {
|
||||
expect(wrapper.vm.setStatusModalReady).toEqual(false);
|
||||
findSetStatusModal().vm.$emit('mounted');
|
||||
await nextTick();
|
||||
expect(wrapper.vm.setStatusModalReady).toEqual(true);
|
||||
}
|
||||
item = wrapper.findByTestId('status-item');
|
||||
};
|
||||
|
||||
|
|
@ -199,11 +192,14 @@ describe('UserMenu component', () => {
|
|||
${true} | ${false}
|
||||
${false} | ${true}
|
||||
`('and the status is busy or customized', ({ busy, customized }) => {
|
||||
it('should pass the current status to the modal', () => {
|
||||
it('should pass the current status to the modal', async () => {
|
||||
createWrapper({
|
||||
status: { ...userMenuMockStatus, can_update: true, busy, customized },
|
||||
});
|
||||
|
||||
wrapper.findByTestId('status-item').vm.$emit('action');
|
||||
await nextTick();
|
||||
|
||||
expect(findSetStatusModal().exists()).toBe(true);
|
||||
expect(findSetStatusModal().props()).toMatchObject({
|
||||
defaultEmoji: 'speech_balloon',
|
||||
|
|
@ -214,11 +210,14 @@ describe('UserMenu component', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('casts falsey values to empty strings', () => {
|
||||
it('casts falsey values to empty strings', async () => {
|
||||
createWrapper({
|
||||
status: { can_update: true, busy, customized },
|
||||
});
|
||||
|
||||
wrapper.findByTestId('status-item').vm.$emit('action');
|
||||
await nextTick();
|
||||
|
||||
expect(findSetStatusModal().exists()).toBe(true);
|
||||
expect(findSetStatusModal().props()).toMatchObject({
|
||||
defaultEmoji: 'speech_balloon',
|
||||
|
|
@ -231,11 +230,14 @@ describe('UserMenu component', () => {
|
|||
});
|
||||
|
||||
describe('and the status is neither busy nor customized', () => {
|
||||
it('should pass an empty status to the modal', () => {
|
||||
it('should pass an empty status to the modal', async () => {
|
||||
createWrapper({
|
||||
status: { ...userMenuMockStatus, can_update: true, busy: false, customized: false },
|
||||
});
|
||||
|
||||
wrapper.findByTestId('status-item').vm.$emit('action');
|
||||
await nextTick();
|
||||
|
||||
expect(findSetStatusModal().exists()).toBe(true);
|
||||
expect(findSetStatusModal().props()).toMatchObject({
|
||||
defaultEmoji: 'speech_balloon',
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ RSpec.describe Types::Ci::CiCdSettingType, feature_category: :continuous_integra
|
|||
|
||||
it 'exposes the expected fields' do
|
||||
expected_fields = %w[
|
||||
inbound_job_token_scope_enabled job_token_scope_enabled
|
||||
group_runners_enabled inbound_job_token_scope_enabled job_token_scope_enabled
|
||||
keep_latest_artifact merge_pipelines_enabled project
|
||||
push_repository_for_job_token_allowed
|
||||
pipeline_variables_minimum_override_role
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ RSpec.describe API::Helpers::Authentication do
|
|||
end
|
||||
end
|
||||
|
||||
cls.attr_writer :current_token
|
||||
|
||||
cls.define_method(:unauthorized!) { raise '401' }
|
||||
cls.define_method(:bad_request!) { |m| raise "400 - #{m}" }
|
||||
|
||||
|
|
@ -107,6 +109,12 @@ RSpec.describe API::Helpers::Authentication do
|
|||
it 'returns the token' do
|
||||
expect(subject).to be(token)
|
||||
end
|
||||
|
||||
it 'sets the current_token' do
|
||||
expect(object).to receive(:current_token=).with(token.password)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'an unauthorized request' do
|
||||
|
|
@ -127,10 +135,10 @@ RSpec.describe API::Helpers::Authentication do
|
|||
end
|
||||
|
||||
context 'with one set of located credentials' do
|
||||
let(:locators) { [double(extract: true)] }
|
||||
let(:locators) { [double(extract: token)] }
|
||||
let(:token) { double(password: 'secret') }
|
||||
|
||||
context 'when the credentials contain a valid token' do
|
||||
let(:token) { double }
|
||||
let(:resolvers) { [double(resolve: token)] }
|
||||
|
||||
it_behaves_like 'an authenticated request'
|
||||
|
|
@ -151,7 +159,7 @@ RSpec.describe API::Helpers::Authentication do
|
|||
end
|
||||
|
||||
context 'when a resolver raises UnauthorizedError' do
|
||||
let(:locators) { [double(extract: true)] }
|
||||
let(:locators) { [double(extract: double(password: nil))] }
|
||||
let(:resolvers) do
|
||||
r = double
|
||||
expect(r).to receive(:resolve).and_raise(Gitlab::Auth::UnauthorizedError)
|
||||
|
|
|
|||
|
|
@ -100,4 +100,40 @@ RSpec.describe Authn::AgnosticTokenIdentifier, feature_category: :system_access
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.name' do
|
||||
let_it_be(:project_bot) { create(:user, :project_bot) }
|
||||
let_it_be(:project) { create(:project, developers: project_bot) }
|
||||
let_it_be(:project_access_token) { create(:personal_access_token, user: project_bot).token }
|
||||
let_it_be(:group_bot) { create(:user, :project_bot) }
|
||||
let_it_be(:group) { create(:group, developers: group_bot) }
|
||||
let_it_be(:group_access_token) { create(:personal_access_token, user: group_bot).token }
|
||||
let_it_be(:nil_resource_access_token) { create(:personal_access_token, user: create(:user, :project_bot)).token }
|
||||
let_it_be(:ci_job_token) { create(:ci_build).token }
|
||||
|
||||
subject { described_class.name(plaintext) }
|
||||
|
||||
where(:plaintext, :name) do
|
||||
ref(:personal_access_token) | 'personal_access_token'
|
||||
ref(:project_access_token) | 'project_access_token'
|
||||
ref(:group_access_token) | 'group_access_token'
|
||||
ref(:nil_resource_access_token) | nil
|
||||
ref(:impersonation_token) | 'personal_access_token'
|
||||
ref(:feed_token) | 'feed_token'
|
||||
ref(:deploy_token) | 'deploy_token'
|
||||
ref(:oauth_application_secret) | 'oauth_application_secret'
|
||||
ref(:cluster_agent_token) | 'cluster_agent_token'
|
||||
ref(:runner_authentication_token) | 'runner_authentication_token'
|
||||
ref(:ci_trigger_token) | 'ci_trigger_token'
|
||||
ref(:feature_flags_client_token) | 'feature_flags_client_token'
|
||||
ref(:gitlab_session) | 'gitlab_session'
|
||||
ref(:incoming_email_token) | 'incoming_email_token'
|
||||
ref(:ci_job_token) | 'ci_job_token'
|
||||
'unsupported' | nil
|
||||
end
|
||||
|
||||
with_them do
|
||||
it { is_expected.to eq name }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -41,6 +41,12 @@ RSpec.describe Authn::Tokens::PersonalAccessToken, feature_category: :system_acc
|
|||
expect(token.revoke!(admin).status).to eq(:success)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#resource_name' do
|
||||
subject(:resource_name) { token.resource_name }
|
||||
|
||||
it { is_expected.to eq 'PersonalAccessToken' }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the token is a resource token' do
|
||||
|
|
@ -52,6 +58,12 @@ RSpec.describe Authn::Tokens::PersonalAccessToken, feature_category: :system_acc
|
|||
it 'successfully revokes the token', :enable_admin_mode do
|
||||
expect(token.revoke!(admin).status).to eq(:success)
|
||||
end
|
||||
|
||||
describe '#resource_name' do
|
||||
subject(:resource_name) { token.resource_name }
|
||||
|
||||
it { is_expected.to eq 'ProjectAccessToken' }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the token is a group access token' do
|
||||
|
|
@ -62,6 +74,22 @@ RSpec.describe Authn::Tokens::PersonalAccessToken, feature_category: :system_acc
|
|||
it 'successfully revokes the token', :enable_admin_mode do
|
||||
expect(token.revoke!(admin).status).to eq(:success)
|
||||
end
|
||||
|
||||
describe '#resource_name' do
|
||||
subject(:resource_name) { token.resource_name }
|
||||
|
||||
it { is_expected.to eq 'GroupAccessToken' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the token is from a bot without a resource' do
|
||||
let_it_be(:plaintext) { create(:personal_access_token, user: create(:user, :project_bot)).token }
|
||||
|
||||
describe '#resource_name' do
|
||||
subject(:resource_name) { token.resource_name }
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -201,6 +201,27 @@ RSpec.describe Ci::RunnerManager, feature_category: :fleet_visibility, type: :mo
|
|||
include_examples 'runner with status scope'
|
||||
end
|
||||
|
||||
describe '.ip_address_exists?' do
|
||||
let(:existing_ip_address) { '127.0.0.1' }
|
||||
let(:ip_address_to_find) { existing_ip_address }
|
||||
|
||||
subject { described_class.ip_address_exists?(ip_address_to_find) }
|
||||
|
||||
before do
|
||||
create(:ci_runner_machine, ip_address: existing_ip_address)
|
||||
end
|
||||
|
||||
context 'when the ip address exists' do
|
||||
it { is_expected.to be(true) }
|
||||
end
|
||||
|
||||
context 'when the ip address does not exist' do
|
||||
let(:ip_address_to_find) { '10.0.0.1' }
|
||||
|
||||
it { is_expected.to be(false) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.available_statuses' do
|
||||
subject { described_class.available_statuses }
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,260 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe API::APIGuard::TrackAPIRequestFromRunnerMiddleware, :request_store, feature_category: :permissions do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
RSpec.shared_examples 'event tracking' do
|
||||
let(:all_metrics) do
|
||||
[
|
||||
"redis_hll_counters.count_#{property}s_from_api_request_from_runner_weekly",
|
||||
"redis_hll_counters.count_#{property}s_from_api_request_from_runner_monthly"
|
||||
]
|
||||
end
|
||||
|
||||
it 'logs to Snowplow, Redis, and product analytics tooling',
|
||||
:clean_gitlab_redis_shared_state, :aggregate_failures do
|
||||
expected_attributes = {
|
||||
project: project,
|
||||
namespace: project.namespace,
|
||||
category: 'InternalEventTracking',
|
||||
feature_enabled_by_namespace_ids: nil,
|
||||
additional_properties: {
|
||||
**additional_properties,
|
||||
**{
|
||||
label: label,
|
||||
property: property
|
||||
}.compact
|
||||
}
|
||||
}
|
||||
|
||||
expect { subject }
|
||||
.to trigger_internal_events(event)
|
||||
.with(expected_attributes)
|
||||
.and increment_usage_metrics(*all_metrics)
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'event not tracked' do
|
||||
it 'does not record an internal event' do
|
||||
expect(Gitlab::InternalEvents).not_to receive(:track_event).with(event, any_args)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
it 'is loaded' do
|
||||
expect(API::API.middleware).to include([:use, described_class])
|
||||
end
|
||||
|
||||
describe '#after' do
|
||||
context 'when requesting an endpoint from a runner' do
|
||||
let_it_be(:token_user) { create(:user) }
|
||||
let_it_be(:token_user_project) { create(:project, developers: token_user) }
|
||||
let_it_be(:status) { 200 }
|
||||
|
||||
let_it_be(:personal_access_token) { create(:personal_access_token, user: token_user).token }
|
||||
let_it_be(:deploy_token) { create(:deploy_token).token }
|
||||
let_it_be(:ci_job_token) { create(:ci_build, :running, user: token_user, project: token_user_project).token }
|
||||
|
||||
let_it_be(:token) { personal_access_token }
|
||||
let_it_be(:token_param) { :private_token }
|
||||
let_it_be(:endpoint) { '/test' }
|
||||
let_it_be(:ip_address) { '10.0.0.1' }
|
||||
let!(:runner_machine) { create(:ci_runner_machine, ip_address: ip_address) }
|
||||
|
||||
let_it_be(:event) { 'api_request_from_runner' }
|
||||
let_it_be(:project) { token_user_project }
|
||||
let_it_be(:label) { "GET /api/:version#{endpoint}" }
|
||||
let_it_be(:property) { 'personal_access_token' }
|
||||
let_it_be(:additional_properties) { { cross_project_request: '' } }
|
||||
|
||||
let_it_be(:app) do
|
||||
Class.new(API::API).tap do |app|
|
||||
app.route_setting :authentication, job_token_allowed: true
|
||||
app.get endpoint do
|
||||
user_project
|
||||
status params[:status].to_i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
subject(:request) do
|
||||
get api(endpoint),
|
||||
params: { id: token_user_project&.id, token_param => token, status: status },
|
||||
headers: { REMOTE_ADDR: ip_address }
|
||||
end
|
||||
|
||||
it_behaves_like 'event tracking'
|
||||
|
||||
context 'when the endpoint return status is not in the 200 range' do
|
||||
let(:status) { 500 }
|
||||
|
||||
it_behaves_like 'event not tracked'
|
||||
end
|
||||
|
||||
context 'when there is no project available' do
|
||||
let(:token_user_project) { nil }
|
||||
|
||||
it_behaves_like 'event not tracked'
|
||||
end
|
||||
|
||||
context 'when there is no token available' do
|
||||
let(:token) { nil }
|
||||
|
||||
it_behaves_like 'event not tracked'
|
||||
end
|
||||
|
||||
context 'when the `track_api_request_from_runner` feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(track_api_request_from_runner: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'event not tracked'
|
||||
end
|
||||
|
||||
context 'when no runner machines exist with the remote ip address' do
|
||||
let(:runner_machine) { nil }
|
||||
|
||||
it_behaves_like 'event not tracked'
|
||||
end
|
||||
|
||||
context 'with different token types' do
|
||||
let_it_be(:project_bot) { create(:user, :project_bot) }
|
||||
let_it_be(:project_bot_project) { create(:project, developers: project_bot) }
|
||||
let_it_be(:project_access_token) { create(:personal_access_token, user: project_bot).token }
|
||||
let_it_be(:group_bot) { create(:user, :project_bot) }
|
||||
let_it_be(:group_bot_group) { create(:group, developers: group_bot) }
|
||||
let_it_be(:group_access_token) { create(:personal_access_token, user: group_bot).token }
|
||||
let_it_be(:oauth_application_secret) do
|
||||
create(:oauth_access_token, scopes: [:api]).tap do |oauth_access_token|
|
||||
oauth_access_token.update_column(:token, oauth_access_token.application.secret)
|
||||
end.application.plaintext_secret
|
||||
end
|
||||
|
||||
let_it_be(:app) do
|
||||
Class.new(API::API).tap do |app|
|
||||
app.route_setting :authentication, deploy_token_allowed: true
|
||||
app.get endpoint do
|
||||
@project = Project.find(params[:id])
|
||||
status find_user_from_sources ? 200 : 401
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
where(:token, :token_param, :token_header, :token_type) do
|
||||
ref(:personal_access_token) | :private_token | nil | 'personal_access_token'
|
||||
ref(:project_access_token) | :private_token | nil | 'project_access_token'
|
||||
ref(:group_access_token) | :private_token | nil | 'group_access_token'
|
||||
ref(:deploy_token) | nil | 'HTTP_DEPLOY_TOKEN' | 'deploy_token'
|
||||
ref(:oauth_application_secret) | :access_token | nil | 'oauth_application_secret'
|
||||
end
|
||||
|
||||
with_them do
|
||||
subject(:request) do
|
||||
get api(endpoint),
|
||||
params: { id: token_user_project.id, token_param => token },
|
||||
headers: { REMOTE_ADDR: ip_address, token_header => token }
|
||||
end
|
||||
|
||||
it_behaves_like 'event tracking' do
|
||||
let(:property) { token_type }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with cluster agent token' do
|
||||
let_it_be(:cluster_agent_token) { create(:cluster_agent_token, token_encrypted: nil).token }
|
||||
let_it_be(:app) do
|
||||
Class.new(API::API).tap do |app|
|
||||
app.helpers ::API::Helpers::Kubernetes::AgentHelpers
|
||||
app.route_setting :authentication, cluster_agent_token_allowed: true
|
||||
app.get endpoint do
|
||||
@project = Project.find(params[:id])
|
||||
status agent_token ? 200 : 401
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
subject(:request) do
|
||||
get api(endpoint),
|
||||
params: { id: token_user_project.id },
|
||||
headers: { REMOTE_ADDR: ip_address, 'Gitlab-Agentk-Api-Request' => cluster_agent_token }
|
||||
end
|
||||
|
||||
it_behaves_like 'event tracking' do
|
||||
let(:property) { 'cluster_agent_token' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with token from namespace inheritable' do
|
||||
let_it_be(:app) do
|
||||
Class.new(API::API).tap do |app|
|
||||
app.include ::API::Helpers::Authentication
|
||||
|
||||
app.authenticate_with do |accept|
|
||||
accept.token_types(:personal_access_token).sent_through(:http_private_token_header)
|
||||
accept.token_types(:deploy_token).sent_through(:http_deploy_token_header)
|
||||
accept.token_types(:job_token).sent_through(:http_job_token_header)
|
||||
end
|
||||
|
||||
app.get endpoint do
|
||||
@project = Project.find(params[:id])
|
||||
status find_user_from_sources ? 200 : 401
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
where(:token, :token_header, :token_type) do
|
||||
ref(:personal_access_token) | 'Private-Token' | 'personal_access_token'
|
||||
ref(:deploy_token) | 'Deploy-Token' | 'deploy_token'
|
||||
ref(:ci_job_token) | 'Job-Token' | 'ci_job_token'
|
||||
end
|
||||
|
||||
with_them do
|
||||
subject(:request) do
|
||||
get api(endpoint),
|
||||
params: { id: token_user_project.id },
|
||||
headers: { REMOTE_ADDR: ip_address, token_header => token }
|
||||
end
|
||||
|
||||
it_behaves_like 'event tracking' do
|
||||
let(:additional_properties) { { cross_project_request: token_type == 'ci_job_token' ? 'false' : '' } }
|
||||
let(:property) { token_type }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the request is authenticated with a job token' do
|
||||
let(:property) { 'ci_job_token' }
|
||||
let(:token_param) { :job_token }
|
||||
|
||||
context 'when a resource from the same project is requested' do
|
||||
let(:token) { ci_job_token }
|
||||
|
||||
it_behaves_like 'event tracking' do
|
||||
let(:additional_properties) { { cross_project_request: 'false' } }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a resource from another project is requested' do
|
||||
let(:build) { create(:ci_build, :running, user: token_user) }
|
||||
let(:token) { build.token }
|
||||
|
||||
before do
|
||||
create(:ci_job_token_project_scope_link,
|
||||
source_project: token_user_project,
|
||||
target_project: build.project,
|
||||
direction: :inbound
|
||||
)
|
||||
end
|
||||
|
||||
it_behaves_like 'event tracking' do
|
||||
let(:additional_properties) { { cross_project_request: 'true' } }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -44,15 +44,17 @@ RSpec.describe 'Getting Ci Cd Setting', feature_category: :continuous_integratio
|
|||
it_behaves_like 'a working graphql query'
|
||||
|
||||
it 'fetches the settings data' do
|
||||
expect(settings_data['mergePipelinesEnabled']).to eql project.ci_cd_settings.merge_pipelines_enabled?
|
||||
expect(settings_data['keepLatestArtifact']).to eql project.keep_latest_artifacts_available?
|
||||
expect(settings_data['jobTokenScopeEnabled']).to eql project.ci_cd_settings.job_token_scope_enabled?
|
||||
expect(settings_data['groupRunnersEnabled']).to eql(
|
||||
project.ci_cd_settings.group_runners_enabled?)
|
||||
expect(settings_data['inboundJobTokenScopeEnabled']).to eql(
|
||||
project.ci_cd_settings.inbound_job_token_scope_enabled?)
|
||||
expect(settings_data['pushRepositoryForJobTokenAllowed']).to eql(
|
||||
project.ci_cd_settings.push_repository_for_job_token_allowed?)
|
||||
expect(settings_data['jobTokenScopeEnabled']).to eql project.ci_cd_settings.job_token_scope_enabled?
|
||||
expect(settings_data['keepLatestArtifact']).to eql project.keep_latest_artifacts_available?
|
||||
expect(settings_data['mergePipelinesEnabled']).to eql project.ci_cd_settings.merge_pipelines_enabled?
|
||||
expect(settings_data['pipelineVariablesMinimumOverrideRole']).to eql(
|
||||
project.ci_pipeline_variables_minimum_override_role)
|
||||
expect(settings_data['pushRepositoryForJobTokenAllowed']).to eql(
|
||||
project.ci_cd_settings.push_repository_for_job_token_allowed?)
|
||||
|
||||
if Gitlab.ee?
|
||||
expect(settings_data['mergeTrainsEnabled']).to eql project.ci_cd_settings.merge_trains_enabled?
|
||||
|
|
|
|||
|
|
@ -12,6 +12,49 @@ RSpec.describe 'Query.project(fullPath).pipelines', feature_category: :continuou
|
|||
travel_to(Time.current) { example.run }
|
||||
end
|
||||
|
||||
describe 'TAGS and BRANCHES scope' do
|
||||
let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
|
||||
let_it_be(:branch_pipeline) { create(:ci_pipeline, project: project, ref: 'feature') }
|
||||
let_it_be(:tag_pipeline) { create(:ci_pipeline, project: project, ref: 'v1.0.0', tag: true) }
|
||||
|
||||
let(:scope) { '' }
|
||||
|
||||
let(:query) do
|
||||
%(
|
||||
query {
|
||||
project(fullPath: "#{project.full_path}") {
|
||||
pipelines(scope: #{scope}) {
|
||||
nodes {
|
||||
ref
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
context 'when the scope is branch pipelines' do
|
||||
let(:scope) { 'BRANCHES' }
|
||||
|
||||
it 'returns all branch pipelines' do
|
||||
post_graphql(query, current_user: user)
|
||||
|
||||
expect(graphql_data_at(:project, :pipelines, :nodes, :ref))
|
||||
.to contain_exactly(eq(pipeline.ref), eq(branch_pipeline.ref))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the scope is tag pipelines' do
|
||||
let(:scope) { 'TAGS' }
|
||||
|
||||
it 'returns all tag pipelines' do
|
||||
post_graphql(query, current_user: user)
|
||||
|
||||
expect(graphql_data_at(:project, :pipelines, :nodes, :ref)).to contain_exactly(eq(tag_pipeline.ref))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'sha' do
|
||||
let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ RSpec.describe 'ProjectCiCdSettingsUpdate', feature_category: :continuous_integr
|
|||
|
||||
let_it_be_with_reload(:project) do
|
||||
create(:project,
|
||||
group_runners_enabled: true,
|
||||
keep_latest_artifact: true,
|
||||
ci_outbound_job_token_scope_enabled: true,
|
||||
ci_inbound_job_token_scope_enabled: true
|
||||
|
|
@ -20,6 +21,7 @@ RSpec.describe 'ProjectCiCdSettingsUpdate', feature_category: :continuous_integr
|
|||
let(:variables) do
|
||||
{
|
||||
full_path: project.full_path,
|
||||
group_runners_enabled: false,
|
||||
keep_latest_artifact: false,
|
||||
job_token_scope_enabled: false,
|
||||
inbound_job_token_scope_enabled: false,
|
||||
|
|
@ -64,6 +66,7 @@ RSpec.describe 'ProjectCiCdSettingsUpdate', feature_category: :continuous_integr
|
|||
|
||||
expect(response).to have_gitlab_http_status(:success)
|
||||
expect(response_errors).to be_blank
|
||||
expect(project.group_runners_enabled).to be(false)
|
||||
expect(project.keep_latest_artifact).to be(false)
|
||||
expect(project.restrict_user_defined_variables?).to be(true)
|
||||
expect(project.ci_pipeline_variables_minimum_override_role).to eq('no_one_allowed')
|
||||
|
|
|
|||
|
|
@ -443,7 +443,6 @@ RSpec.shared_examples 'work items lock discussion' do
|
|||
it 'locks and unlocks discussion', :aggregate_failures do
|
||||
click_button _('More actions'), match: :first
|
||||
click_button 'Lock discussion'
|
||||
click_button _('More actions'), match: :first # click again to close the dropdown
|
||||
|
||||
expect(page).to have_text "Discussion is locked. Only members can comment."
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue