diff --git a/.gitlab/ci/cng/main.gitlab-ci.yml b/.gitlab/ci/cng/main.gitlab-ci.yml
index af33e3db637..214669fa4d9 100644
--- a/.gitlab/ci/cng/main.gitlab-ci.yml
+++ b/.gitlab/ci/cng/main.gitlab-ci.yml
@@ -1,8 +1,3 @@
-spec:
- inputs:
- cng_path:
- type: string
- default: 'build/CNG-mirror'
---
default:
interruptible: true
@@ -66,6 +61,6 @@ include:
TOP_UPSTREAM_MERGE_REQUEST_IID: "${TOP_UPSTREAM_MERGE_REQUEST_IID}"
TOP_UPSTREAM_SOURCE_SHA: "${TOP_UPSTREAM_SOURCE_SHA}"
trigger:
- project: '${CI_PROJECT_NAMESPACE}/$[[ inputs.cng_path ]]'
+ project: ${CI_PROJECT_NAMESPACE}/build/CNG-mirror
branch: $TRIGGER_BRANCH
strategy: depend
diff --git a/.gitlab/ci/release-environments.gitlab-ci.yml b/.gitlab/ci/release-environments.gitlab-ci.yml
index bcd1a3b047c..a6a0e268451 100644
--- a/.gitlab/ci/release-environments.gitlab-ci.yml
+++ b/.gitlab/ci/release-environments.gitlab-ci.yml
@@ -26,31 +26,3 @@ start-release-environments-pipeline:
- project: 'gitlab-org/gitlab'
ref: 'master'
file: '.gitlab/ci/release-environments/main.gitlab-ci.yml'
-
-start-release-environments-security-pipeline:
- allow_failure: true
- extends:
- - .release-environments:rules:start-release-environments-security-pipeline
- stage: release-environments
- # We do not want to have ALL global variables passed as trigger variables,
- # as they cannot be overridden. See this issue for more context:
- #
- # https://gitlab.com/gitlab-org/gitlab/-/issues/387183
- inherit:
- variables:
- - RUBY_VERSION_DEFAULT
- - RUBY_VERSION_NEXT
- - RUBY_VERSION
-
- # These variables are set in the pipeline schedules.
- # They need to be explicitly passed on to the child pipeline.
- # https://docs.gitlab.com/ee/ci/pipelines/multi_project_pipelines.html#pass-cicd-variables-to-a-downstream-pipeline-by-using-the-variables-keyword
- variables:
- # This is needed by `release-environments-build-cng-env` (`.gitlab/ci/release-environments/security.gitlab-ci.yml`).
- PARENT_PIPELINE_ID: $CI_PIPELINE_ID
- trigger:
- strategy: depend
- include:
- - project: 'gitlab-org/security/gitlab'
- ref: 'master'
- file: '.gitlab/ci/release-environments/security.gitlab-ci.yml'
diff --git a/.gitlab/ci/release-environments/main.gitlab-ci.yml b/.gitlab/ci/release-environments/main.gitlab-ci.yml
index a8a05965132..d1097e8326b 100644
--- a/.gitlab/ci/release-environments/main.gitlab-ci.yml
+++ b/.gitlab/ci/release-environments/main.gitlab-ci.yml
@@ -1,10 +1,8 @@
---
include:
- local: .gitlab/ci/cng/main.gitlab-ci.yml
- inputs:
- cng_path: 'build/CNG-mirror'
- project: 'gitlab-org/quality/pipeline-common'
- ref: '8.18.4'
+ ref: '8.18.3'
file: ci/base.gitlab-ci.yml
stages:
@@ -97,6 +95,7 @@ release-environments-qa:
GITLAB_INITIAL_ROOT_PASSWORD: "${RELEASE_ENVIRONMENTS_ROOT_PASSWORD}"
QA_PRAEFECT_REPOSITORY_STORAGE: "default"
SIGNUP_DISABLED: "true"
+ resource_group: release-environment-${CI_COMMIT_REF_SLUG}
release-environments-notification-failure:
stage: finish
diff --git a/.gitlab/ci/release-environments/security.gitlab-ci.yml b/.gitlab/ci/release-environments/security.gitlab-ci.yml
deleted file mode 100644
index 0b68cab6e4b..00000000000
--- a/.gitlab/ci/release-environments/security.gitlab-ci.yml
+++ /dev/null
@@ -1,143 +0,0 @@
-# Similar to .gitlab/ci/release-environments/main.gitlab-ci.yml, for release-environment pipelines in the security mirror.
-# Referenced in .gitlab/ci/release-environments.gitlab-ci.yml to differentiate from the canonical (main) version.
-# This file includes .gitlab/ci/cng/security.gitlab-ci.yml, instead of .gitlab/ci/cng/main.gitlab-ci.yml.
----
-include:
- - local: .gitlab/ci/cng/main.gitlab-ci.yml
- inputs:
- cng_path: 'charts/components/images'
- - project: 'gitlab-org/quality/pipeline-common'
- ref: '8.18.4'
- file: ci/base.gitlab-ci.yml
-
-stages:
- - prepare
- - start
- - deploy
- - qa
- - finish
-
-.inherit_variables:
- inherit:
- variables:
- - GIT_DEPTH
- - GIT_STRATEGY
-
-workflow:
- auto_cancel:
- on_new_commit: none
-
-variables:
- GIT_DEPTH: 20
- GIT_STRATEGY: fetch
-
-release-environments-build-cng-env:
- extends: .build-cng-env
-
-release-environments-build-cng:
- extends: .build-cng
- needs: ["release-environments-build-cng-env"]
- variables:
- IMAGE_TAG_EXT: "-${CI_COMMIT_SHORT_SHA}"
-
-release-environments-deploy-env:
- stage: prepare
- needs: ["release-environments-build-cng"]
- variables:
- DEPLOY_ENV: deploy.env
- script:
- - ./scripts/release_environment/construct-release-environments-versions.rb
- artifacts:
- reports:
- dotenv: $DEPLOY_ENV
- paths:
- - $DEPLOY_ENV
- expire_in: 7 days
- when: always
-
-release-environments-update-resource-group:
- stage: prepare
- script:
- # Make sure pipelines run in order
- # See https://docs.gitlab.com/ee/ci/resource_groups/index.html#change-the-process-mode
- - |
- curl --request PUT --data "process_mode=oldest_first" --header "PRIVATE-TOKEN:${ENVIRONMENT_API_TOKEN}" \
- "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/resource_groups/release-environment-${CI_COMMIT_REF_SLUG}"
-
-release-environments-notification-start:
- stage: start
- extends: .inherit_variables
- variables:
- RELEASE_ENVIRONMENT_NOTIFICATION_TYPE: "deploy"
- script:
- - ruby scripts/release_environment/notification.rb
- needs: ["release-environments-deploy-env"]
-
-release-environments-deploy:
- stage: deploy
- inherit:
- variables: false
- variables:
- VERSIONS: "${VERSIONS}"
- ENVIRONMENT: "${ENVIRONMENT}"
- trigger:
- project: gitlab-com/gl-infra/release-environments
- branch: main
- strategy: depend
- needs: ["release-environments-deploy-env"]
- resource_group: release-environment-${CI_COMMIT_REF_SLUG}
-
-release-environments-qa:
- stage: qa
- extends:
- - .qa-base
- timeout: 30m
- parallel: 5
- variables:
- QA_SCENARIO: "Test::Instance::Smoke"
- RELEASE: "${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_SHA}"
- GITLAB_QA_OPTS: --address "https://gitlab.${ENVIRONMENT}.release.gke.gitlab.net"
- GITLAB_INITIAL_ROOT_PASSWORD: "${RELEASE_ENVIRONMENTS_ROOT_PASSWORD}"
- QA_PRAEFECT_REPOSITORY_STORAGE: "default"
- SIGNUP_DISABLED: "true"
- before_script:
- - !reference [.qa-base, before_script]
- - echo "$CI_REGISTRY_PASSWORD" | docker login "$CI_REGISTRY" -u "$CI_REGISTRY_USER" --password-stdin
-
-release-environments-notification-failure:
- stage: finish
- extends: .inherit_variables
- variables:
- RELEASE_ENVIRONMENT_NOTIFICATION_TYPE: "deploy"
- script:
- - ruby scripts/release_environment/notification.rb
- needs:
- - job: release-environments-deploy
- artifacts: false
- - job: release-environments-deploy-env
- when: on_failure
-
-release-environments-notification-success:
- stage: finish
- extends: .inherit_variables
- variables:
- RELEASE_ENVIRONMENT_NOTIFICATION_TYPE: "deploy"
- script:
- - ruby scripts/release_environment/notification.rb
- needs:
- - job: release-environments-qa
- artifacts: false
- - job: release-environments-deploy-env
-
-release-environments-notification-qa-failure:
- stage: finish
- extends: .inherit_variables
- variables:
- RELEASE_ENVIRONMENT_NOTIFICATION_TYPE: "qa"
- script:
- - ruby scripts/release_environment/notification.rb
- needs:
- - job: release-environments-qa
- artifacts: false
- - job: release-environments-deploy-env
- when: on_failure
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 3b632fefe55..20fbbcd9ace 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -176,9 +176,6 @@
.if-dot-com-gitlab-org-ee-tag: &if-dot-com-gitlab-org-ee-tag
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/gitlab" && $CI_COMMIT_TAG =~ /^v?[\d]+\.[\d]+\.[\d]+[\d\w-]*-ee$/'
-.if-dot-com-gitlab-org-security-ee-tag: &if-dot-com-gitlab-org-security-ee-tag
- if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/security/gitlab" && $CI_COMMIT_TAG =~ /^v?[\d]+\.[\d]+\.[\d]+[\d\w-]*-ee$/'
-
.if-ruby-branch: &if-ruby-branch
if: '$CI_COMMIT_BRANCH =~ /^ruby\d+(_\d)*$/ || (($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_LABELS =~ /pipeline:run-in-ruby\d+(_\d)*/)'
@@ -954,7 +951,6 @@
ARCH: amd64,arm64
- !reference [".build-images:rules:build-qa-image-merge-requests", rules]
- !reference [".releases:rules:canonical-dot-com-gitlab-stable-branch-only-setup-test-env", rules]
- - !reference [".releases:rules:canonical-dot-com-security-gitlab-stable-branch-only-setup-test-env", rules]
.build-images:rules:build-qa-image-as-if-foss:
rules:
@@ -2535,13 +2531,6 @@
when: never
- if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/security/gitlab" && $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable-ee$/'
-.releases:rules:canonical-dot-com-security-gitlab-stable-branch-only-setup-test-env:
- rules:
- - if: '$CI_COMMIT_MESSAGE =~ /\[merge-train skip\]/'
- when: never
- - if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/security/gitlab" && $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable-ee$/'
- changes: *setup-test-env-patterns
-
#################
# Reports rules #
#################
@@ -3293,16 +3282,6 @@
when: always
- !reference [".releases:rules:canonical-dot-com-gitlab-stable-branch-only", rules]
-.release-environments:rules:start-release-environments-security-pipeline:
- rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-merge-request-labels-pipeline-expedite
- when: never
- - <<: *if-dot-com-gitlab-org-security-ee-tag
- when: always
- - !reference [".releases:rules:canonical-dot-com-security-gitlab-stable-branch-only", rules]
-
###################
# Benchmark rules #
###################
diff --git a/.rubocop_todo/gitlab/bounded_contexts.yml b/.rubocop_todo/gitlab/bounded_contexts.yml
index 31893ced36a..5c9ae67889a 100644
--- a/.rubocop_todo/gitlab/bounded_contexts.yml
+++ b/.rubocop_todo/gitlab/bounded_contexts.yml
@@ -2635,6 +2635,7 @@ Gitlab/BoundedContexts:
- 'ee/app/graphql/types/pending_group_member_type.rb'
- 'ee/app/graphql/types/permission_types/dast_site_profile.rb'
- 'ee/app/graphql/types/permission_types/epic.rb'
+ - 'ee/app/graphql/types/permission_types/merge_trains/car.rb'
- 'ee/app/graphql/types/permission_types/pipeline_security_report_finding.rb'
- 'ee/app/graphql/types/permission_types/requirement.rb'
- 'ee/app/graphql/types/permission_types/vulnerability.rb'
diff --git a/.rubocop_todo/gitlab/feature_flag_without_actor.yml b/.rubocop_todo/gitlab/feature_flag_without_actor.yml
index 203e78c2a9d..f0efce75312 100644
--- a/.rubocop_todo/gitlab/feature_flag_without_actor.yml
+++ b/.rubocop_todo/gitlab/feature_flag_without_actor.yml
@@ -159,7 +159,6 @@ Gitlab/FeatureFlagWithoutActor:
- 'ee/lib/ee/gitlab/auth/saml/config.rb'
- 'ee/lib/ee/gitlab/geo_git_access.rb'
- 'ee/lib/ee/gitlab/git_access.rb'
- - 'ee/lib/elastic/latest/merge_request_class_proxy.rb'
- 'ee/lib/gitlab/elastic/bulk_indexer.rb'
- 'ee/lib/gitlab/elastic/client.rb'
- 'ee/lib/gitlab/elastic/document_reference.rb'
diff --git a/app/assets/javascripts/ci/job_details/index.js b/app/assets/javascripts/ci/job_details/index.js
index 7e14572b717..a8c0803f763 100644
--- a/app/assets/javascripts/ci/job_details/index.js
+++ b/app/assets/javascripts/ci/job_details/index.js
@@ -34,6 +34,7 @@ export const initJobDetails = () => {
pipelineTestReportUrl,
logViewerPath,
duoFeaturesEnabled,
+ jobGid,
} = el.dataset;
const fullScreenAPIAvailable = document.fullscreenEnabled;
@@ -58,6 +59,7 @@ export const initJobDetails = () => {
aiRootCauseAnalysisAvailable: parseBoolean(aiRootCauseAnalysisAvailable),
duoFeaturesEnabled: parseBoolean(duoFeaturesEnabled),
pipelineTestReportUrl,
+ jobGid,
},
render(h) {
return h(JobApp, {
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index b856ab236da..6470a07dfc4 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -751,13 +751,6 @@ export default {
-
@@ -784,6 +777,13 @@ export default {
+
-
+
project_runners_path(build.project, anchor: 'js-runners-settings'),
"retry_outdated_job_docs_url" => help_page_path('ci/pipelines/settings', anchor: 'retry-outdated-jobs'),
"pipeline_test_report_url" => test_report_project_pipeline_path(project, build.pipeline),
- "log_viewer_path" => viewer_project_job_path(project, build)
+ "log_viewer_path" => viewer_project_job_path(project, build),
+ "job_gid" => build.to_gid.to_s
}
end
diff --git a/app/services/concerns/update_repository_storage_methods.rb b/app/services/concerns/update_repository_storage_methods.rb
index 952e80c7df7..f1b614bfa32 100644
--- a/app/services/concerns/update_repository_storage_methods.rb
+++ b/app/services/concerns/update_repository_storage_methods.rb
@@ -33,12 +33,12 @@ module UpdateRepositoryStorageMethods
mirror_repositories
end
- repository_storage_move.finish_replication!
-
repository_storage_move.transaction do
track_repository(destination_storage_name)
end
+ repository_storage_move.finish_replication!
+
remove_old_paths unless same_filesystem?
repository_storage_move.finish_cleanup!
diff --git a/app/services/members/activity_service.rb b/app/services/members/activity_service.rb
new file mode 100644
index 00000000000..d38b6db20c5
--- /dev/null
+++ b/app/services/members/activity_service.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Members
+ class ActivityService
+ include ExclusiveLeaseGuard
+
+ def initialize(user, namespace)
+ @user = user
+ @namespace = namespace&.root_ancestor
+ end
+
+ def execute
+ return ServiceResponse.error(message: 'Invalid params') unless namespace && user
+
+ try_obtain_lease do
+ @member = Member.in_hierarchy(namespace).with_user(user).first
+
+ break unless member
+ break if member.last_activity_on.today?
+
+ member.touch(:last_activity_on)
+ end
+
+ ServiceResponse.success(message: 'Member activity tracked')
+ end
+
+ private
+
+ attr_reader :user, :namespace, :member
+
+ def lease_timeout
+ (Time.current.end_of_day - Time.current).to_i
+ end
+
+ def lease_key
+ "members_activity_event:#{namespace.id}:#{user.id}"
+ end
+
+ # Used by ExclusiveLeaseGuard
+ # Overriding value as we only release the lease
+ # before the timeout if there was no member found, in order to prevent multiple
+ # updates in a short span of time but allow an update if the member is added later
+ def lease_release?
+ !member.present?
+ end
+ end
+end
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 9bb49437471..037f9e9d251 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -4098,6 +4098,15 @@
:weight: 1
:idempotent: false
:tags: []
+- :name: users_record_last_activity
+ :worker_name: Users::RecordLastActivityWorker
+ :feature_category: :seat_cost_management
+ :has_external_dependencies: false
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: users_track_namespace_visits
:worker_name: Users::TrackNamespaceVisitsWorker
:feature_category: :navigation
diff --git a/app/workers/users/record_last_activity_worker.rb b/app/workers/users/record_last_activity_worker.rb
new file mode 100644
index 00000000000..aa1e92ca2ea
--- /dev/null
+++ b/app/workers/users/record_last_activity_worker.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Users
+ class RecordLastActivityWorker
+ include Gitlab::EventStore::Subscriber
+
+ data_consistency :delayed
+ feature_category :seat_cost_management
+ urgency :low
+ idempotent!
+ deduplicate :until_executed
+
+ def handle_event(event)
+ user = User.find_by_id(event.data[:user_id])
+ namespace = Namespace.find_by_id(event.data[:namespace_id])
+
+ return unless user && namespace
+
+ Members::ActivityService.new(user, namespace).execute
+ end
+ end
+end
diff --git a/config/events/view_admin_application_settings_security_and_compliance_pageload.yml b/config/events/view_admin_application_settings_security_and_compliance_pageload.yml
new file mode 100644
index 00000000000..867136b0c1d
--- /dev/null
+++ b/config/events/view_admin_application_settings_security_and_compliance_pageload.yml
@@ -0,0 +1,16 @@
+---
+description: Tracks pageviews for the admin application settings security and compliance page
+internal_events: true
+action: view_admin_application_settings_security_and_compliance_pageload
+identifiers:
+- user
+product_group: personal_productivity
+milestone: '17.2'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/158225
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/feature_flags/beta/vulnerability_report_advanced_filtering.yml b/config/feature_flags/beta/vulnerability_report_advanced_filtering.yml
deleted file mode 100644
index 53b37ef8d39..00000000000
--- a/config/feature_flags/beta/vulnerability_report_advanced_filtering.yml
+++ /dev/null
@@ -1,9 +0,0 @@
----
-name: vulnerability_report_advanced_filtering
-feature_issue_url: https://gitlab.com/groups/gitlab-org/-/epics/3429
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/140984
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/437128
-milestone: '16.9'
-group: group::threat insights
-type: beta
-default_enabled: true
diff --git a/config/feature_flags/gitlab_com_derisk/track_member_activity.yml b/config/feature_flags/gitlab_com_derisk/track_member_activity.yml
new file mode 100644
index 00000000000..7be055696bd
--- /dev/null
+++ b/config/feature_flags/gitlab_com_derisk/track_member_activity.yml
@@ -0,0 +1,9 @@
+---
+name: track_member_activity
+feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/461338
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/155559
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/471259
+milestone: '17.2'
+group: group::utilization
+type: gitlab_com_derisk
+default_enabled: false
diff --git a/config/metrics/counts_28d/count_distinct_user_id_from_view_admin_application_settings_security_and_compliance_pageload_monthly.yml b/config/metrics/counts_28d/count_distinct_user_id_from_view_admin_application_settings_security_and_compliance_pageload_monthly.yml
new file mode 100644
index 00000000000..1375806ff4f
--- /dev/null
+++ b/config/metrics/counts_28d/count_distinct_user_id_from_view_admin_application_settings_security_and_compliance_pageload_monthly.yml
@@ -0,0 +1,22 @@
+---
+key_path: redis_hll_counters.count_distinct_user_id_from_view_admin_application_settings_security_and_compliance_pageload_monthly
+description: Monthly count of unique users who visited the admin application settings security and compliance page
+product_group: personal_productivity
+performance_indicator_type: []
+value_type: number
+status: active
+milestone: '17.2'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/158225
+time_frame: 28d
+data_source: internal_events
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+events:
+- name: view_admin_application_settings_security_and_compliance_pageload
+ unique: user.id
diff --git a/config/metrics/counts_28d/count_total_view_admin_application_settings_security_and_compliance_pageload_monthly.yml b/config/metrics/counts_28d/count_total_view_admin_application_settings_security_and_compliance_pageload_monthly.yml
new file mode 100644
index 00000000000..a9ed006ca05
--- /dev/null
+++ b/config/metrics/counts_28d/count_total_view_admin_application_settings_security_and_compliance_pageload_monthly.yml
@@ -0,0 +1,21 @@
+---
+key_path: counts.count_total_view_admin_application_settings_security_and_compliance_pageload_monthly
+description: Monthly count of total users who visisted the application settings security and complaince page
+product_group: personal_productivity
+performance_indicator_type: []
+value_type: number
+status: active
+milestone: '17.2'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/158225
+time_frame: 28d
+data_source: internal_events
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+events:
+- name: view_admin_application_settings_security_and_compliance_pageload
diff --git a/config/metrics/counts_7d/count_distinct_user_id_from_view_admin_application_settings_security_and_compliance_pageload_weekly.yml b/config/metrics/counts_7d/count_distinct_user_id_from_view_admin_application_settings_security_and_compliance_pageload_weekly.yml
new file mode 100644
index 00000000000..fb377873395
--- /dev/null
+++ b/config/metrics/counts_7d/count_distinct_user_id_from_view_admin_application_settings_security_and_compliance_pageload_weekly.yml
@@ -0,0 +1,22 @@
+---
+key_path: redis_hll_counters.count_distinct_user_id_from_view_admin_application_settings_security_and_compliance_pageload_weekly
+description: Weekly count of unique users who visited the admin application settings security and compliance page
+product_group: personal_productivity
+performance_indicator_type: []
+value_type: number
+status: active
+milestone: '17.2'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/158225
+time_frame: 7d
+data_source: internal_events
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+events:
+- name: view_admin_application_settings_security_and_compliance_pageload
+ unique: user.id
diff --git a/config/metrics/counts_7d/count_total_view_admin_application_settings_security_and_compliance_pageload_weekly.yml b/config/metrics/counts_7d/count_total_view_admin_application_settings_security_and_compliance_pageload_weekly.yml
new file mode 100644
index 00000000000..12560128a68
--- /dev/null
+++ b/config/metrics/counts_7d/count_total_view_admin_application_settings_security_and_compliance_pageload_weekly.yml
@@ -0,0 +1,21 @@
+---
+key_path: counts.count_total_view_admin_application_settings_security_and_compliance_pageload_weekly
+description: Weekly count of total users who visited the application settings security and compliance page
+product_group: personal_productivity
+performance_indicator_type: []
+value_type: number
+status: active
+milestone: '17.2'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/158225
+time_frame: 7d
+data_source: internal_events
+data_category: optional
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+events:
+- name: view_admin_application_settings_security_and_compliance_pageload
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index a1b5580af77..d19b0fdbedd 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -807,6 +807,8 @@
- 1
- - upload_checksum
- 1
+- - users_record_last_activity
+ - 1
- - users_track_namespace_visits
- 1
- - vulnerabilities_mark_dropped_as_resolved
diff --git a/db/migrate/20240304190228_add_fk_from_p_ci_build_names_to_p_ci_builds_on_partition_id_and_build_id.rb b/db/migrate/20240304190228_add_fk_from_p_ci_build_names_to_p_ci_builds_on_partition_id_and_build_id.rb
index 887cd9b7ce1..297976f8dee 100644
--- a/db/migrate/20240304190228_add_fk_from_p_ci_build_names_to_p_ci_builds_on_partition_id_and_build_id.rb
+++ b/db/migrate/20240304190228_add_fk_from_p_ci_build_names_to_p_ci_builds_on_partition_id_and_build_id.rb
@@ -8,7 +8,7 @@ class AddFkFromPCiBuildNamesToPCiBuildsOnPartitionIdAndBuildId < Gitlab::Databas
disable_ddl_transaction!
SOURCE_TABLE_NAME = :p_ci_build_names
- TARGET_TABLE_NAME = :ci_builds
+ TARGET_TABLE_NAME = :p_ci_builds
FK_NAME = :fk_rails_bc221a297a
def up
diff --git a/db/post_migrate/20240704070311_add_stage_event_hashes_organization_id_foreign_key.rb b/db/post_migrate/20240704070311_add_stage_event_hashes_organization_id_foreign_key.rb
new file mode 100644
index 00000000000..026fbcb37af
--- /dev/null
+++ b/db/post_migrate/20240704070311_add_stage_event_hashes_organization_id_foreign_key.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddStageEventHashesOrganizationIdForeignKey < Gitlab::Database::Migration[2.2]
+ disable_ddl_transaction!
+
+ milestone '17.2'
+
+ def up
+ add_concurrent_foreign_key :analytics_cycle_analytics_stage_event_hashes, :organizations, column: :organization_id,
+ on_delete: :cascade
+ end
+
+ def down
+ remove_foreign_key_if_exists :analytics_cycle_analytics_stage_event_hashes, column: :organization_id
+ end
+end
diff --git a/db/post_migrate/20240704111127_remove_default_value_from_vsa_stage_hashes_table.rb b/db/post_migrate/20240704111127_remove_default_value_from_vsa_stage_hashes_table.rb
new file mode 100644
index 00000000000..040f5e07a18
--- /dev/null
+++ b/db/post_migrate/20240704111127_remove_default_value_from_vsa_stage_hashes_table.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class RemoveDefaultValueFromVsaStageHashesTable < Gitlab::Database::Migration[2.2]
+ milestone '17.2'
+
+ def up
+ change_column_default :analytics_cycle_analytics_stage_event_hashes, :organization_id, nil
+ end
+
+ def down
+ change_column_default :analytics_cycle_analytics_stage_event_hashes, :organization_id, 1
+ end
+end
diff --git a/db/schema_migrations/20240704070311 b/db/schema_migrations/20240704070311
new file mode 100644
index 00000000000..25ff5e8a1ca
--- /dev/null
+++ b/db/schema_migrations/20240704070311
@@ -0,0 +1 @@
+b57add5352ed4723a1a0ed4a3e53829a6bd492fbfa903da35d0a02f5457efd84
\ No newline at end of file
diff --git a/db/schema_migrations/20240704111127 b/db/schema_migrations/20240704111127
new file mode 100644
index 00000000000..4868ee7a09d
--- /dev/null
+++ b/db/schema_migrations/20240704111127
@@ -0,0 +1 @@
+2c40583211aacf8dc10f3e56545faf9211fc394ef6314af38181398b5fef0fbc
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 4a15b117d80..1ffd0a84876 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -5018,7 +5018,7 @@ ALTER SEQUENCE analytics_cycle_analytics_group_value_streams_id_seq OWNED BY ana
CREATE TABLE analytics_cycle_analytics_stage_event_hashes (
id bigint NOT NULL,
hash_sha256 bytea,
- organization_id bigint DEFAULT 1 NOT NULL
+ organization_id bigint NOT NULL
);
CREATE SEQUENCE analytics_cycle_analytics_stage_event_hashes_id_seq
@@ -31819,6 +31819,9 @@ ALTER TABLE ONLY abuse_report_notes
ALTER TABLE ONLY vulnerability_issue_links
ADD CONSTRAINT fk_081e11030b FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY analytics_cycle_analytics_stage_event_hashes
+ ADD CONSTRAINT fk_0839874e4f FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY abuse_report_user_mentions
ADD CONSTRAINT fk_088018ecd8 FOREIGN KEY (abuse_report_id) REFERENCES abuse_reports(id) ON DELETE CASCADE;
diff --git a/doc/.vale/gitlab/InternalLinkFormat.yml b/doc/.vale/gitlab/InternalLinkFormat.yml
index be09a020846..fe8fae0558c 100644
--- a/doc/.vale/gitlab/InternalLinkFormat.yml
+++ b/doc/.vale/gitlab/InternalLinkFormat.yml
@@ -1,13 +1,13 @@
---
# Error: gitlab.InternalLinkFormat
#
-# Checks that internal link paths don't start with './', which is not needed.
+# Checks that internal link paths don't start with '/' or './'.
#
# For a list of all options, see https://vale.sh/docs/topics/styles/
extends: existence
-message: "Edit the link so it does not start with './'."
+message: "Edit the link so it does not start with '/' or './'."
link: https://docs.gitlab.com/ee/development/documentation/styleguide/index.html#links
level: error
scope: raw
raw:
- - '\[[^\]]+\]\(\.\/.*?\)'
+ - '\[[^\]]+\]\(\.?\/(?!uploads|documentation).*?\)'
diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md
index 41b0d16aa2d..2b5ac15a2c9 100644
--- a/doc/administration/geo/index.md
+++ b/doc/administration/geo/index.md
@@ -58,7 +58,7 @@ the difference between Geo and Gitaly Cluster, see [Comparison to Geo](../gitaly
## How it works
-This is a brief summary of how Geo works in your GitLab environment. For a more detailed information, see the [Geo Development page](/ee/development/geo.md).
+This is a brief summary of how Geo works in your GitLab environment. For a more detailed information, see the [Geo Development page](../../development/geo.md).
Your Geo instance can be used for cloning and fetching projects, in addition to reading any data. This makes working with large repositories over large distances much faster.
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index f35bbd02cae..e7fc2c9406f 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -92,6 +92,7 @@ The following API resources are available in the project context:
| [Project-level variables](project_level_variables.md) | `/projects/:id/variables` |
| [Projects](projects.md) including setting Webhooks | `/projects`, `/projects/:id/hooks` (also available for users) |
| [Protected branches](protected_branches.md) | `/projects/:id/protected_branches` |
+| [Protected container registry](project_container_registry_protection_rules.md) | `/projects/:id/registry/protection/rules` |
| [Protected environments](protected_environments.md) | `/projects/:id/protected_environments` |
| [Protected packages](project_packages_protection_rules.md) | `/projects/:id/protection/rules` |
| [Protected tags](protected_tags.md) | `/projects/:id/protected_tags` |
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index ca2872343dc..24979721c2c 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -6807,6 +6807,28 @@ Input type: `MergeRequestUpdateApprovalRuleInput`
| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| `mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request after mutation. |
+### `Mutation.mergeTrainsDeleteCar`
+
+DETAILS:
+**Introduced** in GitLab 17.2.
+**Status**: Experiment.
+
+Input type: `MergeTrainsDeleteCarInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `carId` | [`MergeTrainsCarID!`](#mergetrainscarid) | Global ID of the car. |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+
### `Mutation.mlModelCreate`
DETAILS:
@@ -17762,6 +17784,16 @@ Represents the total number of issues and their weights for a particular day.
| `scopeCount` | [`Int!`](#int) | Number of issues as of this day. |
| `scopeWeight` | [`Int!`](#int) | Total weight of issues as of this day. |
+### `CarPermissions`
+
+Check user's permission for the car.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `deleteCar` | [`Boolean!`](#boolean) | If `true`, the user can perform `delete_car` on this resource. |
+
### `CiApplicationSettings`
#### Fields
@@ -26051,10 +26083,11 @@ MergeTrainCar represents an attempt to merge a merge requestusing merge trains.
| `mergedAt` | [`Time`](#time) | Timestamp of when the car was merged. |
| `pipeline` | [`Pipeline`](#pipeline) | Pipeline of the car. |
| `status` | [`CarStatus!`](#carstatus) | Status of the car. |
-| `targetBranch` | [`Branch!`](#branch) | Target branch of the car's merge request. |
+| `targetBranch` | [`String!`](#string) | Target branch of the car's merge request. |
| `targetProject` | [`Project!`](#project) | Project the car's MR targets. |
| `updatedAt` | [`Time!`](#time) | Timestamp of when the car was last updated. |
| `user` | [`UserCore!`](#usercore) | Creator of the car (user who added the merge request to the train). |
+| `userPermissions` | [`CarPermissions!`](#carpermissions) | Permissions for the current user on the resource. |
### `Metadata`
diff --git a/doc/api/project_container_registry_protection_rules.md b/doc/api/project_container_registry_protection_rules.md
index 99a0e1fad65..cdbd8be23ee 100644
--- a/doc/api/project_container_registry_protection_rules.md
+++ b/doc/api/project_container_registry_protection_rules.md
@@ -71,3 +71,47 @@ Example response:
},
]
```
+
+## Create a container registry protection rule
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/457518) in GitLab 17.2.
+
+Create a container registry protection rule for a project.
+
+```plaintext
+POST /api/v4/projects/:id/registry/protection/rules
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+|-----------------------------------|----------------|----------|-------------|
+| `id` | integer/string | Yes | ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `repository_path_pattern` | string | Yes | Container repository path pattern protected by the protection rule. For example `flight/flight-*`. Wildcard character `*` allowed. |
+| `minimum_access_level_for_push` | string | No | Minimum GitLab access level to allow to push container images to the container registry. For example `maintainer`, `owner` or `admin`. Must be provided when `minimum_access_level_for_delete` is not set. |
+| `minimum_access_level_for_delete` | string | No | Minimum GitLab access level to allow to delete container images in the container registry. For example `maintainer`, `owner`, `admin`. Must be provided when `minimum_access_level_for_push` is not set. |
+
+If successful, returns [`201`](rest/index.md#status-codes) and the created container registry protection rule.
+
+Can return the following status codes:
+
+- `201 Created`: The container registry protection rule was created successfully.
+- `400 Bad Request`: The container registry protection rule is invalid.
+- `401 Unauthorized`: The access token is invalid.
+- `403 Forbidden`: The user does not have permission to create a container registry protection rule.
+- `404 Not Found`: The project was not found.
+- `422 Unprocessable Entity`: The container registry protection rule could not be created, for example, because the `repository_path_pattern` is already taken.
+
+Example request:
+
+```shell
+curl --request POST \
+ --header "PRIVATE-TOKEN: " \
+ --header "Content-Type: application/json" \
+ --url "https://gitlab.example.com/api/v4/projects/7/registry/protection/rules" \
+ --data '{
+ "repository_path_pattern": "flightjs/flight-needs-to-be-a-unique-path",
+ "minimum_access_level_for_push": "maintainer",
+ "minimum_access_level_for_delete": "maintainer"
+ }'
+```
diff --git a/doc/architecture/blueprints/_template.md b/doc/architecture/blueprints/_template.md
index bb1f0168e2c..f4fe0c51d03 100644
--- a/doc/architecture/blueprints/_template.md
+++ b/doc/architecture/blueprints/_template.md
@@ -33,13 +33,13 @@ Before you start:
To get started with a blueprint you can use this template to inform you about
what you may want to document in it at the beginning. This content will change
-/ evolve as you move forward with the proposal. You are not constrained by the
+/ evolve as you move forward with the proposal. You are not constrained by the
content in this template. If you have a good idea about what should be in your
blueprint, you can ignore the template, but if you don't know yet what should
be in it, this template might be handy.
- **Fill out this file as best you can.** At minimum, you should fill in the
- "Summary", and "Motivation" sections. These can be brief and may be a copy
+ "Summary", and "Motivation" sections. These can be brief and may be a copy
of issue or epic descriptions if the initiative is already on Product's
roadmap.
- **Create a MR for this blueprint.** Assign it to an Architecture Evolution
@@ -60,7 +60,7 @@ If there are new details that belong in the blueprint, edit the blueprint. Once
a feature has become "implemented", major changes should get new blueprints.
The canonical place for the latest set of instructions (and the likely source
-of this file) is [here](/doc/architecture/blueprints/_template.md).
+of this file) is [here](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/architecture/blueprints/_template.md).
Blueprint statuses you can use:
@@ -143,7 +143,7 @@ optional.