Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
40ac69b43f
commit
98b4d737cd
|
@ -7,7 +7,7 @@ workflow:
|
||||||
include:
|
include:
|
||||||
- local: .gitlab/ci/version.yml
|
- local: .gitlab/ci/version.yml
|
||||||
- local: .gitlab/ci/global.gitlab-ci.yml
|
- local: .gitlab/ci/global.gitlab-ci.yml
|
||||||
- component: "gitlab.com/gitlab-org/quality/pipeline-common/allure-report@9.14.0"
|
- component: "gitlab.com/gitlab-org/quality/pipeline-common/allure-report@11.3.0"
|
||||||
inputs:
|
inputs:
|
||||||
job_name: "e2e-test-report"
|
job_name: "e2e-test-report"
|
||||||
job_stage: "report"
|
job_stage: "report"
|
||||||
|
@ -17,7 +17,7 @@ include:
|
||||||
gitlab_auth_token_variable_name: "PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE"
|
gitlab_auth_token_variable_name: "PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE"
|
||||||
allure_job_name: "${QA_RUN_TYPE}"
|
allure_job_name: "${QA_RUN_TYPE}"
|
||||||
- project: gitlab-org/quality/pipeline-common
|
- project: gitlab-org/quality/pipeline-common
|
||||||
ref: 9.14.0
|
ref: 11.3.0
|
||||||
file:
|
file:
|
||||||
- /ci/notify-slack.gitlab-ci.yml
|
- /ci/notify-slack.gitlab-ci.yml
|
||||||
- /ci/qa-report.gitlab-ci.yml
|
- /ci/qa-report.gitlab-ci.yml
|
||||||
|
|
|
@ -27,8 +27,6 @@ Layout/LineBreakAfterFinalMixin:
|
||||||
- 'ee/app/workers/active_user_count_threshold_worker.rb'
|
- 'ee/app/workers/active_user_count_threshold_worker.rb'
|
||||||
- 'ee/app/workers/analytics/value_stream_dashboard/count_worker.rb'
|
- 'ee/app/workers/analytics/value_stream_dashboard/count_worker.rb'
|
||||||
- 'ee/app/workers/arkose/blocked_users_report_worker.rb'
|
- 'ee/app/workers/arkose/blocked_users_report_worker.rb'
|
||||||
- 'ee/app/workers/geo/metrics_update_worker.rb'
|
|
||||||
- 'ee/app/workers/geo/sidekiq_cron_config_worker.rb'
|
|
||||||
- 'ee/app/workers/gitlab_subscriptions/notify_seats_exceeded_batch_worker.rb'
|
- 'ee/app/workers/gitlab_subscriptions/notify_seats_exceeded_batch_worker.rb'
|
||||||
- 'ee/app/workers/historical_data_worker.rb'
|
- 'ee/app/workers/historical_data_worker.rb'
|
||||||
- 'ee/app/workers/ldap_all_groups_sync_worker.rb'
|
- 'ee/app/workers/ldap_all_groups_sync_worker.rb'
|
||||||
|
|
2
Gemfile
2
Gemfile
|
@ -262,7 +262,7 @@ gem 'asciidoctor-kroki', '~> 0.10.0', require: false, feature_category: :markdow
|
||||||
gem 'rouge', '~> 4.5.0', feature_category: :shared
|
gem 'rouge', '~> 4.5.0', feature_category: :shared
|
||||||
gem 'truncato', '~> 0.7.13', feature_category: :team_planning
|
gem 'truncato', '~> 0.7.13', feature_category: :team_planning
|
||||||
gem 'nokogiri', '~> 1.18', feature_category: :shared
|
gem 'nokogiri', '~> 1.18', feature_category: :shared
|
||||||
gem 'gitlab-glfm-markdown', '~> 0.0.30', feature_category: :markdown
|
gem 'gitlab-glfm-markdown', '~> 0.0.31', feature_category: :markdown
|
||||||
gem 'tanuki_emoji', '~> 0.13', feature_category: :markdown
|
gem 'tanuki_emoji', '~> 0.13', feature_category: :markdown
|
||||||
gem 'unicode-emoji', '~> 4.0', feature_category: :markdown
|
gem 'unicode-emoji', '~> 4.0', feature_category: :markdown
|
||||||
|
|
||||||
|
|
|
@ -223,13 +223,13 @@
|
||||||
{"name":"gitlab-dangerfiles","version":"4.9.1","platform":"ruby","checksum":"296b19d8aca5e4da8d391234914a1c4dfedc29700ddbcd9c554b6ffaa7fdf1b2"},
|
{"name":"gitlab-dangerfiles","version":"4.9.1","platform":"ruby","checksum":"296b19d8aca5e4da8d391234914a1c4dfedc29700ddbcd9c554b6ffaa7fdf1b2"},
|
||||||
{"name":"gitlab-experiment","version":"0.9.1","platform":"ruby","checksum":"f230ee742154805a755d5f2539dc44d93cdff08c5bbbb7656018d61f93d01f48"},
|
{"name":"gitlab-experiment","version":"0.9.1","platform":"ruby","checksum":"f230ee742154805a755d5f2539dc44d93cdff08c5bbbb7656018d61f93d01f48"},
|
||||||
{"name":"gitlab-fog-azure-rm","version":"2.2.0","platform":"ruby","checksum":"31aa7c2170f57874053144e7f716ec9e15f32e71ffbd2c56753dce46e2e78ba9"},
|
{"name":"gitlab-fog-azure-rm","version":"2.2.0","platform":"ruby","checksum":"31aa7c2170f57874053144e7f716ec9e15f32e71ffbd2c56753dce46e2e78ba9"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"aarch64-linux-gnu","checksum":"faaa675d3934a066b0374a5ba4a1d97ec228195656814d5eb51c5db2356acad8"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"aarch64-linux-gnu","checksum":"21bd0d9bccaeb1fc9787bbe8b4cabc30688d6800ae2212b7972c9438f0b40f59"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"aarch64-linux-musl","checksum":"06407c9ce6753b6e6219302c875e0d981c15bdcc98a2df4f064771e5e40859da"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"aarch64-linux-musl","checksum":"87b3b500dbab5dd003eff79d2909e8b23eb839fbfb49ab342cd173d6b9adb16d"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"arm64-darwin","checksum":"788065d211288ff60cf3c5d875f678678cf03824d79b5e2d269aaa83c5c4f411"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"arm64-darwin","checksum":"4f452db9f540ea1af0672042fe046b2b883d897f1325394894376da4e7acc1e8"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"ruby","checksum":"f3dea33f9fc6d8991fd496631ef36b6e2406392e378d879f320c4c1b645c0066"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"ruby","checksum":"91c8e9c61c78d49f1e52dbb49e9fd2d790a494a254bc8ad54004dadf091e2d1b"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"x86_64-darwin","checksum":"583057ac3223900759a2bbc0f7dfe11befba74127217f883cd8ed2de2b7e2251"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"x86_64-darwin","checksum":"3d9df3278add66356ce07c983b74f6f0bdefcdfb4110f43dd291c43fb69eb6a6"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"x86_64-linux-gnu","checksum":"d43b185f48577fbe850fa49a5ff28ce2d875a4dd23b1c5333fae2ef4c40bea40"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"x86_64-linux-gnu","checksum":"c2c4c8f77d078f2afb1420289e32f444e91ece48d8f76a78e43f5b69f5d2248c"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"x86_64-linux-musl","checksum":"50ac59a1f9545387773fe0daa389ae146c73beb1acff4093011c2a9a1889879a"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"x86_64-linux-musl","checksum":"cc3e8529f8eaf6be9bfa71509a58396540bb7c2b025e5dd9615a73ad0cf2a6b3"},
|
||||||
{"name":"gitlab-kas-grpc","version":"17.11.2","platform":"ruby","checksum":"f2b9054dcf636346e89549e9478a684a38bf03bf853332e84154ec3a9856ae1c"},
|
{"name":"gitlab-kas-grpc","version":"17.11.2","platform":"ruby","checksum":"f2b9054dcf636346e89549e9478a684a38bf03bf853332e84154ec3a9856ae1c"},
|
||||||
{"name":"gitlab-labkit","version":"0.37.0","platform":"ruby","checksum":"d2dd0a60db2149a9a8eebf2975dc23f54ac3ceb01bdba732eb1b26b86dfffa70"},
|
{"name":"gitlab-labkit","version":"0.37.0","platform":"ruby","checksum":"d2dd0a60db2149a9a8eebf2975dc23f54ac3ceb01bdba732eb1b26b86dfffa70"},
|
||||||
{"name":"gitlab-license","version":"2.6.0","platform":"ruby","checksum":"2c1f8ae73835640ec77bf758c1d0c9730635043c01cf77902f7976e826d7d016"},
|
{"name":"gitlab-license","version":"2.6.0","platform":"ruby","checksum":"2c1f8ae73835640ec77bf758c1d0c9730635043c01cf77902f7976e826d7d016"},
|
||||||
|
|
|
@ -766,7 +766,7 @@ GEM
|
||||||
mime-types
|
mime-types
|
||||||
net-http-persistent (~> 4.0)
|
net-http-persistent (~> 4.0)
|
||||||
nokogiri (~> 1, >= 1.10.8)
|
nokogiri (~> 1, >= 1.10.8)
|
||||||
gitlab-glfm-markdown (0.0.30)
|
gitlab-glfm-markdown (0.0.31)
|
||||||
rb_sys (~> 0.9.109)
|
rb_sys (~> 0.9.109)
|
||||||
gitlab-kas-grpc (17.11.2)
|
gitlab-kas-grpc (17.11.2)
|
||||||
grpc (~> 1.0)
|
grpc (~> 1.0)
|
||||||
|
@ -2163,7 +2163,7 @@ DEPENDENCIES
|
||||||
gitlab-duo-workflow-service-client (~> 0.1)!
|
gitlab-duo-workflow-service-client (~> 0.1)!
|
||||||
gitlab-experiment (~> 0.9.1)
|
gitlab-experiment (~> 0.9.1)
|
||||||
gitlab-fog-azure-rm (~> 2.2.0)
|
gitlab-fog-azure-rm (~> 2.2.0)
|
||||||
gitlab-glfm-markdown (~> 0.0.30)
|
gitlab-glfm-markdown (~> 0.0.31)
|
||||||
gitlab-housekeeper!
|
gitlab-housekeeper!
|
||||||
gitlab-http!
|
gitlab-http!
|
||||||
gitlab-kas-grpc (~> 17.11.0)
|
gitlab-kas-grpc (~> 17.11.0)
|
||||||
|
|
|
@ -223,13 +223,13 @@
|
||||||
{"name":"gitlab-dangerfiles","version":"4.9.1","platform":"ruby","checksum":"296b19d8aca5e4da8d391234914a1c4dfedc29700ddbcd9c554b6ffaa7fdf1b2"},
|
{"name":"gitlab-dangerfiles","version":"4.9.1","platform":"ruby","checksum":"296b19d8aca5e4da8d391234914a1c4dfedc29700ddbcd9c554b6ffaa7fdf1b2"},
|
||||||
{"name":"gitlab-experiment","version":"0.9.1","platform":"ruby","checksum":"f230ee742154805a755d5f2539dc44d93cdff08c5bbbb7656018d61f93d01f48"},
|
{"name":"gitlab-experiment","version":"0.9.1","platform":"ruby","checksum":"f230ee742154805a755d5f2539dc44d93cdff08c5bbbb7656018d61f93d01f48"},
|
||||||
{"name":"gitlab-fog-azure-rm","version":"2.2.0","platform":"ruby","checksum":"31aa7c2170f57874053144e7f716ec9e15f32e71ffbd2c56753dce46e2e78ba9"},
|
{"name":"gitlab-fog-azure-rm","version":"2.2.0","platform":"ruby","checksum":"31aa7c2170f57874053144e7f716ec9e15f32e71ffbd2c56753dce46e2e78ba9"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"aarch64-linux-gnu","checksum":"faaa675d3934a066b0374a5ba4a1d97ec228195656814d5eb51c5db2356acad8"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"aarch64-linux-gnu","checksum":"21bd0d9bccaeb1fc9787bbe8b4cabc30688d6800ae2212b7972c9438f0b40f59"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"aarch64-linux-musl","checksum":"06407c9ce6753b6e6219302c875e0d981c15bdcc98a2df4f064771e5e40859da"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"aarch64-linux-musl","checksum":"87b3b500dbab5dd003eff79d2909e8b23eb839fbfb49ab342cd173d6b9adb16d"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"arm64-darwin","checksum":"788065d211288ff60cf3c5d875f678678cf03824d79b5e2d269aaa83c5c4f411"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"arm64-darwin","checksum":"4f452db9f540ea1af0672042fe046b2b883d897f1325394894376da4e7acc1e8"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"ruby","checksum":"f3dea33f9fc6d8991fd496631ef36b6e2406392e378d879f320c4c1b645c0066"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"ruby","checksum":"91c8e9c61c78d49f1e52dbb49e9fd2d790a494a254bc8ad54004dadf091e2d1b"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"x86_64-darwin","checksum":"583057ac3223900759a2bbc0f7dfe11befba74127217f883cd8ed2de2b7e2251"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"x86_64-darwin","checksum":"3d9df3278add66356ce07c983b74f6f0bdefcdfb4110f43dd291c43fb69eb6a6"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"x86_64-linux-gnu","checksum":"d43b185f48577fbe850fa49a5ff28ce2d875a4dd23b1c5333fae2ef4c40bea40"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"x86_64-linux-gnu","checksum":"c2c4c8f77d078f2afb1420289e32f444e91ece48d8f76a78e43f5b69f5d2248c"},
|
||||||
{"name":"gitlab-glfm-markdown","version":"0.0.30","platform":"x86_64-linux-musl","checksum":"50ac59a1f9545387773fe0daa389ae146c73beb1acff4093011c2a9a1889879a"},
|
{"name":"gitlab-glfm-markdown","version":"0.0.31","platform":"x86_64-linux-musl","checksum":"cc3e8529f8eaf6be9bfa71509a58396540bb7c2b025e5dd9615a73ad0cf2a6b3"},
|
||||||
{"name":"gitlab-kas-grpc","version":"17.11.2","platform":"ruby","checksum":"f2b9054dcf636346e89549e9478a684a38bf03bf853332e84154ec3a9856ae1c"},
|
{"name":"gitlab-kas-grpc","version":"17.11.2","platform":"ruby","checksum":"f2b9054dcf636346e89549e9478a684a38bf03bf853332e84154ec3a9856ae1c"},
|
||||||
{"name":"gitlab-labkit","version":"0.37.0","platform":"ruby","checksum":"d2dd0a60db2149a9a8eebf2975dc23f54ac3ceb01bdba732eb1b26b86dfffa70"},
|
{"name":"gitlab-labkit","version":"0.37.0","platform":"ruby","checksum":"d2dd0a60db2149a9a8eebf2975dc23f54ac3ceb01bdba732eb1b26b86dfffa70"},
|
||||||
{"name":"gitlab-license","version":"2.6.0","platform":"ruby","checksum":"2c1f8ae73835640ec77bf758c1d0c9730635043c01cf77902f7976e826d7d016"},
|
{"name":"gitlab-license","version":"2.6.0","platform":"ruby","checksum":"2c1f8ae73835640ec77bf758c1d0c9730635043c01cf77902f7976e826d7d016"},
|
||||||
|
|
|
@ -766,7 +766,7 @@ GEM
|
||||||
mime-types
|
mime-types
|
||||||
net-http-persistent (~> 4.0)
|
net-http-persistent (~> 4.0)
|
||||||
nokogiri (~> 1, >= 1.10.8)
|
nokogiri (~> 1, >= 1.10.8)
|
||||||
gitlab-glfm-markdown (0.0.30)
|
gitlab-glfm-markdown (0.0.31)
|
||||||
rb_sys (~> 0.9.109)
|
rb_sys (~> 0.9.109)
|
||||||
gitlab-kas-grpc (17.11.2)
|
gitlab-kas-grpc (17.11.2)
|
||||||
grpc (~> 1.0)
|
grpc (~> 1.0)
|
||||||
|
@ -2163,7 +2163,7 @@ DEPENDENCIES
|
||||||
gitlab-duo-workflow-service-client (~> 0.1)!
|
gitlab-duo-workflow-service-client (~> 0.1)!
|
||||||
gitlab-experiment (~> 0.9.1)
|
gitlab-experiment (~> 0.9.1)
|
||||||
gitlab-fog-azure-rm (~> 2.2.0)
|
gitlab-fog-azure-rm (~> 2.2.0)
|
||||||
gitlab-glfm-markdown (~> 0.0.30)
|
gitlab-glfm-markdown (~> 0.0.31)
|
||||||
gitlab-housekeeper!
|
gitlab-housekeeper!
|
||||||
gitlab-http!
|
gitlab-http!
|
||||||
gitlab-kas-grpc (~> 17.11.0)
|
gitlab-kas-grpc (~> 17.11.0)
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
# @graphql-eslint/eslint-plugin@4.0.0 reports missing IDs in `FragmentDefinition`. For now, we are
|
||||||
|
# ignoring the newly uncovered error on this fragment. Please consider addressing the violation
|
||||||
|
# if you are modifying this file and it turns out selecting the ID makes sense here.
|
||||||
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
fragment BaseCiGroupVariable on CiGroupVariable {
|
fragment BaseCiGroupVariable on CiGroupVariable {
|
||||||
description
|
description
|
||||||
environmentScope
|
environmentScope
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
# @graphql-eslint/eslint-plugin@4.0.0 reports missing IDs in `FragmentDefinition`. For now, we are
|
||||||
|
# ignoring the newly uncovered error on this fragment. Please consider addressing the violation
|
||||||
|
# if you are modifying this file and it turns out selecting the ID makes sense here.
|
||||||
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
fragment BaseCiInstanceVariable on CiInstanceVariable {
|
fragment BaseCiInstanceVariable on CiInstanceVariable {
|
||||||
description
|
description
|
||||||
protected
|
protected
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
# @graphql-eslint/eslint-plugin@4.0.0 reports missing IDs in `FragmentDefinition`. For now, we are
|
||||||
|
# ignoring the newly uncovered error on this fragment. Please consider addressing the violation
|
||||||
|
# if you are modifying this file and it turns out selecting the ID makes sense here.
|
||||||
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
fragment BaseCiProjectVariable on CiProjectVariable {
|
fragment BaseCiProjectVariable on CiProjectVariable {
|
||||||
description
|
description
|
||||||
environmentScope
|
environmentScope
|
||||||
|
|
|
@ -27,7 +27,7 @@ query getJobs(
|
||||||
}
|
}
|
||||||
nodes {
|
nodes {
|
||||||
artifacts {
|
artifacts {
|
||||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
nodes {
|
nodes {
|
||||||
downloadPath
|
downloadPath
|
||||||
fileType
|
fileType
|
||||||
|
|
|
@ -11,7 +11,7 @@ query getPipelineJobs($fullPath: ID!, $iid: ID!, $after: String) {
|
||||||
}
|
}
|
||||||
nodes {
|
nodes {
|
||||||
artifacts {
|
artifacts {
|
||||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
nodes {
|
nodes {
|
||||||
downloadPath
|
downloadPath
|
||||||
fileType
|
fileType
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
#import "./list_item_shared.fragment.graphql"
|
#import "./list_item_shared.fragment.graphql"
|
||||||
|
|
||||||
fragment ListItem on CiRunner {
|
fragment ListItem on CiRunner {
|
||||||
|
# @graphql-eslint/eslint-plugin@4.0.0 reports missing IDs in `FragmentDefinition`. For now, we are
|
||||||
|
# ignoring the newly uncovered error on this fragment. Please consider addressing the violation
|
||||||
|
# if you are modifying this file and it turns out selecting the ID makes sense here.
|
||||||
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
...ListItemShared
|
...ListItemShared
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,10 @@ fragment ListItemShared on CiRunner {
|
||||||
}
|
}
|
||||||
managers(first: 1) {
|
managers(first: 1) {
|
||||||
count
|
count
|
||||||
|
# @graphql-eslint/eslint-plugin@4.0.0 reports missing IDs in `FragmentDefinition`. For now, we are
|
||||||
|
# ignoring the newly uncovered error on this fragment. Please consider addressing the violation
|
||||||
|
# if you are modifying this file and it turns out selecting the ID makes sense here.
|
||||||
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
nodes {
|
nodes {
|
||||||
version
|
version
|
||||||
ipAddress
|
ipAddress
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
# @graphql-eslint/eslint-plugin@4.0.0 reports missing IDs in `FragmentDefinition`. For now, we are
|
||||||
|
# ignoring the newly uncovered error on this fragment. Please consider addressing the violation
|
||||||
|
# if you are modifying this file and it turns out selecting the ID makes sense here.
|
||||||
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
fragment ApprovalSummary on Deployment {
|
fragment ApprovalSummary on Deployment {
|
||||||
iid
|
iid
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
# @graphql-eslint/eslint-plugin@4.0.0 reports missing IDs in `FragmentDefinition`. For now, we are
|
||||||
|
# ignoring the newly uncovered error on this fragment. Please consider addressing the violation
|
||||||
|
# if you are modifying this file and it turns out selecting the ID makes sense here.
|
||||||
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
fragment UserAvailability on User {
|
fragment UserAvailability on User {
|
||||||
status {
|
status {
|
||||||
availability
|
availability
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
# @graphql-eslint/eslint-plugin@4.0.0 reports missing IDs in `FragmentDefinition`. For now, we are
|
||||||
|
# ignoring the newly uncovered error on this fragment. Please consider addressing the violation
|
||||||
|
# if you are modifying this file and it turns out selecting the ID makes sense here.
|
||||||
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
fragment IncidentFields on Issue {
|
fragment IncidentFields on Issue {
|
||||||
severity
|
severity
|
||||||
escalationStatus
|
escalationStatus
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
# @graphql-eslint/eslint-plugin@4.0.0 reports missing IDs in `FragmentDefinition`. For now, we are
|
||||||
|
# ignoring the newly uncovered error on this fragment. Please consider addressing the violation
|
||||||
|
# if you are modifying this file and it turns out selecting the ID makes sense here.
|
||||||
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
fragment MergeRequestApprovalFragment on MergeRequest {
|
fragment MergeRequestApprovalFragment on MergeRequest {
|
||||||
approved
|
approved
|
||||||
approvedBy {
|
approvedBy {
|
||||||
|
|
|
@ -14,7 +14,7 @@ query securityReportsDownloadPaths(
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
artifacts {
|
artifacts {
|
||||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
nodes {
|
nodes {
|
||||||
downloadPath
|
downloadPath
|
||||||
fileType
|
fileType
|
||||||
|
|
|
@ -5,6 +5,10 @@ fragment JobArtifacts on Pipeline {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
artifacts {
|
artifacts {
|
||||||
|
# @graphql-eslint/eslint-plugin@4.0.0 reports missing IDs in `FragmentDefinition`. For now, we are
|
||||||
|
# ignoring the newly uncovered error on this fragment. Please consider addressing the violation
|
||||||
|
# if you are modifying this file and it turns out selecting the ID makes sense here.
|
||||||
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
nodes {
|
nodes {
|
||||||
downloadPath
|
downloadPath
|
||||||
fileType
|
fileType
|
||||||
|
|
|
@ -14,7 +14,7 @@ query securityReportDownloadPaths(
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
artifacts {
|
artifacts {
|
||||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
nodes {
|
nodes {
|
||||||
downloadPath
|
downloadPath
|
||||||
fileType
|
fileType
|
||||||
|
|
|
@ -4,7 +4,7 @@ query getPipelineCorpuses($projectPath: ID!, $iid: ID, $reportTypes: [SecurityRe
|
||||||
project(fullPath: $projectPath) {
|
project(fullPath: $projectPath) {
|
||||||
id
|
id
|
||||||
pipeline(iid: $iid) {
|
pipeline(iid: $iid) {
|
||||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
...JobArtifacts
|
...JobArtifacts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#import "ee_else_ce/work_items/graphql/work_item_metadata_widgets.fragment.graphql"
|
#import "ee_else_ce/work_items/graphql/work_item_metadata_widgets.fragment.graphql"
|
||||||
#import "ee_else_ce/work_items/graphql/work_item_metadata_widgets_extras.fragment.graphql"
|
#import "ee_else_ce/work_items/graphql/work_item_metadata_widgets_extras.fragment.graphql"
|
||||||
|
|
||||||
|
# @graphql-eslint/eslint-plugin@4.0.0 reports missing IDs in `FragmentDefinition`. For now, we are
|
||||||
|
# ignoring the newly uncovered error on this fragment. Please consider addressing the violation
|
||||||
|
# if you are modifying this file and it turns out selecting the ID makes sense here.
|
||||||
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
fragment WorkItemLinkedItemsFragment on WorkItem {
|
fragment WorkItemLinkedItemsFragment on WorkItem {
|
||||||
widgets {
|
widgets {
|
||||||
... on WorkItemWidgetLinkedItems {
|
... on WorkItemWidgetLinkedItems {
|
||||||
|
|
|
@ -9,6 +9,10 @@ fragment WorkItemWidgets on WorkItemWidget {
|
||||||
description
|
description
|
||||||
descriptionHtml
|
descriptionHtml
|
||||||
lastEditedAt
|
lastEditedAt
|
||||||
|
# @graphql-eslint/eslint-plugin@4.0.0 reports missing IDs in `FragmentDefinition`. For now, we are
|
||||||
|
# ignoring the newly uncovered error on this fragment. Please consider addressing the violation
|
||||||
|
# if you are modifying this file and it turns out selecting the ID makes sense here.
|
||||||
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
lastEditedBy {
|
lastEditedBy {
|
||||||
name
|
name
|
||||||
webPath
|
webPath
|
||||||
|
|
|
@ -16,6 +16,7 @@ module Mutations
|
||||||
type: GraphQL::Types::ID,
|
type: GraphQL::Types::ID,
|
||||||
required: true,
|
required: true,
|
||||||
description: 'Full path of the namespace on which the preference is set.'
|
description: 'Full path of the namespace on which the preference is set.'
|
||||||
|
|
||||||
argument :work_item_type_id,
|
argument :work_item_type_id,
|
||||||
type: ::Types::GlobalIDType[::WorkItems::Type],
|
type: ::Types::GlobalIDType[::WorkItems::Type],
|
||||||
required: false,
|
required: false,
|
||||||
|
@ -27,6 +28,11 @@ module Mutations
|
||||||
required: false,
|
required: false,
|
||||||
default_value: :created_asc
|
default_value: :created_asc
|
||||||
|
|
||||||
|
argument :display_settings,
|
||||||
|
type: GraphQL::Types::JSON,
|
||||||
|
description: 'Display settings for the work item lists.',
|
||||||
|
required: false
|
||||||
|
|
||||||
field :user_preferences,
|
field :user_preferences,
|
||||||
type: ::Types::WorkItems::UserPreference,
|
type: ::Types::WorkItems::UserPreference,
|
||||||
description: 'User preferences.'
|
description: 'User preferences.'
|
||||||
|
|
|
@ -23,6 +23,10 @@ fragment LinkedPipelineData on Pipeline {
|
||||||
userPermissions {
|
userPermissions {
|
||||||
updatePipeline
|
updatePipeline
|
||||||
}
|
}
|
||||||
|
# @graphql-eslint/eslint-plugin@4.0.0 reports missing IDs in `FragmentDefinition`. For now, we are
|
||||||
|
# ignoring the newly uncovered error on this fragment. Please consider addressing the violation
|
||||||
|
# if you are modifying this file and it turns out selecting the ID makes sense here.
|
||||||
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
status: detailedStatus {
|
status: detailedStatus {
|
||||||
__typename
|
__typename
|
||||||
group
|
group
|
||||||
|
@ -59,13 +63,13 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
|
||||||
downstream {
|
downstream {
|
||||||
__typename
|
__typename
|
||||||
nodes {
|
nodes {
|
||||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available -- for detailedStatus.id
|
# eslint-disable-next-line @graphql-eslint/require-selections -- for detailedStatus.id
|
||||||
...LinkedPipelineData
|
...LinkedPipelineData
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
upstream {
|
upstream {
|
||||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available -- for detailedStatus.id
|
# eslint-disable-next-line @graphql-eslint/require-selections -- for detailedStatus.id
|
||||||
...LinkedPipelineData
|
...LinkedPipelineData
|
||||||
}
|
}
|
||||||
stages {
|
stages {
|
||||||
|
@ -74,7 +78,7 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
|
||||||
__typename
|
__typename
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
status: detailedStatus {
|
status: detailedStatus {
|
||||||
__typename
|
__typename
|
||||||
action {
|
action {
|
||||||
|
@ -91,7 +95,7 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
|
||||||
nodes {
|
nodes {
|
||||||
__typename
|
__typename
|
||||||
id
|
id
|
||||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
status: detailedStatus {
|
status: detailedStatus {
|
||||||
__typename
|
__typename
|
||||||
label
|
label
|
||||||
|
@ -122,7 +126,7 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
|
||||||
...CiNeeds
|
...CiNeeds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
# eslint-disable-next-line @graphql-eslint/require-selections
|
||||||
status: detailedStatus {
|
status: detailedStatus {
|
||||||
__typename
|
__typename
|
||||||
icon
|
icon
|
||||||
|
|
|
@ -22,6 +22,11 @@ module Types
|
||||||
null: true,
|
null: true,
|
||||||
description: 'Sort order for work item lists.'
|
description: 'Sort order for work item lists.'
|
||||||
|
|
||||||
|
field :display_settings,
|
||||||
|
type: GraphQL::Types::JSON,
|
||||||
|
null: true,
|
||||||
|
description: 'Display settings for the work item lists.'
|
||||||
|
|
||||||
def sort
|
def sort
|
||||||
object.sort&.to_sym
|
object.sort&.to_sym
|
||||||
end
|
end
|
||||||
|
|
|
@ -63,6 +63,10 @@ module Approvable
|
||||||
def eligible_for_unapproval_by?(user)
|
def eligible_for_unapproval_by?(user)
|
||||||
user && approved_by?(user) && user.can?(:approve_merge_request, self)
|
user && approved_by?(user) && user.can?(:approve_merge_request, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def approvals_for_user_ids(user_ids)
|
||||||
|
approvals.where(user_id: user_ids)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Approvable.prepend_mod
|
Approvable.prepend_mod
|
||||||
|
|
|
@ -89,6 +89,7 @@ module MergeRequests
|
||||||
merge_request_activity_counter.track_reviewers_changed_action(user: current_user)
|
merge_request_activity_counter.track_reviewers_changed_action(user: current_user)
|
||||||
trigger_merge_request_reviewers_updated(merge_request)
|
trigger_merge_request_reviewers_updated(merge_request)
|
||||||
|
|
||||||
|
set_reviewers_approved(merge_request, new_reviewers) if new_reviewers.any?
|
||||||
set_first_reviewer_assigned_at_metrics(merge_request) if new_reviewers.any?
|
set_first_reviewer_assigned_at_metrics(merge_request) if new_reviewers.any?
|
||||||
trigger_user_merge_request_updated(merge_request)
|
trigger_user_merge_request_updated(merge_request)
|
||||||
end
|
end
|
||||||
|
@ -218,6 +219,13 @@ module MergeRequests
|
||||||
# Implemented in EE
|
# Implemented in EE
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_reviewers_approved(merge_request, new_reviewers)
|
||||||
|
approval_users = merge_request.approvals_for_user_ids(new_reviewers.map(&:id))
|
||||||
|
|
||||||
|
merge_request.merge_request_reviewers_with(approval_users.select(:user_id))
|
||||||
|
.update_all(state: :approved)
|
||||||
|
end
|
||||||
|
|
||||||
def merge_request_metrics_service(merge_request)
|
def merge_request_metrics_service(merge_request)
|
||||||
MergeRequestMetricsService.new(merge_request.metrics)
|
MergeRequestMetricsService.new(merge_request.metrics)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
- if @project.pages_deployed?
|
- if @project.pages_deployed?
|
||||||
- if can?(current_user, :remove_pages, @project)
|
= render ::Layouts::CrudComponent.new(s_('GitLabPages|Delete Pages'),
|
||||||
.gl-bg-red-50.gl-shadow-inner-l-3-red-600.gl-py-5.gl-px-6.gl-mt-5
|
options: { class: 'gl-mt-5' },
|
||||||
%h4.gl-text-lg.gl-mt-0= s_('GitLabPages|Remove pages')
|
body_options: { class: '!gl-m-0 gl-p-5 gl-bg-feedback-danger' }) do |c|
|
||||||
%p= s_('GitLabPages|Removing pages will prevent them from being exposed to the public internet.')
|
- c.with_body do
|
||||||
= render Pajamas::ButtonComponent.new(href: project_pages_path(@project),
|
- if can?(current_user, :remove_pages, @project)
|
||||||
variant: :danger,
|
%p
|
||||||
method: :delete,
|
= s_('GitLabPages|This action will permanently delete all Pages deployments.')
|
||||||
button_options: { data: { confirm: s_('GitLabPages|Are you sure?'), 'confirm-btn-variant': 'danger' }, "aria-label": s_('GitLabPages|Remove pages') }) do
|
= s_('GitLabPages|This is permanent and cannot be undone. To deploy this Pages site again, run a new pipeline.')
|
||||||
= s_('GitLabPages|Remove pages')
|
= render Pajamas::ButtonComponent.new(href: project_pages_path(@project),
|
||||||
- else
|
variant: :danger,
|
||||||
.nothing-here-block
|
method: :delete,
|
||||||
= s_('GitLabPages|Only project maintainers can remove pages')
|
button_options: { data: { confirm: s_('GitLabPages|Are you sure?'), 'confirm-btn-variant': 'danger' }, "aria-label": s_('GitLabPages|Remove pages') }) do
|
||||||
|
= s_('GitLabPages|Delete Pages')
|
||||||
|
- else
|
||||||
|
= s_('GitLabPages|Only project maintainers can remove pages.')
|
||||||
|
|
|
@ -5,5 +5,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/178281
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/514208
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/514208
|
||||||
milestone: '17.11'
|
milestone: '17.11'
|
||||||
group: group::source code
|
group: group::source code
|
||||||
type: gitlab_com_derisk
|
type: beta
|
||||||
default_enabled: false
|
default_enabled: true
|
|
@ -1119,8 +1119,8 @@ Settings.cell['enabled'] ||= false # All Cells Features are disabled by default
|
||||||
Settings.cell['id'] ||= nil
|
Settings.cell['id'] ||= nil
|
||||||
Settings.cell['database'] ||= {}
|
Settings.cell['database'] ||= {}
|
||||||
Settings.cell.database['skip_sequence_alteration'] ||= false
|
Settings.cell.database['skip_sequence_alteration'] ||= false
|
||||||
|
# NOTE: `topology_service_client` is the configuration to use going forward as per https://docs.gitlab.com/administration/cells/#configuration
|
||||||
# Topology Service Client Settings
|
# We continue to be backwards compatible and support `topology_service` as a top-level key.
|
||||||
Settings.cell['topology_service_client'] ||= Settings.respond_to?(:topology_service) ? Settings.topology_service || {} : {}
|
Settings.cell['topology_service_client'] ||= Settings.respond_to?(:topology_service) ? Settings.topology_service || {} : {}
|
||||||
Settings.cell.topology_service_client['address'] ||= 'topology-service.gitlab.example.com:443'
|
Settings.cell.topology_service_client['address'] ||= 'topology-service.gitlab.example.com:443'
|
||||||
Settings.cell.topology_service_client['ca_file'] ||= '/home/git/gitlab/config/topology-service-ca.pem'
|
Settings.cell.topology_service_client['ca_file'] ||= '/home/git/gitlab/config/topology-service-ca.pem'
|
||||||
|
|
|
@ -20,7 +20,7 @@ if Gitlab.config.cell.enabled
|
||||||
|
|
||||||
Settings.required_topology_service_settings.each do |setting|
|
Settings.required_topology_service_settings.each do |setting|
|
||||||
setting_value = Gitlab.config.cell.topology_service_client.send(setting)
|
setting_value = Gitlab.config.cell.topology_service_client.send(setting)
|
||||||
print_error.call("Topology Service setting '#{setting}' is not set.") if setting_value.blank?
|
print_error.call("Topology Service Client setting '#{setting}' is not set.") if setting_value.blank?
|
||||||
end
|
end
|
||||||
elsif Gitlab.config.cell.id.present?
|
elsif Gitlab.config.cell.id.present?
|
||||||
print_error.call("Cell ID is set but Cell is not enabled.")
|
print_error.call("Cell ID is set but Cell is not enabled.")
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
key_path: counts.total_top_level_groups
|
||||||
|
description: Counts the number of top-level groups on the instance
|
||||||
|
product_group: organizations
|
||||||
|
product_categories:
|
||||||
|
- groups_and_projects
|
||||||
|
value_type: number
|
||||||
|
status: active
|
||||||
|
milestone: "18.1"
|
||||||
|
instrumentation_class: CountTopLevelGroupsMetric
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/190217
|
||||||
|
time_frame: all
|
||||||
|
data_source: database
|
||||||
|
data_category: optional
|
||||||
|
tiers:
|
||||||
|
- free
|
||||||
|
- premium
|
||||||
|
- ultimate
|
|
@ -1,8 +1,9 @@
|
||||||
---
|
---
|
||||||
migration_job_name: BackfillStatusPagePublishedIncidentsNamespaceId
|
migration_job_name: BackfillStatusPagePublishedIncidentsNamespaceId
|
||||||
description: Backfills sharding key `status_page_published_incidents.namespace_id` from `issues`.
|
description: Backfills sharding key `status_page_published_incidents.namespace_id`
|
||||||
|
from `issues`.
|
||||||
feature_category: incident_management
|
feature_category: incident_management
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/174868
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/174868
|
||||||
milestone: '17.7'
|
milestone: '17.7'
|
||||||
queued_migration_version: 20241205143060
|
queued_migration_version: 20241205143060
|
||||||
finalized_by: # version of the migration that finalized this BBM
|
finalized_by: '20250521232727'
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class FinalizeHkBackfillStatusPagePublishedIncidentsNamespaceId < Gitlab::Database::Migration[2.3]
|
||||||
|
milestone '18.1'
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
|
||||||
|
|
||||||
|
def up
|
||||||
|
ensure_batched_background_migration_is_finished(
|
||||||
|
job_class_name: 'BackfillStatusPagePublishedIncidentsNamespaceId',
|
||||||
|
table_name: :status_page_published_incidents,
|
||||||
|
column_name: :id,
|
||||||
|
job_arguments: [:namespace_id, :issues, :namespace_id, :issue_id],
|
||||||
|
finalize: true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down; end
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
790cec3f4a91a1db687211c1c6013683339e66d39ceb32fd486015b00069b294
|
|
@ -13001,6 +13001,7 @@ Input type: `WorkItemUserPreferenceUpdateInput`
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | ---- | ----------- |
|
| ---- | ---- | ----------- |
|
||||||
| <a id="mutationworkitemuserpreferenceupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
| <a id="mutationworkitemuserpreferenceupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||||
|
| <a id="mutationworkitemuserpreferenceupdatedisplaysettings"></a>`displaySettings` | [`JSON`](#json) | Display settings for the work item lists. |
|
||||||
| <a id="mutationworkitemuserpreferenceupdatenamespacepath"></a>`namespacePath` | [`ID!`](#id) | Full path of the namespace on which the preference is set. |
|
| <a id="mutationworkitemuserpreferenceupdatenamespacepath"></a>`namespacePath` | [`ID!`](#id) | Full path of the namespace on which the preference is set. |
|
||||||
| <a id="mutationworkitemuserpreferenceupdatesort"></a>`sort` | [`WorkItemSort`](#workitemsort) | Sort order for work item lists. |
|
| <a id="mutationworkitemuserpreferenceupdatesort"></a>`sort` | [`WorkItemSort`](#workitemsort) | Sort order for work item lists. |
|
||||||
| <a id="mutationworkitemuserpreferenceupdateworkitemtypeid"></a>`workItemTypeId` | [`WorkItemsTypeID`](#workitemstypeid) | Global ID of a work item type. |
|
| <a id="mutationworkitemuserpreferenceupdateworkitemtypeid"></a>`workItemTypeId` | [`WorkItemsTypeID`](#workitemstypeid) | Global ID of a work item type. |
|
||||||
|
@ -21551,6 +21552,7 @@ Counts for each analyzer status in the group and subgroups.
|
||||||
| <a id="analyzergroupstatustypefailure"></a>`failure` | [`Int!`](#int) | Number of analyzers failed. |
|
| <a id="analyzergroupstatustypefailure"></a>`failure` | [`Int!`](#int) | Number of analyzers failed. |
|
||||||
| <a id="analyzergroupstatustypenamespaceid"></a>`namespaceId` | [`Int!`](#int) | Namespace ID. |
|
| <a id="analyzergroupstatustypenamespaceid"></a>`namespaceId` | [`Int!`](#int) | Namespace ID. |
|
||||||
| <a id="analyzergroupstatustypesuccess"></a>`success` | [`Int!`](#int) | Number of analyzers succeeded. |
|
| <a id="analyzergroupstatustypesuccess"></a>`success` | [`Int!`](#int) | Number of analyzers succeeded. |
|
||||||
|
| <a id="analyzergroupstatustypeupdatedat"></a>`updatedAt` | [`ISO8601DateTime!`](#iso8601datetime) | Timestamp of when the status was last updated. |
|
||||||
|
|
||||||
### `AnalyzerProjectStatusType`
|
### `AnalyzerProjectStatusType`
|
||||||
|
|
||||||
|
@ -21565,6 +21567,7 @@ Analyzer status (success/fail) for projects.
|
||||||
| <a id="analyzerprojectstatustypelastcall"></a>`lastCall` | [`Time!`](#time) | Last time analyzer was called. |
|
| <a id="analyzerprojectstatustypelastcall"></a>`lastCall` | [`Time!`](#time) | Last time analyzer was called. |
|
||||||
| <a id="analyzerprojectstatustypeprojectid"></a>`projectId` | [`Int!`](#int) | Project ID. |
|
| <a id="analyzerprojectstatustypeprojectid"></a>`projectId` | [`Int!`](#int) | Project ID. |
|
||||||
| <a id="analyzerprojectstatustypestatus"></a>`status` | [`AnalyzerStatusEnum!`](#analyzerstatusenum) | Analyzer status. |
|
| <a id="analyzerprojectstatustypestatus"></a>`status` | [`AnalyzerStatusEnum!`](#analyzerstatusenum) | Analyzer status. |
|
||||||
|
| <a id="analyzerprojectstatustypeupdatedat"></a>`updatedAt` | [`ISO8601DateTime!`](#iso8601datetime) | Timestamp of when the status was last updated. |
|
||||||
|
|
||||||
### `AncestorType`
|
### `AncestorType`
|
||||||
|
|
||||||
|
@ -42070,6 +42073,7 @@ Represents Depth limit reached for the allowed work item type.
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ---- | ---- | ----------- |
|
| ---- | ---- | ----------- |
|
||||||
|
| <a id="workitemtypesuserpreferencedisplaysettings"></a>`displaySettings` | [`JSON`](#json) | Display settings for the work item lists. |
|
||||||
| <a id="workitemtypesuserpreferencenamespace"></a>`namespace` | [`Namespace!`](#namespace) | Namespace for the user preference. |
|
| <a id="workitemtypesuserpreferencenamespace"></a>`namespace` | [`Namespace!`](#namespace) | Namespace for the user preference. |
|
||||||
| <a id="workitemtypesuserpreferencesort"></a>`sort` | [`WorkItemSort`](#workitemsort) | Sort order for work item lists. |
|
| <a id="workitemtypesuserpreferencesort"></a>`sort` | [`WorkItemSort`](#workitemsort) | Sort order for work item lists. |
|
||||||
| <a id="workitemtypesuserpreferenceworkitemtype"></a>`workItemType` | [`WorkItemType`](#workitemtype) | Type assigned to the work item. |
|
| <a id="workitemtypesuserpreferenceworkitemtype"></a>`workItemType` | [`WorkItemType`](#workitemtype) | Type assigned to the work item. |
|
||||||
|
|
|
@ -839,10 +839,11 @@ space by truncating tables. This results in a smaller data set: For example,
|
||||||
the data in `users` table on CI database is no longer read and also no
|
the data in `users` table on CI database is no longer read and also no
|
||||||
longer updated. So this data can be removed by truncating the tables.
|
longer updated. So this data can be removed by truncating the tables.
|
||||||
|
|
||||||
For this purpose, GitLab provides two Rake tasks, one for each database:
|
For this purpose, GitLab provides separate Rake tasks, one for each database:
|
||||||
|
|
||||||
- `gitlab:db:truncate_legacy_tables:main` will truncate the CI tables in Main database.
|
- `gitlab:db:truncate_legacy_tables:main` will truncate the legacy tables in Main database.
|
||||||
- `gitlab:db:truncate_legacy_tables:ci` will truncate the Main tables in CI database.
|
- `gitlab:db:truncate_legacy_tables:ci` will truncate the legacy tables in CI database.
|
||||||
|
- `gitlab:db:truncate_legacy_tables:sec` will truncate the legacy tables in Sec database.
|
||||||
|
|
||||||
{{< alert type="note" >}}
|
{{< alert type="note" >}}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,9 @@ title: AI impact analytics
|
||||||
|
|
||||||
{{< /history >}}
|
{{< /history >}}
|
||||||
|
|
||||||
The primary goal of AI impact analytics is to measure GitLab Duo's impact on software development lifecycle (SDLC) performance.
|
AI impact analytics measure the impact of GitLab Duo on software development lifecycle (SDLC) performance.
|
||||||
This dashboard provides visibility into key SDLC metrics in the context of AI adoption, helping you measure which metrics have improved as a result of AI investments.
|
This dashboard provides visibility into key SDLC metrics in the context of AI adoption for projects or groups.
|
||||||
|
You can use the dashboard to measure which metrics have improved from your AI investments.
|
||||||
|
|
||||||
Use AI impact analytics for:
|
Use AI impact analytics for:
|
||||||
|
|
||||||
|
@ -32,30 +33,32 @@ Use AI impact analytics for:
|
||||||
To learn how you can optimize your license utilization,
|
To learn how you can optimize your license utilization,
|
||||||
see [GitLab Duo add-ons](../../subscriptions/subscription-add-ons.md).
|
see [GitLab Duo add-ons](../../subscriptions/subscription-add-ons.md).
|
||||||
|
|
||||||
|
To learn more about AI impact analytics, see the blog post
|
||||||
|
[Developing GitLab Duo: AI impact analytics dashboard measures the ROI of AI](https://about.gitlab.com/blog/2024/05/15/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/).
|
||||||
|
|
||||||
For a click-through demo, see the [AI impact analytics product tour](https://gitlab.navattic.com/ai-impact).
|
For a click-through demo, see the [AI impact analytics product tour](https://gitlab.navattic.com/ai-impact).
|
||||||
|
|
||||||
<i class="fa-youtube-play" aria-hidden="true"></i>
|
<i class="fa-youtube-play" aria-hidden="true"></i>
|
||||||
For an overview, see [GitLab Duo AI Impact Dashboard](https://youtu.be/FxSWX64aUOE?si=7Yfc6xHm63c3BRwn).
|
For an overview, see [GitLab Duo AI Impact Dashboard](https://youtu.be/FxSWX64aUOE?si=7Yfc6xHm63c3BRwn).
|
||||||
<!-- Video published on 2025-03-06 -->
|
<!-- Video published on 2025-03-06 -->
|
||||||
|
|
||||||
## AI impact metrics
|
## Key metrics
|
||||||
|
|
||||||
AI impact analytics displays key metrics and metric trends for a project or group.
|
|
||||||
|
|
||||||
### Key metrics
|
|
||||||
|
|
||||||
- **Duo seats: Assigned and used**: Percentage of users that are assigned a Duo seat and used at least one AI feature in the last 30 days.
|
- **Duo seats: Assigned and used**: Percentage of users that are assigned a Duo seat and used at least one AI feature in the last 30 days.
|
||||||
It is calculated as the number of users with Duo seats that use AI features divided by the total number of assigned Duo seats.
|
It is calculated as the number of users with Duo seats that use AI features divided by the total number of assigned Duo seats.
|
||||||
- **Code Suggestions: Unique users**: Percentage of users that engage with Code Suggestions every month. It is calculated as the number of monthly unique Code Suggestions users divided by total monthly [unique contributors](../profile/contributions_calendar.md#user-contribution-events). Only unique code contributors, meaning users with `pushed` events, are included in the calculation.
|
- **Code Suggestions: Unique users**: Percentage of users that engage with Code Suggestions every month.
|
||||||
|
It is calculated as the number of monthly unique Code Suggestions users divided by total monthly [unique contributors](../profile/contributions_calendar.md#user-contribution-events).
|
||||||
|
Only unique code contributors (users with `pushed` events) are included in the calculation.
|
||||||
- **Code Suggestions: Acceptance rate**: Percentage of code suggestions provided by GitLab Duo that have been accepted by code contributors in the last 30 days.
|
- **Code Suggestions: Acceptance rate**: Percentage of code suggestions provided by GitLab Duo that have been accepted by code contributors in the last 30 days.
|
||||||
It is calculated as the number of accepted code suggestions divided by the total number of generated code suggestions.
|
It is calculated as the number of accepted code suggestions divided by the total number of generated code suggestions.
|
||||||
- **Duo Chat: Unique users**: Percentage of users that engage with GitLab Duo Chat every month. It is calculated as the number of monthly unique GitLab Duo Chat users divided by the total GitLab Duo assigned users.
|
- **Duo Chat: Unique users**: Percentage of users that engage with GitLab Duo Chat every month.
|
||||||
|
It is calculated as the number of monthly unique GitLab Duo Chat users divided by the total GitLab Duo assigned users.
|
||||||
|
|
||||||
### Metric trends
|
## Metric trends
|
||||||
|
|
||||||
The **Metric trends** table displays metrics for the last six months, with monthly values, percentage changes in the past six months, and trend sparklines.
|
The **Metric trends** table displays metrics for the last six months, with monthly values, percentage changes in the past six months, and trend sparklines.
|
||||||
|
|
||||||
#### Lifecycle metrics
|
### Lifecycle metrics
|
||||||
|
|
||||||
- [**Cycle time**](../group/value_stream_analytics/_index.md#lifecycle-metrics)
|
- [**Cycle time**](../group/value_stream_analytics/_index.md#lifecycle-metrics)
|
||||||
- [**Lead time**](../group/value_stream_analytics/_index.md#lifecycle-metrics)
|
- [**Lead time**](../group/value_stream_analytics/_index.md#lifecycle-metrics)
|
||||||
|
@ -63,13 +66,19 @@ The **Metric trends** table displays metrics for the last six months, with month
|
||||||
- [**Change failure rate**](dora_metrics.md#change-failure-rate)
|
- [**Change failure rate**](dora_metrics.md#change-failure-rate)
|
||||||
- [**Critical vulnerabilities over time**](../application_security/vulnerability_report/_index.md)
|
- [**Critical vulnerabilities over time**](../application_security/vulnerability_report/_index.md)
|
||||||
|
|
||||||
#### AI usage metrics
|
### AI usage metrics
|
||||||
|
|
||||||
**Code Suggestions usage**: Monthly user engagement with AI Code Suggestions.
|
**Code Suggestions usage**: Monthly user engagement with AI Code Suggestions.
|
||||||
|
|
||||||
- The month-over-month comparison of the AI Usage unique users rate gives a more accurate indication of this metric, as it eliminates factors such as developer experience level and project type or complexity.
|
The month-over-month comparison of the AI Usage unique users rate gives a more accurate indication of this metric,
|
||||||
- The baseline for the AI Usage trend is the total number of code contributors, not just users with GitLab Duo seats. This baseline gives a more accurate representation of AI usage by team members. To learn more about AI impact analytics, see the blog post [Developing GitLab Duo: AI impact analytics dashboard measures the ROI of AI](https://about.gitlab.com/blog/2024/05/15/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/).
|
because it eliminates factors such as developer experience level and project type or complexity.
|
||||||
- To analyze the performance of teams that use AI versus teams that don't, you can create a custom [Value Streams Dashboard Scheduled Report](https://gitlab.com/explore/catalog/components/vsd-reports-generator) based on the AI impact view of projects and groups with and without GitLab Duo.
|
|
||||||
|
The baseline for the AI Usage trend is the total number of code contributors, not just users with GitLab Duo seats.
|
||||||
|
This baseline gives a more accurate representation of AI usage by team members.
|
||||||
|
|
||||||
|
To analyze the performance of teams that use AI versus teams that don't, you can create a custom
|
||||||
|
[Value Streams Dashboard Scheduled Report](https://gitlab.com/explore/catalog/components/vsd-reports-generator)
|
||||||
|
based on the AI impact view of projects and groups with and without GitLab Duo.
|
||||||
|
|
||||||
{{< alert type="note" >}}
|
{{< alert type="note" >}}
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,7 @@ You can filter by:
|
||||||
- **Report Type**: For more details, see [Report Type filter](#report-type-filter)
|
- **Report Type**: For more details, see [Report Type filter](#report-type-filter)
|
||||||
- **Scanner**: For more details, see [Scanner filter](#scanner-filter)
|
- **Scanner**: For more details, see [Scanner filter](#scanner-filter)
|
||||||
- **Activity**: For more details, see [Activity filter](#activity-filter).
|
- **Activity**: For more details, see [Activity filter](#activity-filter).
|
||||||
- **Identifier**: Filter by the vulnerability's identifier (available only for projects, support for groups is proposed in [issue 508713](https://gitlab.com/gitlab-org/gitlab/-/issues/508713)).
|
- **Identifier**: Filter by the vulnerability's identifier (requires [advanced vulnerability management](#advanced-vulnerability-management). Without advanced vulnerability management, availability is restricted to projects and groups with a maximum of 20,000 vulnerabilities).
|
||||||
- **Project**: Filter vulnerabilities in specific projects (available only for groups).
|
- **Project**: Filter vulnerabilities in specific projects (available only for groups).
|
||||||
|
|
||||||
<!-- vale gitlab_base.SubstitutionWarning = YES -->
|
<!-- vale gitlab_base.SubstitutionWarning = YES -->
|
||||||
|
@ -244,6 +244,7 @@ The **GitLab Duo (AI)** filter is available when:
|
||||||
- Non-OWASP category in OWASP top 10 grouping [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/442526) in GitLab 17.1 [with a flag](../../../administration/feature_flags.md) named `owasp_top_10_null_filtering`. Disabled by default.
|
- Non-OWASP category in OWASP top 10 grouping [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/442526) in GitLab 17.1 [with a flag](../../../administration/feature_flags.md) named `owasp_top_10_null_filtering`. Disabled by default.
|
||||||
- Non-OWASP category in OWASP top 10 grouping [enabled on GitLab Self-Managed, and GitLab Dedicated](https://gitlab.com/gitlab-org/gitlab/-/issues/463783) in GitLab 17.5.
|
- Non-OWASP category in OWASP top 10 grouping [enabled on GitLab Self-Managed, and GitLab Dedicated](https://gitlab.com/gitlab-org/gitlab/-/issues/463783) in GitLab 17.5.
|
||||||
- Non-OWASP category in OWASP top 10 grouping [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/463783) in GitLab 17.6. Feature flag `owasp_top_10_null_filtering` removed.
|
- Non-OWASP category in OWASP top 10 grouping [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/463783) in GitLab 17.6. Feature flag `owasp_top_10_null_filtering` removed.
|
||||||
|
- OWASP 2021 top 10 grouping [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/466034) on GitLab.com and GitLab Dedicated in GitLab 18.1 [with a flag](../../../administration/feature_flags.md) named `vulnerability_report_owasp_2021`. Disabled by default. Feature also requires [advanced vulnerability management](#advanced-vulnerability-management).
|
||||||
|
|
||||||
{{< /history >}}
|
{{< /history >}}
|
||||||
|
|
||||||
|
@ -256,6 +257,7 @@ You can group by:
|
||||||
- Report Type
|
- Report Type
|
||||||
- Scanner
|
- Scanner
|
||||||
- OWASP top 10 2017
|
- OWASP top 10 2017
|
||||||
|
- OWASP top 10 2021 (requires [advanced vulnerability management](#advanced-vulnerability-management))
|
||||||
|
|
||||||
### Group vulnerabilities
|
### Group vulnerabilities
|
||||||
|
|
||||||
|
@ -530,6 +532,38 @@ To add a vulnerability manually:
|
||||||
|
|
||||||
The newly-created vulnerability's detail page is opened.
|
The newly-created vulnerability's detail page is opened.
|
||||||
|
|
||||||
|
## Advanced vulnerability management
|
||||||
|
|
||||||
|
{{< history >}}
|
||||||
|
|
||||||
|
- Ingestion of vulnerability data into advanced search [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/536299) in GitLab 18.1 [with a flag](../../../administration/feature_flags.md) named `vulnerability_es_ingestion`. Available in GitLab.com and GitLab Dedicated. Disabled by default.
|
||||||
|
- Filters for OWASP 2021 grouping and identifiers in advanced search [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/537673) with the feature flag `advanced_vulnerability_management`. Available in GitLab.com and GitLab Dedicated. Disabled by default.
|
||||||
|
|
||||||
|
{{< /history >}}
|
||||||
|
|
||||||
|
{{< alert type="flag" >}}
|
||||||
|
|
||||||
|
Advanced vulnerability management is controlled by feature flags.
|
||||||
|
For more information, see the history.
|
||||||
|
|
||||||
|
{{< /alert >}}
|
||||||
|
|
||||||
|
GitLab primarily uses PostgreSQL for filtering in the vulnerability report. Due to database indexing limitations and performance challenges when applying multiple filters, GitLab uses [advanced search](../../search/advanced_search.md) for specific vulnerability management features.
|
||||||
|
|
||||||
|
Advanced search powers the following features:
|
||||||
|
|
||||||
|
1. Grouping data by OWASP 2021 categories in the vulnerability report for a project or group.
|
||||||
|
1. Filtering based on a vulnerability's identifier in the vulnerability report for a project or group.
|
||||||
|
|
||||||
|
Advanced search is used only for these specific features, including when they are combined with other [filters](#filter-vulnerabilities). Other filters, when used independently, continue to use the standard PostgreSQL filtering.
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
To use the filters in advanced vulnerability management:
|
||||||
|
|
||||||
|
- You must use GitLab.com or a GitLab Dedicated instance with [advanced search enabled](../../search/advanced_search.md#enable-advanced-search). This feature is not supported on GitLab Self-Managed, but support is proposed [issue 525484](https://gitlab.com/gitlab-org/gitlab/-/issues/525484).
|
||||||
|
- You must be in the vulnerability report for a project or group. This feature is not supported in the security dashboard, but support is proposed in [issue 537807](https://gitlab.com/gitlab-org/gitlab/-/issues/537807).
|
||||||
|
|
||||||
## Operational vulnerabilities
|
## Operational vulnerabilities
|
||||||
|
|
||||||
The **Operational vulnerabilities** tab lists vulnerabilities found by [Operational container scanning](../../clusters/agent/vulnerabilities.md).
|
The **Operational vulnerabilities** tab lists vulnerabilities found by [Operational container scanning](../../clusters/agent/vulnerabilities.md).
|
||||||
|
|
|
@ -69,13 +69,19 @@ If the case of `404.html`, there are different scenarios. For example:
|
||||||
You can configure redirects for your site using a `_redirects` file. For more information, see
|
You can configure redirects for your site using a `_redirects` file. For more information, see
|
||||||
[Create redirects for GitLab Pages](redirects.md).
|
[Create redirects for GitLab Pages](redirects.md).
|
||||||
|
|
||||||
## Remove your pages
|
## Delete a Pages site
|
||||||
|
|
||||||
To remove your pages:
|
Permanently delete all Pages deployments for a project.
|
||||||
|
This is permanent and cannot be undone.
|
||||||
|
|
||||||
|
To delete your pages:
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to** and find your project.
|
1. On the left sidebar, select **Search or go to** and find your project.
|
||||||
1. Select **Deploy > Pages**.
|
1. Select **Deploy > Pages**.
|
||||||
1. Select **Remove pages**.
|
1. Select **Delete pages**.
|
||||||
|
|
||||||
|
Your Pages site is no longer deployed.
|
||||||
|
To deploy this Pages site again, run a new pipeline.
|
||||||
|
|
||||||
## Subdomains of subdomains
|
## Subdomains of subdomains
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ To create a parallel deployment:
|
||||||
pages:
|
pages:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
script:
|
script:
|
||||||
- echo "Pages accessible through ${CI_PAGES_URL}/${CI_COMMIT_BRANCH}"
|
- echo "Pages accessible through ${CI_PAGES_URL}"
|
||||||
pages: # specifies that this is a Pages job and publishes the default public directory
|
pages: # specifies that this is a Pages job and publishes the default public directory
|
||||||
path_prefix: "$CI_COMMIT_BRANCH"
|
path_prefix: "$CI_COMMIT_BRANCH"
|
||||||
```
|
```
|
||||||
|
|
|
@ -23,7 +23,7 @@ Use advanced search to find exactly what you need across your entire GitLab inst
|
||||||
With advanced search:
|
With advanced search:
|
||||||
|
|
||||||
- Identify code patterns across all projects to refactor shared components more efficiently.
|
- Identify code patterns across all projects to refactor shared components more efficiently.
|
||||||
- Locate security vulnerabilities in dependencies across your entire organization at once.
|
- Locate security vulnerabilities across your entire organization's codebase and dependencies using [advanced vulnerability management](../application_security/vulnerability_report/_index.md#advanced-vulnerability-management).
|
||||||
- Track usage of deprecated functions or libraries throughout all repositories.
|
- Track usage of deprecated functions or libraries throughout all repositories.
|
||||||
- Find discussions buried in issues, merge requests, or comments.
|
- Find discussions buried in issues, merge requests, or comments.
|
||||||
- Discover existing solutions instead of reinventing functionality that already exists.
|
- Discover existing solutions instead of reinventing functionality that already exists.
|
||||||
|
|
|
@ -4,7 +4,8 @@ import { existsSync } from 'node:fs';
|
||||||
import localRules from 'eslint-plugin-local-rules';
|
import localRules from 'eslint-plugin-local-rules';
|
||||||
import js from '@eslint/js';
|
import js from '@eslint/js';
|
||||||
import { FlatCompat } from '@eslint/eslintrc';
|
import { FlatCompat } from '@eslint/eslintrc';
|
||||||
import * as graphqlEslint from '@graphql-eslint/eslint-plugin';
|
// eslint-disable-next-line import/no-unresolved
|
||||||
|
import graphqlPlugin from '@graphql-eslint/eslint-plugin';
|
||||||
import * as todoLists from './.eslint_todo/index.mjs';
|
import * as todoLists from './.eslint_todo/index.mjs';
|
||||||
|
|
||||||
const { dirname } = import.meta;
|
const { dirname } = import.meta;
|
||||||
|
@ -108,7 +109,7 @@ export default [
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
...compat.extends(...extendConfigs),
|
...compat.extends(...extendConfigs),
|
||||||
...compat.plugins('no-jquery', '@graphql-eslint'),
|
...compat.plugins('no-jquery'),
|
||||||
{
|
{
|
||||||
rules: {
|
rules: {
|
||||||
'no-unused-vars': [
|
'no-unused-vars': [
|
||||||
|
@ -589,11 +590,9 @@ export default [
|
||||||
files: ['**/*.graphql'],
|
files: ['**/*.graphql'],
|
||||||
|
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
ecmaVersion: 5,
|
|
||||||
sourceType: 'script',
|
|
||||||
|
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
parser: { ...graphqlEslint, meta: { name: '@graphql-eslint' } },
|
parser: graphqlPlugin.parser,
|
||||||
graphQLConfig: {
|
graphQLConfig: {
|
||||||
documents: '{,ee/,jh/}app/**/*.graphql',
|
documents: '{,ee/,jh/}app/**/*.graphql',
|
||||||
schema: './tmp/tests/graphql/gitlab_schema_apollo.graphql',
|
schema: './tmp/tests/graphql/gitlab_schema_apollo.graphql',
|
||||||
|
@ -601,12 +600,16 @@ export default [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
plugins: {
|
||||||
|
'@graphql-eslint': graphqlPlugin,
|
||||||
|
},
|
||||||
|
|
||||||
rules: {
|
rules: {
|
||||||
'filenames/match-regex': 'off',
|
'filenames/match-regex': 'off',
|
||||||
'spaced-comment': 'off',
|
'spaced-comment': 'off',
|
||||||
'@graphql-eslint/no-anonymous-operations': 'error',
|
'@graphql-eslint/no-anonymous-operations': 'error',
|
||||||
'@graphql-eslint/unique-operation-name': 'error',
|
'@graphql-eslint/unique-operation-name': 'error',
|
||||||
'@graphql-eslint/require-id-when-available': 'error',
|
'@graphql-eslint/require-selections': 'error',
|
||||||
'@graphql-eslint/no-unused-variables': 'error',
|
'@graphql-eslint/no-unused-variables': 'error',
|
||||||
'@graphql-eslint/no-unused-fragments': 'error',
|
'@graphql-eslint/no-unused-fragments': 'error',
|
||||||
'@graphql-eslint/no-duplicate-fields': 'error',
|
'@graphql-eslint/no-duplicate-fields': 'error',
|
||||||
|
@ -622,7 +625,7 @@ export default [
|
||||||
],
|
],
|
||||||
|
|
||||||
rules: {
|
rules: {
|
||||||
'@graphql-eslint/require-id-when-available': 'off',
|
'@graphql-eslint/require-selections': 'off',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
|
|
||||||
module ActiveContext
|
module ActiveContext
|
||||||
class Embeddings
|
class Embeddings
|
||||||
def self.generate_embeddings(content, model: nil, primitive: 'semantic_search_issue', user: nil)
|
def self.generate_embeddings(content, unit_primitive:, model: nil, user: nil)
|
||||||
|
action = 'embedding'
|
||||||
embeddings = Gitlab::Llm::VertexAi::Embeddings::Text
|
embeddings = Gitlab::Llm::VertexAi::Embeddings::Text
|
||||||
.new(content, user: user, tracking_context: { action: 'embedding' }, unit_primitive: primitive, model: model)
|
.new(content, user: user, tracking_context: { action: action }, unit_primitive: unit_primitive, model: model)
|
||||||
.execute
|
.execute
|
||||||
|
|
||||||
embeddings.all?(Array) ? embeddings : [embeddings]
|
embeddings.all?(Array) ? embeddings : [embeddings]
|
||||||
|
|
|
@ -14,6 +14,7 @@ module ActiveContext
|
||||||
class_methods do
|
class_methods do
|
||||||
def apply_embeddings(
|
def apply_embeddings(
|
||||||
refs:,
|
refs:,
|
||||||
|
unit_primitive:,
|
||||||
content_field: :content,
|
content_field: :content,
|
||||||
content_method: nil,
|
content_method: nil,
|
||||||
remove_content: true
|
remove_content: true
|
||||||
|
@ -44,7 +45,8 @@ module ActiveContext
|
||||||
versions = items.first[:versions]
|
versions = items.first[:versions]
|
||||||
contents = items.map { |item| item[:doc][content_field] }
|
contents = items.map { |item| item[:doc][content_field] }
|
||||||
|
|
||||||
embeddings_by_version = generate_embeddings_for_each_version(versions, contents)
|
embeddings_by_version = generate_embeddings_for_each_version(versions: versions, contents: contents,
|
||||||
|
unit_primitive: unit_primitive)
|
||||||
|
|
||||||
# Apply the generated embeddings back to each document
|
# Apply the generated embeddings back to each document
|
||||||
items.each.with_index do |item, index|
|
items.each.with_index do |item, index|
|
||||||
|
@ -75,9 +77,10 @@ module ActiveContext
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_embeddings_for_each_version(versions, contents)
|
def generate_embeddings_for_each_version(versions:, contents:, unit_primitive:)
|
||||||
versions.each_with_object({}) do |version, embeddings_by_version|
|
versions.each_with_object({}) do |version, embeddings_by_version|
|
||||||
embedding = ActiveContext::Embeddings.generate_embeddings(contents, model: version[:model])
|
embedding = ActiveContext::Embeddings.generate_embeddings(contents, model: version[:model],
|
||||||
|
unit_primitive: unit_primitive)
|
||||||
embeddings_by_version[version[:field]] = embedding
|
embeddings_by_version[version[:field]] = embedding
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
include ::ActiveContext::Preprocessors::Embeddings
|
include ::ActiveContext::Preprocessors::Embeddings
|
||||||
|
|
||||||
add_preprocessor :embeddings do |refs|
|
add_preprocessor :embeddings do |refs|
|
||||||
apply_embeddings(refs: refs, content_method: :embedding_content)
|
apply_embeddings(refs: refs, content_method: :embedding_content, unit_primitive: 'test_unit_primitive')
|
||||||
end
|
end
|
||||||
|
|
||||||
def embedding_content
|
def embedding_content
|
||||||
|
@ -29,6 +29,7 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
let(:object_id) { 5 }
|
let(:object_id) { 5 }
|
||||||
let(:collection_name) { 'mock_collection' }
|
let(:collection_name) { 'mock_collection' }
|
||||||
let(:vectors) { [1.0, 2.0] }
|
let(:vectors) { [1.0, 2.0] }
|
||||||
|
let(:unit_primitive) { 'test_unit_primitive' }
|
||||||
let(:vertex_blank_error) { StandardError.new('The text content is empty.') }
|
let(:vertex_blank_error) { StandardError.new('The text content is empty.') }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
@ -61,7 +62,7 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
|
|
||||||
it 'generates and sets embeddings for each document' do
|
it 'generates and sets embeddings for each document' do
|
||||||
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
||||||
.once.with(['Some content'], model: nil).and_return([vectors])
|
.once.with(['Some content'], model: nil, unit_primitive: unit_primitive).and_return([vectors])
|
||||||
|
|
||||||
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
||||||
end
|
end
|
||||||
|
@ -86,7 +87,7 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
|
|
||||||
it 'generates and sets embeddings for each document' do
|
it 'generates and sets embeddings for each document' do
|
||||||
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
||||||
.once.with(['Other content'], model: nil).and_return([vectors])
|
.once.with(['Other content'], model: nil, unit_primitive: unit_primitive).and_return([vectors])
|
||||||
|
|
||||||
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
||||||
end
|
end
|
||||||
|
@ -109,7 +110,7 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
|
|
||||||
it 'generates and sets embeddings for each document' do
|
it 'generates and sets embeddings for each document' do
|
||||||
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
||||||
.once.with(['Some content'], model: nil).and_return([vectors])
|
.once.with(['Some content'], model: nil, unit_primitive: unit_primitive).and_return([vectors])
|
||||||
|
|
||||||
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
||||||
end
|
end
|
||||||
|
@ -121,7 +122,8 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
include ::ActiveContext::Preprocessors::Embeddings
|
include ::ActiveContext::Preprocessors::Embeddings
|
||||||
|
|
||||||
add_preprocessor :embeddings do |refs|
|
add_preprocessor :embeddings do |refs|
|
||||||
apply_embeddings(refs: refs, content_method: :embedding_content, remove_content: false)
|
apply_embeddings(refs: refs, content_method: :embedding_content, remove_content: false,
|
||||||
|
unit_primitive: 'test_unit_primitive')
|
||||||
end
|
end
|
||||||
|
|
||||||
def embedding_content
|
def embedding_content
|
||||||
|
@ -146,7 +148,8 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
include ::ActiveContext::Preprocessors::Embeddings
|
include ::ActiveContext::Preprocessors::Embeddings
|
||||||
|
|
||||||
add_preprocessor :embeddings do |refs|
|
add_preprocessor :embeddings do |refs|
|
||||||
apply_embeddings(refs: refs, content_field: :other_field, content_method: :embedding_content)
|
apply_embeddings(refs: refs, content_field: :other_field, content_method: :embedding_content,
|
||||||
|
unit_primitive: 'test_unit_primitive')
|
||||||
end
|
end
|
||||||
|
|
||||||
def embedding_content
|
def embedding_content
|
||||||
|
@ -172,7 +175,7 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
|
|
||||||
it 'generates and sets embeddings for each document' do
|
it 'generates and sets embeddings for each document' do
|
||||||
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
||||||
.once.with(['Some other content'], model: nil).and_return([vectors])
|
.once.with(['Some other content'], model: nil, unit_primitive: unit_primitive).and_return([vectors])
|
||||||
|
|
||||||
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
||||||
end
|
end
|
||||||
|
@ -195,7 +198,7 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
|
|
||||||
it 'generates and sets embeddings for each document' do
|
it 'generates and sets embeddings for each document' do
|
||||||
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
||||||
.once.with(['Some content'], model: nil).and_return([vectors])
|
.once.with(['Some content'], model: nil, unit_primitive: unit_primitive).and_return([vectors])
|
||||||
|
|
||||||
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
||||||
end
|
end
|
||||||
|
@ -207,8 +210,8 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
include ::ActiveContext::Preprocessors::Embeddings
|
include ::ActiveContext::Preprocessors::Embeddings
|
||||||
|
|
||||||
add_preprocessor :embeddings do |refs|
|
add_preprocessor :embeddings do |refs|
|
||||||
apply_embeddings(refs: refs, content_field: :other_field,
|
apply_embeddings(refs: refs, content_field: :other_field, content_method: :embedding_content,
|
||||||
content_method: :embedding_content, remove_content: false)
|
remove_content: false, unit_primitive: 'test_unit_primitive')
|
||||||
end
|
end
|
||||||
|
|
||||||
def embedding_content
|
def embedding_content
|
||||||
|
@ -236,7 +239,8 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
include ::ActiveContext::Preprocessors::Embeddings
|
include ::ActiveContext::Preprocessors::Embeddings
|
||||||
|
|
||||||
add_preprocessor :embeddings do |refs|
|
add_preprocessor :embeddings do |refs|
|
||||||
apply_embeddings(refs: refs, content_method: :embedding_content)
|
apply_embeddings(refs: refs, content_method: :embedding_content,
|
||||||
|
unit_primitive: 'test_unit_primitive')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -258,7 +262,7 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
include ::ActiveContext::Preprocessors::Embeddings
|
include ::ActiveContext::Preprocessors::Embeddings
|
||||||
|
|
||||||
add_preprocessor :embeddings do |refs|
|
add_preprocessor :embeddings do |refs|
|
||||||
apply_embeddings(refs: refs)
|
apply_embeddings(refs: refs, unit_primitive: 'test_unit_primitive')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -288,7 +292,7 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
|
|
||||||
it 'generates and sets embeddings for each document' do
|
it 'generates and sets embeddings for each document' do
|
||||||
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
||||||
.once.with(['Other content'], model: nil).and_return([vectors])
|
.once.with(['Other content'], model: nil, unit_primitive: unit_primitive).and_return([vectors])
|
||||||
|
|
||||||
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
||||||
end
|
end
|
||||||
|
@ -315,7 +319,8 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
include ::ActiveContext::Preprocessors::Embeddings
|
include ::ActiveContext::Preprocessors::Embeddings
|
||||||
|
|
||||||
add_preprocessor :embeddings do |refs|
|
add_preprocessor :embeddings do |refs|
|
||||||
apply_embeddings(refs: refs, content_field: :other_field)
|
apply_embeddings(refs: refs, content_field: :other_field,
|
||||||
|
unit_primitive: 'test_unit_primitive')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -331,7 +336,7 @@ RSpec.describe ActiveContext::Preprocessors::Embeddings do
|
||||||
|
|
||||||
it 'generates and sets embeddings for each document' do
|
it 'generates and sets embeddings for each document' do
|
||||||
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
expect(ActiveContext::Embeddings).to receive(:generate_embeddings)
|
||||||
.once.with(['Some other content'], model: nil).and_return([vectors])
|
.once.with(['Some other content'], model: nil, unit_primitive: unit_primitive).and_return([vectors])
|
||||||
|
|
||||||
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
expect(preprocessed_reference.documents).to match_array([{ embedding: vectors }])
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
variables:
|
variables:
|
||||||
DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.128.0'
|
DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.130.0'
|
||||||
|
|
||||||
.dast-auto-deploy:
|
.dast-auto-deploy:
|
||||||
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${DAST_AUTO_DEPLOY_IMAGE_VERSION}"
|
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${DAST_AUTO_DEPLOY_IMAGE_VERSION}"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
variables:
|
variables:
|
||||||
AUTO_DEPLOY_IMAGE_VERSION: 'v2.128.0'
|
AUTO_DEPLOY_IMAGE_VERSION: 'v2.130.0'
|
||||||
|
|
||||||
.auto-deploy:
|
.auto-deploy:
|
||||||
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
|
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
variables:
|
variables:
|
||||||
AUTO_DEPLOY_IMAGE_VERSION: 'v2.128.0'
|
AUTO_DEPLOY_IMAGE_VERSION: 'v2.130.0'
|
||||||
|
|
||||||
.auto-deploy:
|
.auto-deploy:
|
||||||
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
|
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Gitlab
|
||||||
|
module Usage
|
||||||
|
module Metrics
|
||||||
|
module Instrumentations
|
||||||
|
class CountTopLevelGroupsMetric < DatabaseMetric
|
||||||
|
operation :count, column: :id
|
||||||
|
|
||||||
|
relation { Group.top_level }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,7 +3,7 @@
|
||||||
namespace :gitlab do
|
namespace :gitlab do
|
||||||
namespace :db do
|
namespace :db do
|
||||||
namespace :truncate_legacy_tables do
|
namespace :truncate_legacy_tables do
|
||||||
desc "GitLab | DB | Truncate CI Tables on Main"
|
desc "GitLab | DB | Truncate Legacy Tables on Main"
|
||||||
task :main, [:min_batch_size] => [:environment, 'gitlab:db:validate_config'] do |_t, args|
|
task :main, [:min_batch_size] => [:environment, 'gitlab:db:validate_config'] do |_t, args|
|
||||||
args.with_defaults(min_batch_size: 5)
|
args.with_defaults(min_batch_size: 5)
|
||||||
Gitlab::Database::TablesTruncate.new(
|
Gitlab::Database::TablesTruncate.new(
|
||||||
|
@ -15,7 +15,7 @@ namespace :gitlab do
|
||||||
).execute
|
).execute
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "GitLab | DB | Truncate Main Tables on CI"
|
desc "GitLab | DB | Truncate Legacy Tables on CI"
|
||||||
task :ci, [:min_batch_size] => [:environment, 'gitlab:db:validate_config'] do |_t, args|
|
task :ci, [:min_batch_size] => [:environment, 'gitlab:db:validate_config'] do |_t, args|
|
||||||
args.with_defaults(min_batch_size: 5)
|
args.with_defaults(min_batch_size: 5)
|
||||||
Gitlab::Database::TablesTruncate.new(
|
Gitlab::Database::TablesTruncate.new(
|
||||||
|
@ -26,6 +26,18 @@ namespace :gitlab do
|
||||||
until_table: ENV['UNTIL_TABLE']
|
until_table: ENV['UNTIL_TABLE']
|
||||||
).execute
|
).execute
|
||||||
end
|
end
|
||||||
|
|
||||||
|
desc "GitLab | DB | Truncate Legacy Tables on Sec"
|
||||||
|
task :sec, [:min_batch_size] => [:environment, 'gitlab:db:validate_config'] do |_t, args|
|
||||||
|
args.with_defaults(min_batch_size: 5)
|
||||||
|
Gitlab::Database::TablesTruncate.new(
|
||||||
|
database_name: 'sec',
|
||||||
|
min_batch_size: args.min_batch_size.to_i,
|
||||||
|
logger: Logger.new($stdout),
|
||||||
|
dry_run: ENV['DRY_RUN'] == 'true',
|
||||||
|
until_table: ENV['UNTIL_TABLE']
|
||||||
|
).execute
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -28375,6 +28375,9 @@ msgstr ""
|
||||||
msgid "GitLabPages|DNS check unsuccessful"
|
msgid "GitLabPages|DNS check unsuccessful"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "GitLabPages|Delete Pages"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "GitLabPages|Domain ownership verification required. Add a TXT record to verify ownership at your domain provider."
|
msgid "GitLabPages|Domain ownership verification required. Add a TXT record to verify ownership at your domain provider."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -28405,7 +28408,7 @@ msgstr ""
|
||||||
msgid "GitLabPages|New domain"
|
msgid "GitLabPages|New domain"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "GitLabPages|Only project maintainers can remove pages"
|
msgid "GitLabPages|Only project maintainers can remove pages."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "GitLabPages|Pages"
|
msgid "GitLabPages|Pages"
|
||||||
|
@ -28429,9 +28432,6 @@ msgstr ""
|
||||||
msgid "GitLabPages|Remove pages"
|
msgid "GitLabPages|Remove pages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "GitLabPages|Removing pages will prevent them from being exposed to the public internet."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "GitLabPages|Restrict access to only project members on all group projects"
|
msgid "GitLabPages|Restrict access to only project members on all group projects"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -28447,6 +28447,12 @@ msgstr ""
|
||||||
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your GitLab administrator to enable it."
|
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your GitLab administrator to enable it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "GitLabPages|This action will permanently delete all Pages deployments."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "GitLabPages|This is permanent and cannot be undone. To deploy this Pages site again, run a new pipeline."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "GitLabPages|Updating your Pages configuration…"
|
msgid "GitLabPages|Updating your Pages configuration…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -43224,7 +43230,10 @@ msgstr ""
|
||||||
msgid "Owasp|A9:2017 Using Components with Known Vulnerabilities"
|
msgid "Owasp|A9:2017 Using Components with Known Vulnerabilities"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Owasp|Non-OWASP Top 10"
|
msgid "Owasp|Non-OWASP Top 10 2017"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Owasp|Non-OWASP Top 10 2021"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Owned by %{image_tag}"
|
msgid "Owned by %{image_tag}"
|
||||||
|
|
76
package.json
76
package.json
|
@ -56,7 +56,7 @@
|
||||||
"@babel/preset-env": "^7.23.7",
|
"@babel/preset-env": "^7.23.7",
|
||||||
"@csstools/postcss-global-data": "^2.1.1",
|
"@csstools/postcss-global-data": "^2.1.1",
|
||||||
"@cubejs-client/core": "^1.0.0",
|
"@cubejs-client/core": "^1.0.0",
|
||||||
"@floating-ui/dom": "^1.6.13",
|
"@floating-ui/dom": "^1.7.0",
|
||||||
"@gitlab/application-sdk-browser": "^0.3.4",
|
"@gitlab/application-sdk-browser": "^0.3.4",
|
||||||
"@gitlab/at.js": "1.5.7",
|
"@gitlab/at.js": "1.5.7",
|
||||||
"@gitlab/cluster-client": "^3.0.0",
|
"@gitlab/cluster-client": "^3.0.0",
|
||||||
|
@ -82,41 +82,41 @@
|
||||||
"@snowplow/browser-plugin-timezone": "^3.24.2",
|
"@snowplow/browser-plugin-timezone": "^3.24.2",
|
||||||
"@snowplow/browser-tracker": "^3.24.2",
|
"@snowplow/browser-tracker": "^3.24.2",
|
||||||
"@sourcegraph/code-host-integration": "0.0.95",
|
"@sourcegraph/code-host-integration": "0.0.95",
|
||||||
"@tiptap/core": "^2.11.7",
|
"@tiptap/core": "^2.12.0",
|
||||||
"@tiptap/extension-blockquote": "^2.11.7",
|
"@tiptap/extension-blockquote": "^2.12.0",
|
||||||
"@tiptap/extension-bold": "^2.11.7",
|
"@tiptap/extension-bold": "^2.12.0",
|
||||||
"@tiptap/extension-bubble-menu": "^2.11.7",
|
"@tiptap/extension-bubble-menu": "^2.12.0",
|
||||||
"@tiptap/extension-bullet-list": "^2.11.7",
|
"@tiptap/extension-bullet-list": "^2.12.0",
|
||||||
"@tiptap/extension-code": "^2.11.7",
|
"@tiptap/extension-code": "^2.12.0",
|
||||||
"@tiptap/extension-code-block": "^2.11.7",
|
"@tiptap/extension-code-block": "^2.12.0",
|
||||||
"@tiptap/extension-code-block-lowlight": "^2.11.7",
|
"@tiptap/extension-code-block-lowlight": "^2.12.0",
|
||||||
"@tiptap/extension-document": "^2.11.7",
|
"@tiptap/extension-document": "^2.12.0",
|
||||||
"@tiptap/extension-dropcursor": "^2.11.7",
|
"@tiptap/extension-dropcursor": "^2.12.0",
|
||||||
"@tiptap/extension-gapcursor": "^2.11.7",
|
"@tiptap/extension-gapcursor": "^2.12.0",
|
||||||
"@tiptap/extension-hard-break": "^2.11.7",
|
"@tiptap/extension-hard-break": "^2.12.0",
|
||||||
"@tiptap/extension-heading": "^2.11.7",
|
"@tiptap/extension-heading": "^2.12.0",
|
||||||
"@tiptap/extension-highlight": "^2.11.7",
|
"@tiptap/extension-highlight": "^2.12.0",
|
||||||
"@tiptap/extension-history": "^2.11.7",
|
"@tiptap/extension-history": "^2.12.0",
|
||||||
"@tiptap/extension-horizontal-rule": "^2.11.7",
|
"@tiptap/extension-horizontal-rule": "^2.12.0",
|
||||||
"@tiptap/extension-image": "^2.11.7",
|
"@tiptap/extension-image": "^2.12.0",
|
||||||
"@tiptap/extension-italic": "^2.11.7",
|
"@tiptap/extension-italic": "^2.12.0",
|
||||||
"@tiptap/extension-link": "^2.11.7",
|
"@tiptap/extension-link": "^2.12.0",
|
||||||
"@tiptap/extension-list-item": "^2.11.7",
|
"@tiptap/extension-list-item": "^2.12.0",
|
||||||
"@tiptap/extension-ordered-list": "^2.11.7",
|
"@tiptap/extension-ordered-list": "^2.12.0",
|
||||||
"@tiptap/extension-paragraph": "^2.11.7",
|
"@tiptap/extension-paragraph": "^2.12.0",
|
||||||
"@tiptap/extension-strike": "^2.11.7",
|
"@tiptap/extension-strike": "^2.12.0",
|
||||||
"@tiptap/extension-subscript": "^2.11.7",
|
"@tiptap/extension-subscript": "^2.12.0",
|
||||||
"@tiptap/extension-superscript": "^2.11.7",
|
"@tiptap/extension-superscript": "^2.12.0",
|
||||||
"@tiptap/extension-table": "^2.11.7",
|
"@tiptap/extension-table": "^2.12.0",
|
||||||
"@tiptap/extension-table-cell": "^2.11.7",
|
"@tiptap/extension-table-cell": "^2.12.0",
|
||||||
"@tiptap/extension-table-header": "^2.11.7",
|
"@tiptap/extension-table-header": "^2.12.0",
|
||||||
"@tiptap/extension-table-row": "^2.11.7",
|
"@tiptap/extension-table-row": "^2.12.0",
|
||||||
"@tiptap/extension-task-item": "^2.11.7",
|
"@tiptap/extension-task-item": "^2.12.0",
|
||||||
"@tiptap/extension-task-list": "^2.11.7",
|
"@tiptap/extension-task-list": "^2.12.0",
|
||||||
"@tiptap/extension-text": "^2.11.7",
|
"@tiptap/extension-text": "^2.12.0",
|
||||||
"@tiptap/pm": "^2.11.7",
|
"@tiptap/pm": "^2.12.0",
|
||||||
"@tiptap/suggestion": "^2.11.7",
|
"@tiptap/suggestion": "^2.12.0",
|
||||||
"@tiptap/vue-2": "^2.11.7",
|
"@tiptap/vue-2": "^2.12.0",
|
||||||
"@vue/apollo-components": "^4.0.0-beta.4",
|
"@vue/apollo-components": "^4.0.0-beta.4",
|
||||||
"@vue/apollo-option": "^4.0.0-beta.4",
|
"@vue/apollo-option": "^4.0.0-beta.4",
|
||||||
"apollo-upload-client": "15.0.0",
|
"apollo-upload-client": "15.0.0",
|
||||||
|
@ -251,7 +251,7 @@
|
||||||
"@gitlab/eslint-plugin": "20.7.1",
|
"@gitlab/eslint-plugin": "20.7.1",
|
||||||
"@gitlab/noop": "^1.0.1",
|
"@gitlab/noop": "^1.0.1",
|
||||||
"@gitlab/stylelint-config": "6.2.2",
|
"@gitlab/stylelint-config": "6.2.2",
|
||||||
"@graphql-eslint/eslint-plugin": "3.20.1",
|
"@graphql-eslint/eslint-plugin": "4.4.0",
|
||||||
"@originjs/vite-plugin-commonjs": "^1.0.3",
|
"@originjs/vite-plugin-commonjs": "^1.0.3",
|
||||||
"@pinia/testing": "^0.1.5",
|
"@pinia/testing": "^0.1.5",
|
||||||
"@rollup/plugin-graphql": "^2.0.5",
|
"@rollup/plugin-graphql": "^2.0.5",
|
||||||
|
@ -277,7 +277,7 @@
|
||||||
"custom-jquery-matchers": "^2.1.0",
|
"custom-jquery-matchers": "^2.1.0",
|
||||||
"dependency-cruiser": "^16.9.0",
|
"dependency-cruiser": "^16.9.0",
|
||||||
"eslint": "9.25.1",
|
"eslint": "9.25.1",
|
||||||
"eslint-formatter-gitlab": "^5.1.0",
|
"eslint-formatter-gitlab": "^6.0.0",
|
||||||
"eslint-import-resolver-jest": "3.0.2",
|
"eslint-import-resolver-jest": "3.0.2",
|
||||||
"eslint-import-resolver-webpack": "0.13.10",
|
"eslint-import-resolver-webpack": "0.13.10",
|
||||||
"eslint-plugin-import": "^2.31.0",
|
"eslint-plugin-import": "^2.31.0",
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
diff --git a/node_modules/@graphql-eslint/eslint-plugin/cjs/utils.js b/node_modules/@graphql-eslint/eslint-plugin/cjs/utils.js
|
|
||||||
index bd7f92a..1ee1ca1 100644
|
|
||||||
--- a/node_modules/@graphql-eslint/eslint-plugin/cjs/utils.js
|
|
||||||
+++ b/node_modules/@graphql-eslint/eslint-plugin/cjs/utils.js
|
|
||||||
@@ -52,7 +52,7 @@ var import_chalk = __toESM(require("chalk"));
|
|
||||||
var import_graphql = require("graphql");
|
|
||||||
var import_lodash = __toESM(require("lodash.lowercase"));
|
|
||||||
function requireSiblingsOperations(ruleId, context) {
|
|
||||||
- const { siblingOperations } = context.parserServices;
|
|
||||||
+ const { siblingOperations } = context.sourceCode.parserServices;
|
|
||||||
if (!siblingOperations.available) {
|
|
||||||
throw new Error(
|
|
||||||
`Rule \`${ruleId}\` requires \`parserOptions.operations\` to be set and loaded. See https://bit.ly/graphql-eslint-operations for more info`
|
|
||||||
@@ -61,7 +61,7 @@ function requireSiblingsOperations(ruleId, context) {
|
|
||||||
return siblingOperations;
|
|
||||||
}
|
|
||||||
function requireGraphQLSchemaFromContext(ruleId, context) {
|
|
||||||
- const { schema } = context.parserServices;
|
|
||||||
+ const { schema } = context.sourceCode.parserServices;
|
|
||||||
if (!schema) {
|
|
||||||
throw new Error(
|
|
||||||
`Rule \`${ruleId}\` requires \`parserOptions.schema\` to be set and loaded. See https://bit.ly/graphql-eslint-schema for more info`
|
|
|
@ -85,7 +85,7 @@ RSpec.describe '1_settings', feature_category: :shared do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when legacy topology service config is provided' do
|
context 'when legacy topology service client config is provided as a top-level key' do
|
||||||
before do
|
before do
|
||||||
stub_config({ cell: { enabled: true, id: 1 }, topology_service: config })
|
stub_config({ cell: { enabled: true, id: 1 }, topology_service: config })
|
||||||
load_settings
|
load_settings
|
||||||
|
@ -96,6 +96,18 @@ RSpec.describe '1_settings', feature_category: :shared do
|
||||||
it { expect(Settings.cell.topology_service_client.certificate_file).to eq(config[:certificate_file]) }
|
it { expect(Settings.cell.topology_service_client.certificate_file).to eq(config[:certificate_file]) }
|
||||||
it { expect(Settings.cell.topology_service_client.private_key_file).to eq(config[:private_key_file]) }
|
it { expect(Settings.cell.topology_service_client.private_key_file).to eq(config[:private_key_file]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when topology service client config is provided as a key nested' do
|
||||||
|
before do
|
||||||
|
stub_config({ cell: { enabled: true, id: 1, topology_service_client: config } })
|
||||||
|
load_settings
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(Settings.cell.topology_service_client.address).to eq(config[:address]) }
|
||||||
|
it { expect(Settings.cell.topology_service_client.ca_file).to eq(config[:ca_file]) }
|
||||||
|
it { expect(Settings.cell.topology_service_client.certificate_file).to eq(config[:certificate_file]) }
|
||||||
|
it { expect(Settings.cell.topology_service_client.private_key_file).to eq(config[:private_key_file]) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'Pages custom domains settings' do
|
describe 'Pages custom domains settings' do
|
||||||
|
|
|
@ -121,7 +121,7 @@ RSpec.describe 'validate database config', feature_category: :cell do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'raises exception about missing topology service client config' do
|
it 'raises exception about missing topology service client config' do
|
||||||
expect { validate_config }.to raise_error("Topology Service setting 'address' is not set.#{dev_message}")
|
expect { validate_config }.to raise_error("Topology Service Client setting 'address' is not set.#{dev_message}")
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'with SKIP_CELL_CONFIG_VALIDATION=true'
|
it_behaves_like 'with SKIP_CELL_CONFIG_VALIDATION=true'
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountTopLevelGroupsMetric, feature_category: :groups_and_projects do
|
||||||
|
let_it_be(:top_level_group) { create(:group) }
|
||||||
|
let_it_be(:subgroup) { create(:group, :nested) }
|
||||||
|
let_it_be(:project_in_group_namespace) { create(:project, group: subgroup) }
|
||||||
|
let_it_be(:project_in_user_namespace) { create(:project) }
|
||||||
|
let(:expected_value) { 2 }
|
||||||
|
|
||||||
|
it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database' }
|
||||||
|
end
|
|
@ -106,6 +106,19 @@ RSpec.describe Approvable do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#approvals_for_user_ids' do
|
||||||
|
let_it_be(:user) { create(:user) }
|
||||||
|
let_it_be(:merge_request) { create(:merge_request) }
|
||||||
|
let_it_be(:approval) { create(:approval, merge_request: merge_request, user: user) }
|
||||||
|
let_it_be(:approval2) { create(:approval, merge_request: merge_request, user: create(:user)) }
|
||||||
|
|
||||||
|
subject(:approvals) { merge_request.approvals_for_user_ids([user.id]) }
|
||||||
|
|
||||||
|
it 'returns approvals by user' do
|
||||||
|
is_expected.to contain_exactly(approval)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '.not_approved_by_users_with_usernames' do
|
describe '.not_approved_by_users_with_usernames' do
|
||||||
subject { MergeRequest.not_approved_by_users_with_usernames([user.username, user2.username]) }
|
subject { MergeRequest.not_approved_by_users_with_usernames([user.username, user2.username]) }
|
||||||
|
|
||||||
|
|
|
@ -59,5 +59,41 @@ RSpec.describe WorkItems::UserPreference, type: :model, feature_category: :team_
|
||||||
MESSAGE
|
MESSAGE
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'validate display_settings' do
|
||||||
|
before do
|
||||||
|
allow(WorkItems::SortingKeys).to receive(:available?).and_return(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is valid with an empty display settings hash' do
|
||||||
|
preferences = described_class.new(namespace: namespace, display_settings: {})
|
||||||
|
|
||||||
|
expect(preferences).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid with properties not defined in the schema' do
|
||||||
|
invalid_display_settings = { 'invalidProperty' => 'some_value' }
|
||||||
|
preferences = described_class.new(namespace: namespace, display_settings: invalid_display_settings)
|
||||||
|
|
||||||
|
expect(preferences).not_to be_valid
|
||||||
|
expect(preferences.errors[:display_settings]).to include('must be a valid json schema')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is valid with a valid display_settings hash' do
|
||||||
|
valid_display_settings = { 'shouldOpenItemsInSidePanel' => true }
|
||||||
|
preferences = described_class.new(namespace: namespace, display_settings: valid_display_settings)
|
||||||
|
|
||||||
|
expect(preferences).to be_valid
|
||||||
|
expect(preferences.display_settings).to eq(valid_display_settings)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid with a wrong type as per schema validation' do
|
||||||
|
invalid_display_settings = { 'shouldOpenItemsInSidePanel' => 'string_type' }
|
||||||
|
preferences = described_class.new(namespace: namespace, display_settings: invalid_display_settings)
|
||||||
|
|
||||||
|
expect(preferences).not_to be_valid
|
||||||
|
expect(preferences.errors[:display_settings]).to include('must be a valid json schema')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -31,5 +31,13 @@ RSpec.describe 'Updating an existing HTTP Integration', feature_category: :incid
|
||||||
|
|
||||||
let(:mutation_response) { graphql_mutation_response(:http_integration_update) }
|
let(:mutation_response) { graphql_mutation_response(:http_integration_update) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow_unlimited_graphql_complexity
|
||||||
|
allow_unlimited_graphql_depth
|
||||||
|
allow_unlimited_validation_timeout
|
||||||
|
# Optional, if you suspect recursion issues, though less common for timeouts:
|
||||||
|
# allow_high_graphql_recursion
|
||||||
|
end
|
||||||
|
|
||||||
it_behaves_like 'updating an existing HTTP integration'
|
it_behaves_like 'updating an existing HTTP integration'
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,12 +10,14 @@ RSpec.describe 'Update work items user preferences', feature_category: :team_pla
|
||||||
let_it_be(:work_item_type) { WorkItems::Type.default_by_type(:incident) }
|
let_it_be(:work_item_type) { WorkItems::Type.default_by_type(:incident) }
|
||||||
|
|
||||||
let(:sorting_value) { 'CREATED_ASC' }
|
let(:sorting_value) { 'CREATED_ASC' }
|
||||||
|
let(:display_settings) { { 'shouldOpenItemsInSidePanel' => true } }
|
||||||
|
|
||||||
let(:input) do
|
let(:input) do
|
||||||
{
|
{
|
||||||
namespacePath: namespace.full_path,
|
namespacePath: namespace.full_path,
|
||||||
workItemTypeId: work_item_type&.to_gid,
|
workItemTypeId: work_item_type&.to_gid,
|
||||||
sort: sorting_value
|
sort: sorting_value,
|
||||||
|
displaySettings: display_settings
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -30,6 +32,7 @@ RSpec.describe 'Update work items user preferences', feature_category: :team_pla
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
sort
|
sort
|
||||||
|
displaySettings
|
||||||
}
|
}
|
||||||
FIELDS
|
FIELDS
|
||||||
end
|
end
|
||||||
|
@ -66,7 +69,8 @@ RSpec.describe 'Update work items user preferences', feature_category: :team_pla
|
||||||
'workItemType' => {
|
'workItemType' => {
|
||||||
'name' => work_item_type.name
|
'name' => work_item_type.name
|
||||||
},
|
},
|
||||||
'sort' => sorting_value
|
'sort' => sorting_value,
|
||||||
|
'displaySettings' => display_settings
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -74,7 +78,8 @@ RSpec.describe 'Update work items user preferences', feature_category: :team_pla
|
||||||
let(:input) do
|
let(:input) do
|
||||||
{
|
{
|
||||||
namespacePath: namespace.full_path,
|
namespacePath: namespace.full_path,
|
||||||
sort: sorting_value
|
sort: sorting_value,
|
||||||
|
displaySettings: display_settings
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -89,7 +94,8 @@ RSpec.describe 'Update work items user preferences', feature_category: :team_pla
|
||||||
'path' => namespace.path
|
'path' => namespace.path
|
||||||
},
|
},
|
||||||
'workItemType' => nil,
|
'workItemType' => nil,
|
||||||
'sort' => sorting_value
|
'sort' => sorting_value,
|
||||||
|
'displaySettings' => display_settings
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -109,6 +115,20 @@ RSpec.describe 'Update work items user preferences', feature_category: :team_pla
|
||||||
expect(mutation_response['userPreferences']).to be_nil
|
expect(mutation_response['userPreferences']).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when display settings are not valid' do
|
||||||
|
let_it_be(:display_settings) { { 'shouldOpenItemsInSidePanel' => 'test' } }
|
||||||
|
|
||||||
|
it 'updates the user preferences successfully' do
|
||||||
|
post_graphql_mutation(mutation, current_user: user)
|
||||||
|
expect(response).to have_gitlab_http_status(:success)
|
||||||
|
expect(graphql_errors).to be_blank
|
||||||
|
expect(mutation_response['errors']).to include(
|
||||||
|
'Display settings must be a valid json schema'
|
||||||
|
)
|
||||||
|
expect(mutation_response['userPreferences']).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -307,6 +307,14 @@ RSpec.describe MergeRequests::UpdateService, :mailer, feature_category: :code_re
|
||||||
|
|
||||||
update_merge_request(reviewer_ids: [user.id])
|
update_merge_request(reviewer_ids: [user.id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'sets reviewer state as approved if user has previously approved' do
|
||||||
|
create(:approval, merge_request: merge_request, user: user)
|
||||||
|
|
||||||
|
update_merge_request(reviewer_ids: [user.id])
|
||||||
|
|
||||||
|
expect(merge_request.find_reviewer(user)).to be_approved
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'creates a resource label event' do
|
it 'creates a resource label event' do
|
||||||
|
|
|
@ -6,8 +6,18 @@ RSpec.describe 'gitlab:db:truncate_legacy_tables', :silence_stdout, :reestablish
|
||||||
:suppress_gitlab_schemas_validate_connection, feature_category: :cell do
|
:suppress_gitlab_schemas_validate_connection, feature_category: :cell do
|
||||||
let(:main_connection) { ApplicationRecord.connection }
|
let(:main_connection) { ApplicationRecord.connection }
|
||||||
let(:ci_connection) { Ci::ApplicationRecord.connection }
|
let(:ci_connection) { Ci::ApplicationRecord.connection }
|
||||||
|
let(:sec_connection) { SecApplicationRecord.connection }
|
||||||
let(:test_gitlab_main_table) { '_test_gitlab_main_table' }
|
let(:test_gitlab_main_table) { '_test_gitlab_main_table' }
|
||||||
let(:test_gitlab_ci_table) { '_test_gitlab_ci_table' }
|
let(:test_gitlab_ci_table) { '_test_gitlab_ci_table' }
|
||||||
|
let(:test_gitlab_sec_table) { '_test_gitlab_sec_table' }
|
||||||
|
let(:databases) { %i[main ci] }
|
||||||
|
let(:tables_to_schema) do
|
||||||
|
{
|
||||||
|
test_gitlab_main_table => :gitlab_main,
|
||||||
|
test_gitlab_ci_table => :gitlab_ci,
|
||||||
|
test_gitlab_sec_table => :gitlab_main
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
before(:all) do
|
before(:all) do
|
||||||
Rake.application.rake_require 'active_record/railties/databases'
|
Rake.application.rake_require 'active_record/railties/databases'
|
||||||
|
@ -19,20 +29,21 @@ RSpec.describe 'gitlab:db:truncate_legacy_tables', :silence_stdout, :reestablish
|
||||||
before do
|
before do
|
||||||
skip_if_shared_database(:ci)
|
skip_if_shared_database(:ci)
|
||||||
|
|
||||||
execute_on_each_database(<<~SQL)
|
execute_on_each_database(<<~SQL, databases: databases)
|
||||||
CREATE TABLE #{test_gitlab_main_table} (id integer NOT NULL);
|
CREATE TABLE #{test_gitlab_main_table} (id integer NOT NULL);
|
||||||
INSERT INTO #{test_gitlab_main_table} VALUES(generate_series(1, 50));
|
INSERT INTO #{test_gitlab_main_table} VALUES(generate_series(1, 50));
|
||||||
SQL
|
SQL
|
||||||
execute_on_each_database(<<~SQL)
|
execute_on_each_database(<<~SQL, databases: databases)
|
||||||
CREATE TABLE #{test_gitlab_ci_table} (id integer NOT NULL);
|
CREATE TABLE #{test_gitlab_ci_table} (id integer NOT NULL);
|
||||||
INSERT INTO #{test_gitlab_ci_table} VALUES(generate_series(1, 50));
|
INSERT INTO #{test_gitlab_ci_table} VALUES(generate_series(1, 50));
|
||||||
SQL
|
SQL
|
||||||
|
execute_on_each_database(<<~SQL, databases: databases)
|
||||||
|
CREATE TABLE #{test_gitlab_sec_table} (id integer NOT NULL);
|
||||||
|
INSERT INTO #{test_gitlab_sec_table} VALUES(generate_series(1, 50));
|
||||||
|
SQL
|
||||||
|
|
||||||
allow(Gitlab::Database::GitlabSchema).to receive(:tables_to_schema).and_return(
|
allow(Gitlab::Database::GitlabSchema).to receive(:tables_to_schema).and_return(
|
||||||
{
|
tables_to_schema
|
||||||
test_gitlab_main_table => :gitlab_main,
|
|
||||||
test_gitlab_ci_table => :gitlab_ci
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -61,6 +72,40 @@ RSpec.describe 'gitlab:db:truncate_legacy_tables', :silence_stdout, :reestablish
|
||||||
database_name: "ci",
|
database_name: "ci",
|
||||||
with_retries: false
|
with_retries: false
|
||||||
).lock_writes
|
).lock_writes
|
||||||
|
|
||||||
|
# Locking sec table on the ci database
|
||||||
|
Gitlab::Database::LockWritesManager.new(
|
||||||
|
table_name: test_gitlab_sec_table,
|
||||||
|
connection: ci_connection,
|
||||||
|
database_name: "ci",
|
||||||
|
with_retries: false
|
||||||
|
).lock_writes
|
||||||
|
|
||||||
|
if database_exists?('sec')
|
||||||
|
# Locking sec table on the main database
|
||||||
|
Gitlab::Database::LockWritesManager.new(
|
||||||
|
table_name: test_gitlab_sec_table,
|
||||||
|
connection: main_connection,
|
||||||
|
database_name: "main",
|
||||||
|
with_retries: false
|
||||||
|
).lock_writes
|
||||||
|
|
||||||
|
# Locking ci table on the sec database
|
||||||
|
Gitlab::Database::LockWritesManager.new(
|
||||||
|
table_name: test_gitlab_ci_table,
|
||||||
|
connection: sec_connection,
|
||||||
|
database_name: "sec",
|
||||||
|
with_retries: false
|
||||||
|
).lock_writes
|
||||||
|
|
||||||
|
# Locking main table on the sec database
|
||||||
|
Gitlab::Database::LockWritesManager.new(
|
||||||
|
table_name: test_gitlab_main_table,
|
||||||
|
connection: sec_connection,
|
||||||
|
database_name: "sec",
|
||||||
|
with_retries: false
|
||||||
|
).lock_writes
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'calls TablesTruncate with the correct parameters and default minimum batch size' do
|
it 'calls TablesTruncate with the correct parameters and default minimum batch size' do
|
||||||
|
@ -75,10 +120,20 @@ RSpec.describe 'gitlab:db:truncate_legacy_tables', :silence_stdout, :reestablish
|
||||||
truncate_legacy_tables
|
truncate_legacy_tables
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'truncates the legacy table' do
|
it 'truncates the legacy tables' do
|
||||||
expect do
|
legacy_tables.each do |legacy_table|
|
||||||
truncate_legacy_tables
|
expect(
|
||||||
end.to change { connection.select_value("SELECT count(*) from #{legacy_table}") }.from(50).to(0)
|
connection.select_value("SELECT count(*) from #{legacy_table}")
|
||||||
|
).to eq(50)
|
||||||
|
end
|
||||||
|
|
||||||
|
truncate_legacy_tables
|
||||||
|
|
||||||
|
legacy_tables.each do |legacy_table|
|
||||||
|
expect(
|
||||||
|
connection.select_value("SELECT count(*) from #{legacy_table}")
|
||||||
|
).to eq(0)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not truncate the table that belongs to the connection schema' do
|
it 'does not truncate the table that belongs to the connection schema' do
|
||||||
|
@ -95,19 +150,23 @@ RSpec.describe 'gitlab:db:truncate_legacy_tables', :silence_stdout, :reestablish
|
||||||
it 'does not truncate any tables' do
|
it 'does not truncate any tables' do
|
||||||
expect do
|
expect do
|
||||||
truncate_legacy_tables
|
truncate_legacy_tables
|
||||||
end.not_to change { connection.select_value("SELECT count(*) from #{legacy_table}") }
|
end.not_to change {
|
||||||
|
legacy_tables.map do |legacy_table|
|
||||||
|
connection.select_value("SELECT count(*) from #{legacy_table}")
|
||||||
|
end
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'prints the truncation sql statement to the output' do
|
it 'prints the truncation sql statement to the output' do
|
||||||
expect do
|
expect do
|
||||||
truncate_legacy_tables
|
truncate_legacy_tables
|
||||||
end.to output(/TRUNCATE TABLE #{legacy_table} RESTRICT/).to_stdout
|
end.to output(/TRUNCATE TABLE #{legacy_tables.join(', ')} RESTRICT/).to_stdout
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when passing until_table parameter via environment variable' do
|
context 'when passing until_table parameter via environment variable' do
|
||||||
before do
|
before do
|
||||||
stub_env('UNTIL_TABLE', legacy_table)
|
stub_env('UNTIL_TABLE', legacy_tables.first)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sends the table name to TablesTruncate' do
|
it 'sends the table name to TablesTruncate' do
|
||||||
|
@ -116,7 +175,7 @@ RSpec.describe 'gitlab:db:truncate_legacy_tables', :silence_stdout, :reestablish
|
||||||
min_batch_size: 5,
|
min_batch_size: 5,
|
||||||
logger: anything,
|
logger: anything,
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
until_table: legacy_table
|
until_table: legacy_tables.first
|
||||||
).and_call_original
|
).and_call_original
|
||||||
|
|
||||||
truncate_legacy_tables
|
truncate_legacy_tables
|
||||||
|
@ -131,18 +190,55 @@ RSpec.describe 'gitlab:db:truncate_legacy_tables', :silence_stdout, :reestablish
|
||||||
let(:connection) { ApplicationRecord.connection }
|
let(:connection) { ApplicationRecord.connection }
|
||||||
let(:database_name) { 'main' }
|
let(:database_name) { 'main' }
|
||||||
let(:active_table) { test_gitlab_main_table }
|
let(:active_table) { test_gitlab_main_table }
|
||||||
let(:legacy_table) { test_gitlab_ci_table }
|
let(:legacy_tables) { [test_gitlab_ci_table] }
|
||||||
|
|
||||||
it_behaves_like 'truncating legacy tables'
|
it_behaves_like 'truncating legacy tables'
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when truncating main tables on the ci database' do
|
context 'when truncating main tables on the ci database' do
|
||||||
subject(:truncate_legacy_tables) { run_rake_task('gitlab:db:truncate_legacy_tables:ci') }
|
subject(:truncate_legacy_tables) do
|
||||||
|
# These are purposefully cross-DB to properly test multi-schema truncation
|
||||||
|
Gitlab::Database.allow_cross_joins_across_databases(
|
||||||
|
url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/189237'
|
||||||
|
) do
|
||||||
|
run_rake_task('gitlab:db:truncate_legacy_tables:ci')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
let(:connection) { Ci::ApplicationRecord.connection }
|
let(:connection) { Ci::ApplicationRecord.connection }
|
||||||
let(:database_name) { 'ci' }
|
let(:database_name) { 'ci' }
|
||||||
let(:active_table) { test_gitlab_ci_table }
|
let(:active_table) { test_gitlab_ci_table }
|
||||||
let(:legacy_table) { test_gitlab_main_table }
|
let(:legacy_tables) { [test_gitlab_main_table, test_gitlab_sec_table] }
|
||||||
|
|
||||||
|
it_behaves_like 'truncating legacy tables'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when truncating both ci and main tables on the sec database' do
|
||||||
|
subject(:truncate_legacy_tables) do
|
||||||
|
# These are purposefully cross-DB to properly test multi-schema truncation
|
||||||
|
Gitlab::Database.allow_cross_joins_across_databases(
|
||||||
|
url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/189237'
|
||||||
|
) do
|
||||||
|
run_rake_task('gitlab:db:truncate_legacy_tables:sec')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:connection) { SecApplicationRecord.connection }
|
||||||
|
let(:database_name) { 'sec' }
|
||||||
|
let(:active_table) { test_gitlab_sec_table }
|
||||||
|
let(:legacy_tables) { [test_gitlab_ci_table, test_gitlab_main_table] }
|
||||||
|
let(:databases) { %i[ci main sec] }
|
||||||
|
let(:tables_to_schema) do
|
||||||
|
{
|
||||||
|
test_gitlab_main_table => :gitlab_main,
|
||||||
|
test_gitlab_ci_table => :gitlab_ci,
|
||||||
|
test_gitlab_sec_table => :gitlab_sec
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
skip unless database_exists?(:sec)
|
||||||
|
end
|
||||||
|
|
||||||
it_behaves_like 'truncating legacy tables'
|
it_behaves_like 'truncating legacy tables'
|
||||||
end
|
end
|
||||||
|
|
|
@ -72,7 +72,8 @@ RSpec.describe CI::ChangedFiles, feature_category: :tooling do
|
||||||
|
|
||||||
describe '#run_eslint_for_changed_files' do
|
describe '#run_eslint_for_changed_files' do
|
||||||
let(:eslint_command) do
|
let(:eslint_command) do
|
||||||
['yarn', 'run', 'lint:eslint', '--no-warn-ignored', '--format', 'gitlab', 'file1.js', 'file2.vue']
|
['yarn', 'run', 'lint:eslint', '--no-warn-ignored', '--no-error-on-unmatched-pattern', '--format', 'gitlab',
|
||||||
|
'file1.js', 'file2.vue']
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:console_message) { /Running ESLint for changed files.../i }
|
let(:console_message) { /Running ESLint for changed files.../i }
|
||||||
|
@ -120,7 +121,7 @@ RSpec.describe CI::ChangedFiles, feature_category: :tooling do
|
||||||
|
|
||||||
context 'when a single todo file has been changed' do
|
context 'when a single todo file has been changed' do
|
||||||
let(:eslint_command) do
|
let(:eslint_command) do
|
||||||
['yarn', 'run', 'lint:eslint', '--no-warn-ignored', '--format', 'gitlab',
|
['yarn', 'run', 'lint:eslint', '--no-warn-ignored', '--no-error-on-unmatched-pattern', '--format', 'gitlab',
|
||||||
'.eslint_todo/vue-no-unused-properties.mjs',
|
'.eslint_todo/vue-no-unused-properties.mjs',
|
||||||
'app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue',
|
'app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue',
|
||||||
'app/assets/javascripts/admin/abuse_report/components/notes/abuse_report_comment_form.vue',
|
'app/assets/javascripts/admin/abuse_report/components/notes/abuse_report_comment_form.vue',
|
||||||
|
@ -174,7 +175,7 @@ RSpec.describe CI::ChangedFiles, feature_category: :tooling do
|
||||||
|
|
||||||
context 'when several todo files have been changed' do
|
context 'when several todo files have been changed' do
|
||||||
let(:eslint_command) do
|
let(:eslint_command) do
|
||||||
['yarn', 'run', 'lint:eslint', '--no-warn-ignored', '--format', 'gitlab',
|
['yarn', 'run', 'lint:eslint', '--no-warn-ignored', '--no-error-on-unmatched-pattern', '--format', 'gitlab',
|
||||||
'.eslint_todo/vue-no-unused-properties.mjs',
|
'.eslint_todo/vue-no-unused-properties.mjs',
|
||||||
'app/assets/javascripts/projects/project_new.js',
|
'app/assets/javascripts/projects/project_new.js',
|
||||||
'app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue',
|
'app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_wrapper.vue',
|
||||||
|
@ -240,7 +241,7 @@ RSpec.describe CI::ChangedFiles, feature_category: :tooling do
|
||||||
|
|
||||||
context 'when todo files have been changed but no ignored file was removed from them' do
|
context 'when todo files have been changed but no ignored file was removed from them' do
|
||||||
let(:eslint_command) do
|
let(:eslint_command) do
|
||||||
['yarn', 'run', 'lint:eslint', '--no-warn-ignored', '--format', 'gitlab',
|
['yarn', 'run', 'lint:eslint', '--no-warn-ignored', '--no-error-on-unmatched-pattern', '--format', 'gitlab',
|
||||||
'.eslint_todo/vue-no-unused-properties.mjs']
|
'.eslint_todo/vue-no-unused-properties.mjs']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,13 @@ module CI
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
command = ["yarn", "run", "lint:eslint", "--no-warn-ignored", "--format", "gitlab", *files]
|
command = [
|
||||||
|
"yarn", "run", "lint:eslint",
|
||||||
|
"--no-warn-ignored",
|
||||||
|
"--no-error-on-unmatched-pattern",
|
||||||
|
"--format", "gitlab",
|
||||||
|
*files
|
||||||
|
]
|
||||||
system(*command)
|
system(*command)
|
||||||
|
|
||||||
last_command_status.exitstatus
|
last_command_status.exitstatus
|
||||||
|
|
Loading…
Reference in New Issue