Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-07-08 18:29:54 +00:00
parent 31bafaf04d
commit ef6e077a33
64 changed files with 997 additions and 365 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -751,13 +751,6 @@ export default {
<compare-versions :diff-files-count-text="numTotalFiles" />
<template v-if="!isBatchLoadingError">
<hidden-files-warning
v-if="visibleWarning == $options.alerts.ALERT_OVERFLOW_HIDDEN"
:visible="numVisibleFiles"
:total="numTotalFiles"
:plain-diff-path="plainDiffPath"
:email-patch-path="emailPatchPath"
/>
<collapsed-files-warning v-if="visibleWarning == $options.alerts.ALERT_COLLAPSED_FILES" />
</template>
@ -784,6 +777,13 @@ export default {
<div v-if="pinnedFileStatus === 'loading'" class="loading">
<gl-loading-icon size="lg" />
</div>
<hidden-files-warning
v-if="visibleWarning == $options.alerts.ALERT_OVERFLOW_HIDDEN"
:visible="numVisibleFiles"
:total="numTotalFiles"
:plain-diff-path="plainDiffPath"
:email-patch-path="emailPatchPath"
/>
<dynamic-scroller
v-if="isVirtualScrollingEnabled"
:items="diffs"

View File

@ -37,12 +37,7 @@ export default {
</script>
<template>
<gl-alert
variant="warning"
class="gl-mx-5 gl-mb-4 gl-mt-3"
:title="$options.i18n.title"
:dismissible="false"
>
<gl-alert variant="warning" class="gl-mb-5" :title="$options.i18n.title" :dismissible="false">
<gl-sprintf
:message="
sprintf(

View File

@ -13,6 +13,7 @@ module RecordUserLastActivity
included do
before_action :set_user_last_activity
after_action :set_member_last_activity
end
def set_user_last_activity
@ -23,4 +24,16 @@ module RecordUserLastActivity
# TODO: add namespace & project - https://gitlab.com/gitlab-org/gitlab/-/issues/387952
Users::ActivityService.new(author: current_user).execute
end
def set_member_last_activity
context = @group || @project # rubocop:disable Gitlab/ModuleWithInstanceVariables -- This is a controller concern
return unless current_user && context && context.persisted?
Gitlab::EventStore.publish(
Users::ActivityEvent.new(data: {
user_id: current_user.id,
namespace_id: context.root_ancestor.id
})
)
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
module Users
class ActivityEvent < ::Gitlab::EventStore::Event
def schema
{
'type' => 'object',
'required' => %w[user_id namespace_id],
'properties' => {
'user_id' => { 'type' => 'integer' },
'namespace_id' => { 'type' => 'integer' }
}
}
end
end
end

View File

@ -14,7 +14,8 @@ module Ci
"runner_settings_url" => 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -807,6 +807,8 @@
- 1
- - upload_checksum
- 1
- - users_record_last_activity
- 1
- - users_track_namespace_visits
- 1
- - vulnerabilities_mark_dropped_as_resolved

View File

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

View File

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

View File

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

View File

@ -0,0 +1 @@
b57add5352ed4723a1a0ed4a3e53829a6bd492fbfa903da35d0a02f5457efd84

View File

@ -0,0 +1 @@
2c40583211aacf8dc10f3e56545faf9211fc394ef6314af38181398b5fef0fbc

View File

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

View File

@ -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).*?\)'

View File

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

View File

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

View File

@ -6807,6 +6807,28 @@ Input type: `MergeRequestUpdateApprovalRuleInput`
| <a id="mutationmergerequestupdateapprovalruleerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationmergerequestupdateapprovalrulemergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request after mutation. |
### `Mutation.mergeTrainsDeleteCar`
DETAILS:
**Introduced** in GitLab 17.2.
**Status**: Experiment.
Input type: `MergeTrainsDeleteCarInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationmergetrainsdeletecarcarid"></a>`carId` | [`MergeTrainsCarID!`](#mergetrainscarid) | Global ID of the car. |
| <a id="mutationmergetrainsdeletecarclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationmergetrainsdeletecarclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationmergetrainsdeletecarerrors"></a>`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.
| <a id="burnupchartdailytotalsscopecount"></a>`scopeCount` | [`Int!`](#int) | Number of issues as of this day. |
| <a id="burnupchartdailytotalsscopeweight"></a>`scopeWeight` | [`Int!`](#int) | Total weight of issues as of this day. |
### `CarPermissions`
Check user's permission for the car.
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="carpermissionsdeletecar"></a>`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.
| <a id="mergetraincarmergedat"></a>`mergedAt` | [`Time`](#time) | Timestamp of when the car was merged. |
| <a id="mergetraincarpipeline"></a>`pipeline` | [`Pipeline`](#pipeline) | Pipeline of the car. |
| <a id="mergetraincarstatus"></a>`status` | [`CarStatus!`](#carstatus) | Status of the car. |
| <a id="mergetraincartargetbranch"></a>`targetBranch` | [`Branch!`](#branch) | Target branch of the car's merge request. |
| <a id="mergetraincartargetbranch"></a>`targetBranch` | [`String!`](#string) | Target branch of the car's merge request. |
| <a id="mergetraincartargetproject"></a>`targetProject` | [`Project!`](#project) | Project the car's MR targets. |
| <a id="mergetraincarupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the car was last updated. |
| <a id="mergetraincaruser"></a>`user` | [`UserCore!`](#usercore) | Creator of the car (user who added the merge request to the train). |
| <a id="mergetraincaruserpermissions"></a>`userPermissions` | [`CarPermissions!`](#carpermissions) | Permissions for the current user on the resource. |
### `Metadata`

View File

@ -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: <your_access_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"
}'
```

View File

@ -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.
<!--
This is where we get down to the specifics of what the proposal actually is,
but keep it simple! This should have enough detail that reviewers can
but keep it simple! This should have enough detail that reviewers can
understand exactly what you're proposing, but should not include things like
API designs or implementation. The "Design Details" section below is for the
real nitty-gritty.

View File

@ -34,12 +34,12 @@ objects from the server is reduced, putting less load on the server's CPU.
When a user pushes changes, it usually kicks off a CI pipeline with
a bunch of jobs. When the CI runners all clone the repository from scratch,
if they use [`git clone`](/ee/ci/pipelines/settings.md#choose-the-default-git-strategy),
if they use [`git clone`](../../../ci/pipelines/settings.md#choose-the-default-git-strategy),
they all start negotiating with the server what they need to clone. This is
really CPU intensive for the server.
Some time ago we've introduced the
[pack-objects](/ee/administration/gitaly/configure_gitaly.md#pack-objects-cache),
[pack-objects](../../../administration/gitaly/configure_gitaly.md#pack-objects-cache),
but it has some pitfalls. When the tip of a branch changes, a new packfile needs
to be calculated, and the cache needs to be refreshed.

View File

@ -52,5 +52,5 @@ Snippets are scoped to an Organization because Gitaly is confined to a Cell.
## 4.2. Cons
- We will break [snippet discovery](/ee/user/snippets.md#discover-snippets).
- We will break [snippet discovery](../../../../user/snippets.md#discover-snippets).
- Snippet access may become subordinate to the visibility of the Organization.

View File

@ -46,7 +46,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:

View File

@ -115,7 +115,7 @@ Simplicity is the opposite of complexity. This uses a definition of simple and c
### Done
GitLab has an existing [definition of done](/ee/development/contributing/merge_request_workflow.md#definition-of-done) which is geared primarily toward identifying when an MR is ready to be merged.
GitLab has an existing [definition of done](../../../development/contributing/merge_request_workflow.md#definition-of-done) which is geared primarily toward identifying when an MR is ready to be merged.
In addition to the items in the GitLab definition of done, work on RRD should also adhere to the following requirements:

View File

@ -52,12 +52,21 @@ To help design the architecture, we need to understand how users, in their roles
operate and use the system. Here are significant use case scenarios that can help drive our
design decisions:
- As a user running a pipeline, I want a CI job to automatically fetch secrets specified in the `.gitlab-ci.yml` file.
- As a DevOps engineer, I want the deployment process to fetch secrets necessary for deployment directly from GitLab Secrets Manager.
- As a DevOps engineer, I want to manually retrieve the staging database password from the GitLab Secrets Manager.
- As a project maintainer, I want to destroy all secrets in the scope of the project, when the project is being deleted.
- As a GitLab instance admin, I want to quickly rotate all runner registration tokens.
- As a FIPS compliant customer, I want GitLab Secrets Manager to encrypt/decrypt secrets using an HSM solution.
1. As a Compliance Manager or Security Ops engineer, I want to use dynamic secrets to provide an additional layer of security for my system.
1. As a Compliance Manager or Security Ops engineer, I want to use automatic secret rotation to provide an additional layer of security for my system.
1. As a Compliance Manager or Security Ops engineer, I want to set secrets expiration policies to provide an additional layer of security for my system.
1. As a Developer, I want sensitive credentials to be fully encrypted so I am not accidentally leaking this information in my deliverables.
1. As a Developer, I want to use secrets to store sensitive credentials to avoid storing this information inside of my code.
1. As a GitLab Admin and as a GitLab Group Owner, I want to have the ability to disable secrets management feature altogether if my organization requires the use of a 3rd party tool.
1. As a Compliance Manager or Security Ops engineer, I need to have audit tools which will show me the status of the secrets, their usage so I can identify any suspicious behavior and ensure our security and compliance of our sensitive credentials.
1. As a Compliance Manager, I need to audit log of secrets usage and management to ensure my organization is following compliance policy.
1. As a DevOps Engineer, I want the deployment process to fetch secrets necessary for deployment directly from a secrets manager.
1. As a Customer of a regulated industry, I need a secrets manager with HSM support so I can meet FIPS requirements.
1. As a US Public Sector customer, I need a secrets manager that is FedRAMP certified to meet security requirements.
1. As a Customer with an air-gapped system, I need a secrets managers that can be installed on-prem and managed on-site to meet network requirements.
1. As a Secret Owner, I need to quickly update or rotate the secret in case there has been a vulnerability to ensure the security of my software supply chain.
1. As a Secret Owner, I need the ability to rollback change to a secret in the event of an accidental change.
1. As a Security Engineer, I want to ensure all secrets are properly deleted/destroyed if they are no longer needed.
#### Non-functional requirements

View File

@ -30,11 +30,11 @@ Base type for issue, requirement, test case, incident and task (this list is pla
A set of predefined types for different categories of work items. Currently, the available types are:
- [Incident](/ee/operations/incident_management/incidents.md)
- [Test case](/ee/ci/test_cases/index.md)
- [Requirement](/ee/user/project/requirements/index.md)
- [Task](/ee/user/tasks.md)
- [OKRs](/ee/user/okrs.md)
- [Incident](../../../operations/incident_management/incidents.md)
- [Test case](../../../ci/test_cases/index.md)
- [Requirement](../../../user/project/requirements/index.md)
- [Task](../../../user/tasks.md)
- [OKRs](../../../user/okrs.md)
Work is underway to convert existing objects to Work Item Types or add new ones:

View File

@ -173,7 +173,7 @@ The time limit to resolve all files is 30 seconds.
And optionally:
- [`include:inputs`](#includeinputs)
- [`include:rules`](includes.md#use-rules-with-include)
- [`include:rules`](#includerules)
**Additional details**:
@ -198,11 +198,6 @@ And optionally:
- From [GitLab 14.9 to GitLab 15.9](https://gitlab.com/gitlab-org/gitlab/-/issues/28987), you can have up to 100 includes.
The same file can be included multiple times in nested includes, but duplicates are ignored.
**Related topics**:
- [Use variables with `include`](includes.md#use-variables-with-include).
- [Use `rules` with `include`](includes.md#use-rules-with-include).
#### `include:component`
Use `include:component` to add a [CI/CD component](../components/index.md) to the
@ -394,6 +389,7 @@ include:
#### `include:inputs`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/391331) in GitLab 15.11 as a beta feature.
> - [Made generally available](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/134062) in GitLab 17.0.
Use `include:inputs` to set the values for input parameters when the included configuration
uses [`spec:inputs`](#specinputs) and is added to the pipeline.
@ -427,6 +423,45 @@ In this example:
- [Set input values when using `include`](inputs.md#set-input-values-when-using-include).
#### `include:rules`
You can use [`rules`](#rules) with `include` to conditionally include other configuration files.
**Keyword type**: Global keyword.
**Possible inputs**: These `rules` subkeys:
- [`rules:if`](#rulesif).
- [`rules:exists`](#rulesexists).
- [`rules:changes`](#ruleschanges).
Some [CI/CD variables are supported](includes.md#use-variables-with-include).
**Example of `include:rules`**:
```yaml
include:
- local: build_jobs.yml
rules:
- if: $INCLUDE_BUILDS == "true"
test-job:
stage: test
script: echo "This is a test job"
```
In this example, if the `INCLUDE_BUILDS` variable is:
- `true`, the `build_jobs.yml` configuration is included in the pipeline.
- Not `true` or does not exist, the `build_jobs.yml` configuration is not included in the pipeline.
**Related topics**:
- Examples of using `include` with:
- [`rules:if`](includes.md#include-with-rulesif).
- [`rules:changes`](includes.md#include-with-ruleschanges).
- [`rules:exists`](includes.md#include-with-rulesexists).
### `stages`
> - Support for nested array of strings [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/439451) in GitLab 16.9.

View File

@ -81,7 +81,7 @@ if you need help finding the correct person or labels:
[the product page](https://handbook.gitlab.com/handbook/product/categories/) or the
[feature page](https://handbook.gitlab.com/handbook/product/categories/features/).
- If you still can't find the engineering manager, use
[Git blame](/ee/user/project/repository/files/git_blame.md) to identify a maintainer
[Git blame](../../user/project/repository/files/git_blame.md) to identify a maintainer
involved in the project.
1. Create an upgrade issue for each dependency in the

View File

@ -327,20 +327,53 @@ To replace the token:
### Identify personal, project, and group access tokens expiring on a certain date
Use these scripts in self-managed instances to identify tokens affected by
[incident 18003](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/18003).
Run the script from your terminal window in either:
Access tokens that have no expiration date are valid indefinitely, which is a
security risk if the access token is divulged.
To manage this risk, when you upgrade to GitLab 16.0 and later, any
[personal](../user/profile/personal_access_tokens.md),
[project](../user/project/settings/project_access_tokens.md), or
[group](../user/group/settings/group_access_tokens.md) access
token that does not have an expiration date automatically has an expiration
date set at one year from the date of upgrade.
If you are not aware of when your tokens expire because the dates have changed,
you might have unexpected authentication failures when trying to sign into GitLab
on that date.
To manage this issue, you can run scripts in self-managed instances to identify
tokens that either:
- Expire on a specific date.
- Have no expiration date.
You run these scripts from your terminal window in either:
- A [Rails console session](../administration/operations/rails_console.md#starting-a-rails-console-session).
- Using the [Rails Runner](../administration/operations/rails_console.md#using-the-rails-runner).
These scripts return results in this format:
The specific scripts you run differ depending on if you have upgraded to GitLab 16.0
and later, or not:
- If you have not yet upgraded to GitLab 16.0 or later, [identify tokens that do not have an expiration date](#find-tokens-with-no-expiration-date).
- If you have upgraded to GitLab 16.0 or later, use scripts to identify any of
the following:
- [Tokens expiring on a specific date](#find-all-tokens-expiring-on-a-specific-date).
- [Tokens expiring in a specific month](#find-tokens-expiring-in-a-given-month).
- [Dates when many tokens expire](#identify-dates-when-many-tokens-expire).
After you have identified tokens affected by this issue, you can run a final script
to [extend the lifetime of specific tokens](#extend-token-lifetime) if needed.
These scripts return results in the following format:
```plaintext
Expired Group Access Token in Group ID 25, Token ID: 8, Name: Example Token, Scopes: ["read_api", "create_runner"], Last used:
Expired Project Access Token in Project ID 2, Token ID: 9, Name: Test Token, Scopes: ["api", "read_registry", "write_registry"], Last used: 2022-02-11 13:22:14 UTC
```
For more information on this, see [incident 18003](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/18003).
#### Find all tokens expiring on a specific date
This script finds tokens that expire on a specific date.

View File

@ -53,7 +53,7 @@ Only applications that are built as Spring Boot [executable JARs](https://docs.s
The easiest way to run API Discovery is through a pipeline job based on our CI template.
When running in this method, you provide a container image that has the required dependencies installed (such as an appropriate Java runtime). See [Image Requirements](#image-requirements) for more information.
1. A container image that meets the [image requirements](#image-requirements) is uploaded to a container registry. If the container registry requires authentication see [this help section](/ee/ci/docker/using_docker_images.md#access-an-image-from-a-private-container-registry).
1. A container image that meets the [image requirements](#image-requirements) is uploaded to a container registry. If the container registry requires authentication see [this help section](../../../../ci/docker/using_docker_images.md#access-an-image-from-a-private-container-registry).
1. In a job in the `build` stage, build your application and configure the resulting Spring Boot executable JAR as a job artifact.
1. Include the API Discovery template in your `.gitlab-ci.yml` file.

View File

@ -194,14 +194,14 @@ this:
1. Optional. If you did not save your SCIM token when you first configured SCIM, [generate a new token](scim_setup.md#configure-gitlab). If you generate a new SCIM token, you **must** update the token in your identity provider's SCIM configuration, or SCIM will stop working.
1. Locate your SCIM token.
1. Use the API to [get a single SCIM provisioned user](/ee/development/internal_api/index.md#get-a-single-scim-provisioned-user).
1. Use the API to [get a single SCIM provisioned user](../../../development/internal_api/index.md#get-a-single-scim-provisioned-user).
1. Check the returned information to make sure that:
- The user's identifier (`id`) and email match what your identity provider is sending.
- `active` is set to `false`.
If any of this information does not match, [contact GitLab Support](https://support.gitlab.com/).
1. Use the API to [update the SCIM provisioned user's `active` value to `true`](/ee/development/internal_api/index.md#update-a-single-scim-provisioned-user).
1. Use the API to [update the SCIM provisioned user's `active` value to `true`](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user).
1. If the update returns a status code `204`, have the user attempt to sign in
using SAML SSO.

View File

@ -1853,10 +1853,10 @@ This example links to `<wiki_root>/documentation`:
[Link to Related Page](/documentation)
```
This example links to `<wiki_root>/miscellaneous.md`:
This example links to `<wiki_root>/documentation.md`:
```markdown
[Link to Related Page](/miscellaneous.md)
[Link to Related Page](/documentation.md)
```
### diagrams.net editor

View File

@ -13,26 +13,62 @@ module API
authorize! :admin_container_image, user_project
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get list of container registry protection rules for a project' do
success Entities::Projects::ContainerRegistry::Protection::Rule
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[projects]
is_array true
hidden true
end
end
params do
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
get ':id/registry/protection/rules' do
present user_project.container_registry_protection_rules,
with: Entities::Projects::ContainerRegistry::Protection::Rule
resource ':id/registry/protection/rules' do
desc 'Get list of container registry protection rules for a project' do
success Entities::Projects::ContainerRegistry::Protection::Rule
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[projects]
is_array true
hidden true
end
get do
present user_project.container_registry_protection_rules,
with: Entities::Projects::ContainerRegistry::Protection::Rule
end
desc 'Create a container protection rule for a project' do
success Entities::Projects::ContainerRegistry::Protection::Rule
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' },
{ code: 422, message: 'Unprocessable Entity' }
]
tags %w[projects]
hidden true
end
params do
requires :repository_path_pattern, type: String,
desc: 'Container repository path pattern protected by the protection rule.
For example `flight/flight-*`. Wildcard character `*` allowed.'
optional :minimum_access_level_for_push, type: String,
values: ContainerRegistry::Protection::Rule.minimum_access_level_for_pushes.keys,
desc: 'Minimum GitLab access level to allow to push container images to the container registry.
For example maintainer, owner or admin.'
optional :minimum_access_level_for_delete, type: String,
values: ContainerRegistry::Protection::Rule.minimum_access_level_for_deletes.keys,
desc: 'Minimum GitLab access level to allow to delete container images in the container registry.
For example maintainer, owner or admin.'
at_least_one_of :minimum_access_level_for_push, :minimum_access_level_for_delete
end
post do
response = ::ContainerRegistry::Protection::CreateRuleService.new(user_project,
current_user, declared_params).execute
render_api_error!({ error: response.message }, :unprocessable_entity) if response.error?
present response[:container_registry_protection_rule],
with: Entities::Projects::ContainerRegistry::Protection::Rule
end
end
end
end

View File

@ -50,6 +50,12 @@ module Gitlab
to: ::Packages::PackageCreatedEvent,
if: ->(event) { ::Ml::ExperimentTracking::AssociateMlCandidateToPackageWorker.handles_event?(event) }
store.subscribe ::Ci::InitializePipelinesIidSequenceWorker, to: ::Projects::ProjectCreatedEvent
store.subscribe ::Users::RecordLastActivityWorker,
to: ::Users::ActivityEvent,
if: ->(event) do
actor = ::Namespace.actor_from_id(event.data[:namespace_id])
Feature.enabled?(:track_member_activity, actor)
end
end
private_class_method :configure!
end

View File

@ -2168,6 +2168,9 @@ msgstr ""
msgid "AI|An error occurred while explaining the code."
msgstr ""
msgid "AI|An error occurred while troubleshooting the failed job."
msgstr ""
msgid "AI|Apply AI-generated description"
msgstr ""
@ -13412,6 +13415,9 @@ msgstr ""
msgid "ComplianceFrameworks| Project frameworks export"
msgstr ""
msgid "ComplianceFrameworks|\"%{name}\" is a reserved word and cannot be used as a compliance framework name."
msgstr ""
msgid "ComplianceFrameworks|%{count} linked policy."
msgid_plural "ComplianceFrameworks|%{count} linked policies."
msgstr[0] ""

View File

@ -34,6 +34,7 @@ tmp/*
!tmp/sockets
db/fixtures/
!db/fixtures/development/01__default_organization.rb
!db/fixtures/development/01_admin.rb
!db/fixtures/development/02_application_settings.rb
!db/fixtures/development/25_api_personal_access_token.rb

View File

@ -21,7 +21,7 @@ class ReleaseEnvironmentsModel
def generate_json
output_json = {}
COMPONENTS.each do |component|
output_json[component.to_s] = image_tag.to_s
output_json[component.to_s] = "#{environment}-#{ENV['CI_COMMIT_SHORT_SHA']}"
end
JSON.generate(output_json)
end
@ -39,35 +39,17 @@ class ReleaseEnvironmentsModel
end
def environment
@environment ||= environment_base + (security_project? ? "-security" : "")
end
def image_tag
@image_tag ||= "#{environment_base}-#{ENV['CI_COMMIT_SHORT_SHA']}"
end
private
# This is to generate the environment name without "-security". It is used by the image tag
def environment_base
@environment_base ||= if release_tag_match
"#{release_tag_match[1]}-#{release_tag_match[2]}-stable"
else
ENV['CI_COMMIT_REF_SLUG'].delete_suffix('-ee')
end
end
def release_tag_match
@release_tag_match ||= ENV['CI_COMMIT_REF_SLUG'].match(/^v?([\d]+)\.([\d]+)\.[\d]+[\d\w-]*-ee$/)
end
def security_project?
ENV['CI_PROJECT_PATH'] == "gitlab-org/security/gitlab"
match = ENV['CI_COMMIT_REF_SLUG'].match(/^v?([\d]+)\.([\d]+)\.[\d]+[\d\w-]*-ee$/)
@environment ||= if match
"#{match[1]}-#{match[2]}-stable"
else
ENV['CI_COMMIT_REF_SLUG'].sub("-ee", "")
end
end
end
# Outputs in `dotenv` format the ENVIRONMENT and VERSIONS to pass to release environments e.g.
# ENVIRONMENT=15-10-stable(-security)
# ENVIRONMENT=15-10-stable
# VERSIONS={"gitaly":"15-10-stable-c7c5131c","registry":"15-10-stable-c7c5131c","kas":"15-10-stable-c7c5131c", ...
if $PROGRAM_NAME == __FILE__
model = ReleaseEnvironmentsModel.new

View File

@ -136,7 +136,7 @@ module Trigger
def normalize_stable_branch_name(branch_name)
if ENV['CI_PROJECT_NAMESPACE'] == 'gitlab-cn'
branch_name.delete_suffix('-jh')
elsif ["gitlab-org", "gitlab-org/security"].include?(ENV['CI_PROJECT_NAMESPACE'])
elsif ENV['CI_PROJECT_NAMESPACE'] == 'gitlab-org'
branch_name.delete_suffix('-ee')
end
end

View File

@ -0,0 +1,119 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe RecordUserLastActivity, feature_category: :seat_cost_management do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:user) { create(:user) }
let(:controller_class) do
# rubocop:disable Rails/ApplicationController -- This is a test controller
Class.new(ActionController::Base) do
include RecordUserLastActivity
def initialize(user, group, project)
@current_user = user
@group = group
@project = project
end
def request
@request ||= Struct.new(:get?).new(true)
end
end
# rubocop:enable Rails/ApplicationController
end
subject(:controller) { controller_class.new(user, group, project) }
shared_examples 'does not update the user activity timestamp' do
it 'does not update the user last activity' do
expect { controller.set_user_last_activity }.not_to change { user.reload.last_activity_on }
end
end
describe '#set_user_last_activity' do
context 'when the request is a GET request' do
it 'updates the user last activity' do
expect { controller.set_user_last_activity }.to change { user.reload.last_activity_on }
end
end
context 'when the request is not a GET request' do
before do
allow(controller.request).to receive(:get?).and_return(false)
end
it_behaves_like 'does not update the user activity timestamp'
end
context 'when the database is read-only' do
before do
allow(Gitlab::Database).to receive(:read_only?).and_return(true)
end
it_behaves_like 'does not update the user activity timestamp'
end
context 'when there is no current user' do
before do
allow(controller).to receive(:current_user).and_return(nil)
end
it_behaves_like 'does not update the user activity timestamp'
end
end
describe '#set_member_last_activity' do
shared_examples 'does not update publish an activity event' do
it do
expect { controller.set_member_last_activity }.not_to publish_event(Users::ActivityEvent)
end
end
shared_examples 'publishes an activity event' do
it 'publishes a Users::ActivityEvent' do
expect { controller.set_member_last_activity }
.to publish_event(Users::ActivityEvent)
.with({
user_id: user.id,
namespace_id: context.root_ancestor.id
})
end
end
context 'when the request is a GET request' do
context 'when a group is available' do
let(:context) { group }
it_behaves_like 'publishes an activity event'
end
context 'when no group is available' do
let(:group) { nil }
context 'when a project is available' do
let(:context) { project }
it_behaves_like 'publishes an activity event'
end
end
context 'when there is no group or project' do
let(:group) { nil }
let(:project) { nil }
it_behaves_like 'does not update publish an activity event'
end
end
context 'when the request is not a GET request' do
before do
allow(controller.request).to receive(:get?).and_return(false)
end
it_behaves_like 'does not update publish an activity event'
end
end
end

View File

@ -516,6 +516,9 @@ describe('diffs/components/app', () => {
state.diffs.plainDiffPath = 'plain diff path';
state.diffs.emailPatchPath = 'email patch path';
state.diffs.size = 1;
state.diffs.treeEntries = {
111: { type: 'blob', fileHash: '111', path: '111.js' },
};
},
});

View File

@ -29,7 +29,8 @@ RSpec.describe Ci::JobsHelper, feature_category: :continuous_integration do
"runner_settings_url" => "/#{project.full_path}/-/runners#js-runners-settings",
"retry_outdated_job_docs_url" => "/help/ci/pipelines/settings#retry-outdated-jobs",
"pipeline_test_report_url" => "/#{project.full_path}/-/pipelines/#{job.pipeline.id}/test_report",
"log_viewer_path" => "/#{project.full_path}/-/jobs/#{job.id}/viewer"
"log_viewer_path" => "/#{project.full_path}/-/jobs/#{job.id}/viewer",
"job_gid" => "gid://gitlab/Ci::Build/#{job.id}"
})
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe API::ProjectContainerRegistryProtectionRules, feature_category: :container_registry do
RSpec.describe API::ProjectContainerRegistryProtectionRules, :aggregate_failures, feature_category: :container_registry do
include ExclusiveLeaseHelpers
let_it_be(:project) { create(:project, :private) }
@ -15,7 +15,13 @@ RSpec.describe API::ProjectContainerRegistryProtectionRules, feature_category: :
let_it_be(:invalid_token) { 'invalid-token123' }
let_it_be(:headers_with_invalid_token) { { Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER => invalid_token } }
shared_examples 'rejecting project container protection rules request' do
let(:params) do
{ repository_path_pattern: "#{container_registry_protection_rule.repository_path_pattern}-unique",
minimum_access_level_for_push: container_registry_protection_rule.minimum_access_level_for_push,
minimum_access_level_for_delete: container_registry_protection_rule.minimum_access_level_for_delete }
end
shared_examples 'rejecting project container protection rules request when not enough permissions' do
using RSpec::Parameterized::TableSyntax
where(:user_role, :status) do
@ -34,14 +40,34 @@ RSpec.describe API::ProjectContainerRegistryProtectionRules, feature_category: :
end
end
shared_examples 'rejecting container registry protection rules request when enough permissions' do
context 'when feature flag is disabled' do
before do
stub_feature_flags(container_registry_protected_containers: false)
end
it_behaves_like 'returning response status', :not_found
end
context 'when the project id is invalid' do
let(:url) { "/projects/invalid/registry/protection/rules" }
it_behaves_like 'returning response status', :not_found
end
context 'when the project id does not exist' do
let(:url) { "/projects/#{non_existing_record_id}/registry/protection/rules" }
it_behaves_like 'returning response status', :not_found
end
end
describe 'GET /projects/:id/registry/protection/rules' do
let(:url) { "/projects/#{project.id}/registry/protection/rules" }
subject(:get_container_registry_rules) { get(api(url, api_user)) }
context 'when not enough permissions' do
it_behaves_like 'rejecting project container protection rules request'
end
it_behaves_like 'rejecting project container protection rules request when not enough permissions'
context 'for maintainer' do
let(:api_user) { maintainer }
@ -74,25 +100,7 @@ RSpec.describe API::ProjectContainerRegistryProtectionRules, feature_category: :
)
end
context 'when the project id is invalid' do
let(:url) { '/projects/invalid/registry/protection/rules' }
it_behaves_like 'returning response status', :not_found
end
context 'when the project id does not exist' do
let(:url) { "/projects/#{non_existing_record_id}/registry/protection/rules" }
it_behaves_like 'returning response status', :not_found
end
context 'when container_registry_protected_containers is disabled' do
before do
stub_feature_flags(container_registry_protected_containers: false)
end
it_behaves_like 'returning response status', :not_found
end
it_behaves_like 'rejecting container registry protection rules request when enough permissions'
end
context 'with invalid token' do
@ -101,4 +109,96 @@ RSpec.describe API::ProjectContainerRegistryProtectionRules, feature_category: :
it_behaves_like 'returning response status', :unauthorized
end
end
describe 'POST /projects/:id/registry/protection/rules' do
let(:url) { "/projects/#{project.id}/registry/protection/rules" }
subject(:post_container_registry_rule) { post(api(url, api_user), params: params) }
it_behaves_like 'rejecting project container protection rules request when not enough permissions'
context 'for maintainer' do
let(:api_user) { maintainer }
it 'creates a container registry protection rule' do
expect { post_container_registry_rule }.to change { ContainerRegistry::Protection::Rule.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
end
context 'with empty minimum_access_level_for_push' do
before do
params[:minimum_access_level_for_push] = nil
end
it 'creates a container registry protection rule' do
expect { post_container_registry_rule }.to change { ContainerRegistry::Protection::Rule.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
end
end
context 'with invalid minimum_access_level_for_delete' do
before do
params[:minimum_access_level_for_delete] = "not in enum"
end
it 'does not create a container registry protection rule' do
expect { post_container_registry_rule }.to not_change(ContainerRegistry::Protection::Rule, :count)
expect(response).to have_gitlab_http_status(:bad_request)
end
end
context 'with empty minimum_access_level_for_delete' do
before do
params[:minimum_access_level_for_delete] = nil
end
it 'creates a container registry protection rule' do
expect { post_container_registry_rule }.to change { ContainerRegistry::Protection::Rule.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
end
end
context 'with invalid minimum_access_level_for_push' do
before do
params[:minimum_access_level_for_push] = "not in enum"
end
it 'does not create a container registry protection rule' do
expect { post_container_registry_rule }.to not_change(ContainerRegistry::Protection::Rule, :count)
expect(response).to have_gitlab_http_status(:bad_request)
end
end
context 'with already existing repository_path_pattern' do
before do
params[:repository_path_pattern] = container_registry_protection_rule.repository_path_pattern
end
it 'does not create a container registry protection rule' do
expect { post_container_registry_rule }.to not_change(ContainerRegistry::Protection::Rule, :count)
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
end
context 'with neither minimum_access_level_for_push nor minimum_access_level_for_delete' do
before do
params[:minimum_access_level_for_push] = nil
params[:minimum_access_level_for_delete] = nil
end
it 'does not create a container registry protection rule' do
expect { post_container_registry_rule }.to not_change(ContainerRegistry::Protection::Rule, :count)
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
end
it_behaves_like 'rejecting container registry protection rules request when enough permissions'
end
context 'with invalid token' do
subject(:post_container_registry_rules) { post(api(url), headers: headers_with_invalid_token, params: params) }
it_behaves_like 'returning response status', :unauthorized
end
end
end

View File

@ -42,37 +42,24 @@ RSpec.describe ReleaseEnvironmentsModel, feature_category: :delivery do
end
describe '#environment' do
context 'when CI_PROJECT_PATH is not gitlab-org/security/gitlab' do
context 'for stable branch' do
it 'returns the correct environment' do
stub_env('CI_COMMIT_REF_SLUG', '15-10-stable-ee')
expect(model.environment).to eq('15-10-stable')
end
end
context 'for RC tag' do
it 'returns the correct environment' do
stub_env('CI_COMMIT_REF_SLUG', 'v15.10.3-rc42-ee')
expect(model.environment).to eq('15-10-stable')
end
end
context 'for release tag' do
it 'returns the correct environment' do
stub_env('CI_COMMIT_REF_SLUG', 'v15.10.3-ee')
expect(model.environment).to eq('15-10-stable')
end
context 'for stable branch' do
it 'returns the correct environment' do
stub_env('CI_COMMIT_REF_SLUG', '15-10-stable-ee')
expect(model.environment).to eq('15-10-stable')
end
end
context 'when CI_PROJECT_PATH is gitlab-org/security/gitlab' do
before do
stub_env('CI_PROJECT_PATH', 'gitlab-org/security/gitlab')
stub_env('CI_COMMIT_REF_SLUG', '15-10-stable-ee')
context 'for RC tag' do
it 'returns the correct environment' do
stub_env('CI_COMMIT_REF_SLUG', 'v15.10.3-rc42-ee')
expect(model.environment).to eq('15-10-stable')
end
end
it 'returns the environment with -security' do
expect(model.environment).to eq('15-10-stable-security')
context 'for release tag' do
it 'returns the correct environment' do
stub_env('CI_COMMIT_REF_SLUG', 'v15.10.3-ee')
expect(model.environment).to eq('15-10-stable')
end
end
end

View File

@ -0,0 +1,128 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Members::ActivityService, :clean_gitlab_redis_shared_state, feature_category: :seat_cost_management do
include ExclusiveLeaseHelpers
let_it_be(:user) { create(:user) }
let_it_be(:namespace) { create(:group) }
let_it_be(:project) { create(:project, namespace: namespace) }
let(:lease_key) { "members_activity_event:#{namespace.id}:#{user.id}" }
let(:instance) { described_class.new(user, namespace) }
describe '#execute' do
subject(:execute) { instance.execute }
shared_examples 'does not update last_activity_on' do
it do
expect_next_found_instance_of(Member) do |member|
expect(member).not_to receive(:touch).with(:last_activity_on)
end
expect(execute).to be_success
end
end
shared_examples 'updates last_activity_on' do
it 'updates the members last activity timestamp' do
expect(execute).to be_success
expect(member.reload.last_activity_on).to eq Date.today
end
it 'tries to obtain a lease', :freeze_time do
ttl = (Time.current.end_of_day - Time.current).to_i
expect_to_obtain_exclusive_lease(lease_key, timeout: ttl)
expect(execute).to be_success
end
context 'when a lease cannot be obtained' do
it 'returns success' do
stub_exclusive_lease_taken(lease_key)
expect(execute).to be_success
end
end
end
shared_examples 'tracking a group member' do
context 'when last activity was before today' do
let_it_be(:member) do
create(:group_member, :developer, user: user, group: namespace, last_activity_on: Date.yesterday)
end
it_behaves_like 'updates last_activity_on'
end
context 'when last activity was today' do
let_it_be(:member) do
create(:group_member, :developer, user: user, group: namespace, last_activity_on: Date.today)
end
it_behaves_like 'does not update last_activity_on'
end
end
shared_examples 'tracking a project member' do
context 'when last activity was before today' do
let_it_be(:member) do
create(:project_member, :developer, user: user, project: project, last_activity_on: Date.yesterday)
end
it_behaves_like 'updates last_activity_on'
end
context 'when last activity was today' do
let_it_be(:member) do
create(:project_member, :developer, user: user, project: project, last_activity_on: Date.today)
end
it_behaves_like 'does not update last_activity_on'
end
end
shared_examples 'returns an error' do
it do
response = execute
expect(response).to be_error
expect(response.message).to eq('Invalid params')
end
end
context 'with a namespace' do
it_behaves_like 'tracking a group member'
it_behaves_like 'tracking a project member'
end
context 'with no namespace' do
let(:namespace) { nil }
it_behaves_like 'returns an error'
end
context 'with no user' do
let(:user) { nil }
it_behaves_like 'returns an error'
end
context 'with no member for namespace and user' do
it 'returns does not raise an error' do
response = execute
expect(response).to be_success
end
it 'releases the lease' do
expect_to_obtain_exclusive_lease(lease_key, 'uuid')
expect_to_cancel_exclusive_lease(lease_key, 'uuid')
execute
end
end
end
end

View File

@ -6,7 +6,8 @@ RSpec.shared_context 'with current_organization setting', shared_context: :metad
let_it_be(:current_organization, reload: true) { create(:organization, name: 'Current Organization') }
before do
Current.organization = current_organization
allow(Current).to receive(:organization).and_return(current_organization)
allow(Current).to receive(:organization_id).and_return(current_organization.id)
end
after do

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
RSpec.shared_context 'with default_organization setting', shared_context: :metadata do # rubocop:disable RSpec/SharedGroupsMetadata -- We are actually using this for easy metadata setting
let_it_be(:default_organization) { create(:organization, :default) }
end
RSpec.configure do |rspec|
rspec.include_context 'with default_organization setting', with_default_organization: true
end

View File

@ -0,0 +1,53 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Users::RecordLastActivityWorker, feature_category: :seat_cost_management do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let(:user_id) { user.id }
let(:namespace_id) { group.id }
let(:last_activity_event) do
Users::ActivityEvent.new(data: { user_id: user_id, namespace_id: namespace_id })
end
it_behaves_like 'subscribes to event' do
let(:event) { last_activity_event }
end
it 'has the `until_executed` deduplicate strategy' do
expect(described_class.get_deduplicate_strategy).to eq(:until_executed)
end
describe '#handle_event' do
let_it_be(:member) { create(:group_member, user: user, group: group, last_activity_on: 1.week.ago) }
it 'updates the member timestamp' do
expect do
consume_event(subscriber: described_class, event: last_activity_event)
end.to change { member.reload.last_activity_on }
end
shared_examples 'returns early' do
it do
expect(Users::ActivityService).not_to receive(:new)
consume_event(subscriber: described_class, event: last_activity_event)
end
end
context 'when the user is not found' do
let(:user_id) { non_existing_record_id }
it_behaves_like 'returns early'
end
context 'when the namespace is not found' do
let(:namespace_id) { non_existing_record_id }
it_behaves_like 'returns early'
end
end
end