Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
31bafaf04d
commit
ef6e077a33
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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 #
|
||||
###################
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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, {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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!
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -807,6 +807,8 @@
|
|||
- 1
|
||||
- - upload_checksum
|
||||
- 1
|
||||
- - users_record_last_activity
|
||||
- 1
|
||||
- - users_track_namespace_visits
|
||||
- 1
|
||||
- - vulnerabilities_mark_dropped_as_resolved
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
b57add5352ed4723a1a0ed4a3e53829a6bd492fbfa903da35d0a02f5457efd84
|
||||
|
|
@ -0,0 +1 @@
|
|||
2c40583211aacf8dc10f3e56545faf9211fc394ef6314af38181398b5fef0fbc
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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).*?\)'
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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` |
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}'
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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] ""
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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' },
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue