Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-09-11 21:13:14 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-09-11 21:13:14 +0300
commit9e40efa6a6cb39c0a4a6d7d43f7445e2d6e25172 (patch)
tree3b5db6c0284b8c37d6afcae4e1340c3fe57c90f9
parentd06e4d855aed9148571c7fd95fe02f208a017dd3 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml29
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml10
-rw-r--r--.rubocop.yml11
-rw-r--r--.rubocop_todo/style/mutable_constant.yml1
-rw-r--r--.rubocop_todo/style/redundant_freeze.yml11
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.checksum15
-rw-r--r--Gemfile.lock11
-rw-r--r--app/assets/javascripts/jobs/components/table/jobs_table_tabs.vue2
-rw-r--r--app/controllers/groups/work_items_controller.rb4
-rw-r--r--app/helpers/routing/projects_helper.rb18
-rw-r--r--app/views/groups/work_items/show.html.haml1
-rw-r--r--config/routes/group.rb2
-rw-r--r--doc/.vale/gitlab/spelling-exceptions.txt3
-rw-r--r--doc/administration/geo/replication/datatypes.md61
-rw-r--r--doc/administration/geo/replication/object_storage.md6
-rw-r--r--doc/api/graphql/reference/index.md2
-rw-r--r--doc/architecture/blueprints/google_artifact_registry_integration/index.md159
-rw-r--r--doc/architecture/blueprints/google_artifact_registry_integration/ui_ux.md17
-rw-r--r--doc/ci/components/index.md16
-rw-r--r--doc/ci/migration/examples/jenkins-maven.md145
-rw-r--r--doc/development/testing_guide/end_to_end/resources.md18
-rw-r--r--doc/user/infrastructure/clusters/index.md4
-rw-r--r--rubocop/cop/lint/last_keyword_argument.rb89
-rw-r--r--rubocop/rubocop-ruby27.yml9
-rw-r--r--rubocop/rubocop-ruby30.yml16
-rw-r--r--spec/lib/gitlab/url_builder_spec.rb3
-rw-r--r--spec/requests/groups/work_items_controller_spec.rb44
-rw-r--r--spec/rubocop/cop/lint/last_keyword_argument_spec.rb168
29 files changed, 410 insertions, 469 deletions
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 753bbdc8590..419c659e745 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -309,35 +309,6 @@ gitlab:setup:
paths:
- log/*.log
-rspec:deprecations:
- extends:
- - .default-retry
- - .default-before_script
- - .static-analysis-cache
- - .rails:rules:deprecations
- stage: post-test
- allow_failure: true
- needs:
- - job: rspec:artifact-collector unit
- optional: true
- - job: rspec:artifact-collector system
- optional: true
- - job: rspec:artifact-collector remainder
- optional: true
- - job: rspec:artifact-collector ee
- optional: true
- variables:
- SETUP_DB: "false"
- script:
- - grep -h -R "keyword" deprecations/ | awk '{$1=$1};1' | sort | uniq -c | sort
- - grep -R "keyword" deprecations/ | wc
- - run_timed_command "fail_on_warnings bundle exec rubocop --only Lint/LastKeywordArgument --parallel"
- artifacts:
- expire_in: 31d
- when: always
- paths:
- - deprecations/
-
# The jobs built upon `.artifact-collector` are to work around the
# needs: [] limit of a maximum of 50 dependencies.
# These intermediate jobs allow us to collect the artifacts of
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 9361563c1d9..4b573ff473e 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -2206,16 +2206,6 @@
changes: *code-backstage-patterns
when: on_failure
-.rails:rules:deprecations:
- rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-merge-request-labels-pipeline-expedite
- when: never
- - <<: *if-default-branch-schedule-nightly
- - <<: *if-ruby3_1-branch-schedule-nightly
- - <<: *if-merge-request-labels-run-all-rspec
-
.rails:rules:rspec-coverage:
rules:
- <<: *if-not-ee
diff --git a/.rubocop.yml b/.rubocop.yml
index 3263434238b..8ce199fd201 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -13,12 +13,6 @@ inherit_from:
<% end %>
- '.rubocop_todo.yml'
<% end %>
- <% if RUBY_VERSION[/^\d+\.\d+/, 0] == '2.7' %>
- - ./rubocop/rubocop-ruby27.yml
- <% end %>
- <% if RUBY_VERSION[/^\d+\.\d+/, 0] == '3.0' %>
- - ./rubocop/rubocop-ruby30.yml
- <% end %>
<% if RUBY_VERSION[/^\d+\.\d+/, 0] == '3.1' %>
- ./rubocop/rubocop-ruby31.yml
<% end %>
@@ -36,7 +30,7 @@ inherit_mode:
- AllowedPatterns
AllCops:
- # Target the current Ruby version. For example, "2.7" or "3.0".
+ # Target the current Ruby version. For example, "3.0" or "3.1".
TargetRubyVersion: <%= RUBY_VERSION[/^\d+\.\d+/, 0] %>
TargetRailsVersion: 7.0
Exclude:
@@ -112,9 +106,6 @@ Layout/LineLength:
- 'ee/spec/controllers/concerns/routable_actions_spec.rb'
- 'ee/spec/lib/gitlab/auth/group_saml/sso_enforcer_spec.rb'
-Lint/LastKeywordArgument:
- Safe: false
-
Lint/Debugger:
DebuggerMethods:
PryShell:
diff --git a/.rubocop_todo/style/mutable_constant.yml b/.rubocop_todo/style/mutable_constant.yml
index f7a82be400a..d549830992f 100644
--- a/.rubocop_todo/style/mutable_constant.yml
+++ b/.rubocop_todo/style/mutable_constant.yml
@@ -7,7 +7,6 @@ Style/MutableConstant:
- 'app/graphql/mutations/packages/bulk_destroy.rb'
- 'app/helpers/blame_helper.rb'
- 'app/models/ci/build_trace_chunks/redis_base.rb'
- - 'app/models/design_management/repository.rb'
- 'app/models/integrations/datadog.rb'
- 'app/presenters/packages/helm/index_presenter.rb'
- 'app/services/import/validate_remote_git_endpoint_service.rb'
diff --git a/.rubocop_todo/style/redundant_freeze.yml b/.rubocop_todo/style/redundant_freeze.yml
index 2a6ace4f090..a637a2dc28f 100644
--- a/.rubocop_todo/style/redundant_freeze.yml
+++ b/.rubocop_todo/style/redundant_freeze.yml
@@ -28,7 +28,6 @@ Style/RedundantFreeze:
- 'app/models/integrations/confluence.rb'
- 'app/models/integrations/datadog.rb'
- 'app/models/integrations/discord.rb'
- - 'app/models/integrations/field.rb'
- 'app/models/integrations/teamcity.rb'
- 'app/models/license_template.rb'
- 'app/models/members/group_member.rb'
@@ -43,19 +42,15 @@ Style/RedundantFreeze:
- 'app/models/snippet_repository.rb'
- 'app/models/terraform/state.rb'
- 'app/services/clusters/agent_tokens/track_usage_service.rb'
- - 'app/services/error_tracking/list_projects_service.rb'
- - 'app/services/grafana/proxy_service.rb'
- 'app/services/import/validate_remote_git_endpoint_service.rb'
- 'app/services/issues/base_service.rb'
- 'app/services/projects/import_error_filter.rb'
- 'app/services/projects/lfs_pointers/lfs_object_download_list_service.rb'
- - 'app/services/prometheus/proxy_variable_substitution_service.rb'
- 'app/uploaders/file_uploader.rb'
- 'app/validators/certificate_fingerprint_validator.rb'
- 'app/validators/json_schema_validator.rb'
- 'app/validators/line_code_validator.rb'
- 'lib/api/api.rb'
- - 'lib/api/concerns/packages/nuget_endpoints.rb'
- 'lib/api/debian_group_packages.rb'
- 'lib/api/go_proxy.rb'
- 'lib/api/helpers.rb'
@@ -67,8 +62,6 @@ Style/RedundantFreeze:
- 'lib/banzai/filter/attributes_filter.rb'
- 'lib/banzai/filter/autolink_filter.rb'
- 'lib/banzai/filter/blockquote_fence_filter.rb'
- - 'lib/banzai/filter/dollar_math_post_filter.rb'
- - 'lib/banzai/filter/dollar_math_pre_filter.rb'
- 'lib/banzai/filter/footnote_filter.rb'
- 'lib/banzai/filter/gollum_tags_filter.rb'
- 'lib/banzai/filter/markdown_post_escape_filter.rb'
@@ -89,7 +82,6 @@ Style/RedundantFreeze:
- 'lib/gitlab/ci/build/artifacts/metadata.rb'
- 'lib/gitlab/ci/config/entry/artifacts.rb'
- 'lib/gitlab/ci/config/external/file/base.rb'
- - 'lib/gitlab/ci/interpolation/block.rb'
- 'lib/gitlab/ci/parsers/test/junit.rb'
- 'lib/gitlab/ci/pipeline/chain/skip.rb'
- 'lib/gitlab/ci/pipeline/expression/lexeme/and.rb'
@@ -112,7 +104,6 @@ Style/RedundantFreeze:
- 'lib/gitlab/database/background_migration/batch_optimizer.rb'
- 'lib/gitlab/database/load_balancing/service_discovery.rb'
- 'lib/gitlab/database/migrations/runner.rb'
- - 'lib/gitlab/database/query_analyzers/query_recorder.rb'
- 'lib/gitlab/dependency_linker/base_linker.rb'
- 'lib/gitlab/dependency_linker/gemfile_linker.rb'
- 'lib/gitlab/dependency_linker/godeps_json_linker.rb'
@@ -127,7 +118,6 @@ Style/RedundantFreeze:
- 'lib/gitlab/email/handler/service_desk_handler.rb'
- 'lib/gitlab/email/receiver.rb'
- 'lib/gitlab/error_tracking/error_repository/open_api_strategy.rb'
- - 'lib/gitlab/front_matter.rb'
- 'lib/gitlab/git.rb'
- 'lib/gitlab/git/base_error.rb'
- 'lib/gitlab/git/diff.rb'
@@ -139,7 +129,6 @@ Style/RedundantFreeze:
- 'lib/gitlab/golang.rb'
- 'lib/gitlab/graphql/queries.rb'
- 'lib/gitlab/harbor/query.rb'
- - 'lib/gitlab/hook_data/base_builder.rb'
- 'lib/gitlab/i18n/po_linter.rb'
- 'lib/gitlab/i18n/translation_entry.rb'
- 'lib/gitlab/jira/dvcs.rb'
diff --git a/Gemfile b/Gemfile
index 4ef5bb8b5e2..262830ff4b1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -129,7 +129,7 @@ gem 'grape-swagger', '~> 1.6.1', group: [:development, :test]
gem 'grape-swagger-entity', '~> 0.5.1', group: [:development, :test]
# GraphQL API
-gem 'graphql', '~> 1.13.12'
+gem 'graphql', '~> 1.13.19'
gem 'graphiql-rails', '~> 1.8.0'
gem 'apollo_upload_server', '~> 2.1.0'
gem 'graphql-docs', '~> 2.1.0', group: [:development, :test]
@@ -256,7 +256,7 @@ gem 'rainbow', '~> 3.0'
gem 'ruby-progressbar', '~> 1.10'
# Linear-time regex library for untrusted regular expressions
-gem 're2', '~> 1.7.0'
+gem 're2', '2.0.0.beta2'
# Misc
diff --git a/Gemfile.checksum b/Gemfile.checksum
index 6a85dc3ce67..c95a7bca4f7 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -265,7 +265,7 @@
{"name":"graphiql-rails","version":"1.8.0","platform":"ruby","checksum":"02e2c5098be2c6c29219a0e9b2910a2cd3c494301587a3199a7c4484d8038ed1"},
{"name":"graphlient","version":"0.5.0","platform":"ruby","checksum":"0f2c9416142e50b6bd4edcd86fe6810f792951732c487f9061aee6d420e0f292"},
{"name":"graphlyte","version":"1.0.0","platform":"ruby","checksum":"b5af4ab67dde6e961f00ea1c18f159f73b52ed11395bb4ece297fe628fa1804d"},
-{"name":"graphql","version":"1.13.12","platform":"ruby","checksum":"1d82666cf201193a8d0cb54cea38576b820418db4869b549f61a35f3a2d97ac3"},
+{"name":"graphql","version":"1.13.19","platform":"ruby","checksum":"43581db30e21f781d3c175e85807071dc0ba94304d59621b44116f817a5f5a5a"},
{"name":"graphql-client","version":"0.17.0","platform":"ruby","checksum":"5aaf02ce8f2dbc8e3ba05a7eaeb3ad9336762c4424c6093f4438fbb9490eeb5d"},
{"name":"graphql-docs","version":"2.1.0","platform":"ruby","checksum":"7eb82402f8fda455104b2b60364e9ada145d79d3121a8f915790d49da38bb576"},
{"name":"grpc","version":"1.55.0","platform":"ruby","checksum":"529332f8e5e98f5b138afd5c4a9c7bdc9e247f4c10c84c1adbf1a114eba161ae"},
@@ -359,7 +359,7 @@
{"name":"mini_histogram","version":"0.3.1","platform":"ruby","checksum":"6a114b504e4618b0e076cc672996036870f7cc6f16b8e5c25c0c637726d2dd94"},
{"name":"mini_magick","version":"4.10.1","platform":"ruby","checksum":"e939d2c70c8002233fc6b1eecfe762f38a156d69ad31a87160205870be08f852"},
{"name":"mini_mime","version":"1.1.2","platform":"ruby","checksum":"a54aec0cc7438a03a850adb00daca2bdb60747f839e28186994df057cea87151"},
-{"name":"mini_portile2","version":"2.8.2","platform":"ruby","checksum":"46b2d244cc6ff01a89bf61274690c09fdbdca47a84ae9eac39039e81231aee7c"},
+{"name":"mini_portile2","version":"2.8.4","platform":"ruby","checksum":"180bc4193701bbeb9b6c02df5a6b8185bff7f32abd466dd97d6532d36e45b20a"},
{"name":"minitest","version":"5.11.3","platform":"ruby","checksum":"78e18aa2c49c58e9bc53c54a0b900e87ad0a96394e92fbbfa58d3ff860a68f45"},
{"name":"mixlib-cli","version":"2.1.8","platform":"ruby","checksum":"e6f27be34d580f6ed71731ca46b967e57793a627131c1f6e1ed2dad39ea3bdf9"},
{"name":"mixlib-config","version":"3.0.9","platform":"ruby","checksum":"9867adab3ab547eb74a8efdc9dfab6bcc83d2802a571ff8af8d6e981ca8d53ab"},
@@ -491,7 +491,16 @@
{"name":"rbtree","version":"0.4.6","platform":"ruby","checksum":"14eea4469b24fd2472542e5f3eb105d6344c8ccf36f0b56d55fdcfeb4e0f10fc"},
{"name":"rchardet","version":"1.8.0","platform":"ruby","checksum":"693acd5253d5ade81a51940697955f6dd4bb2f0d245bda76a8e23deec70a52c7"},
{"name":"rdoc","version":"6.3.2","platform":"ruby","checksum":"def4a720235c27d56c176ae73555e647eb04ea58a8bbaa927f8f9f79de7805a6"},
-{"name":"re2","version":"1.7.0","platform":"ruby","checksum":"0ccf19e3b289e67b56bd89a542488075de98d9b101b9946c4133d4b96af4d903"},
+{"name":"re2","version":"2.0.0.beta2","platform":"aarch64-linux","checksum":"7fdd52a0f5a17f626b55ee1edfdababe3e9e4648e5335e677138baad2cd6f180"},
+{"name":"re2","version":"2.0.0.beta2","platform":"arm-linux","checksum":"47339c3b6bd70b8c2707e2a762d770b1e22c039d736e758f44b44060339f3048"},
+{"name":"re2","version":"2.0.0.beta2","platform":"arm64-darwin","checksum":"8ab3b332c131f419e85698b4251868001ec828f6b98bfa268af55a750ba73ee0"},
+{"name":"re2","version":"2.0.0.beta2","platform":"ruby","checksum":"eb08108fe7f94c63e6dc6e15ad1148d53b6d6610b833724f98672d79cc2cca5d"},
+{"name":"re2","version":"2.0.0.beta2","platform":"x64-mingw-ucrt","checksum":"b0dd168a7446589c55168fe4d91e020e8667f660c1096458f852614052f6c6c5"},
+{"name":"re2","version":"2.0.0.beta2","platform":"x64-mingw32","checksum":"d98baf20f3e9b073d8c9841341260587a6491487bd03970f226e251aa3c79722"},
+{"name":"re2","version":"2.0.0.beta2","platform":"x86-linux","checksum":"97ea8c700aa673c49c7c6aad7ea1ec23ca77a3c02be99f8a756e2557e54051f3"},
+{"name":"re2","version":"2.0.0.beta2","platform":"x86-mingw32","checksum":"6700ad5427f68f8245e9be1d3fe35cd7a93779d68bc15bb95f720ebea472e6b4"},
+{"name":"re2","version":"2.0.0.beta2","platform":"x86_64-darwin","checksum":"ea4c9ae704241f10f983229c1911b66f5a3cf7de5c443f37d0d17eb56e7e5f73"},
+{"name":"re2","version":"2.0.0.beta2","platform":"x86_64-linux","checksum":"da8352f05430c96f9b662a29c8bbe991a9e5cf154752add5a96fb19d7c0df4b9"},
{"name":"recaptcha","version":"5.12.3","platform":"ruby","checksum":"37d1894add9e70a54d0c6c7f0ecbeedffbfa7d075acfbd4c509818dfdebdb7ee"},
{"name":"recursive-open-struct","version":"1.1.3","platform":"ruby","checksum":"a3538a72552fcebcd0ada657bdff313641a4a5fbc482c08cfb9a65acb1c9de5a"},
{"name":"redcarpet","version":"3.6.0","platform":"ruby","checksum":"8ad1889c0355ff4c47174af14edd06d62f45a326da1da6e8a121d59bdcd2e9e9"},
diff --git a/Gemfile.lock b/Gemfile.lock
index b85acd88706..8cbfdae1ae7 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -801,7 +801,7 @@ GEM
faraday_middleware
graphql-client
graphlyte (1.0.0)
- graphql (1.13.12)
+ graphql (1.13.19)
graphql-client (0.17.0)
activesupport (>= 3.0)
graphql (~> 1.10)
@@ -1016,7 +1016,7 @@ GEM
mini_histogram (0.3.1)
mini_magick (4.10.1)
mini_mime (1.1.2)
- mini_portile2 (2.8.2)
+ mini_portile2 (2.8.4)
minitest (5.11.3)
mixlib-cli (2.1.8)
mixlib-config (3.0.9)
@@ -1295,7 +1295,8 @@ GEM
rbtree (0.4.6)
rchardet (1.8.0)
rdoc (6.3.2)
- re2 (1.7.0)
+ re2 (2.0.0.beta2)
+ mini_portile2 (~> 2.8.4)
recaptcha (5.12.3)
json
recursive-open-struct (1.1.3)
@@ -1859,7 +1860,7 @@ DEPENDENCIES
graphiql-rails (~> 1.8.0)
graphlient (~> 0.5.0)
graphlyte (~> 1.0.0)
- graphql (~> 1.13.12)
+ graphql (~> 1.13.19)
graphql-docs (~> 2.1.0)
grpc (~> 1.55.0)
gssapi (~> 1.3.1)
@@ -1964,7 +1965,7 @@ DEPENDENCIES
rainbow (~> 3.0)
rbtrace (~> 0.4)
rdoc (~> 6.3.2)
- re2 (~> 1.7.0)
+ re2 (= 2.0.0.beta2)
recaptcha (~> 5.12)
redis (~> 4.8.0)
redis-actionpack (~> 5.3.0)
diff --git a/app/assets/javascripts/jobs/components/table/jobs_table_tabs.vue b/app/assets/javascripts/jobs/components/table/jobs_table_tabs.vue
index 797facb1eb8..464b500c66e 100644
--- a/app/assets/javascripts/jobs/components/table/jobs_table_tabs.vue
+++ b/app/assets/javascripts/jobs/components/table/jobs_table_tabs.vue
@@ -63,7 +63,7 @@ export default {
<template>
<div class="gl-display-flex align-items-lg-center">
- <gl-tabs content-class="gl-py-0">
+ <gl-tabs content-class="gl-py-0" class="gl-w-full">
<gl-tab
v-for="tab in tabs"
:key="tab.text"
diff --git a/app/controllers/groups/work_items_controller.rb b/app/controllers/groups/work_items_controller.rb
index d1e15c81471..bd85f12119b 100644
--- a/app/controllers/groups/work_items_controller.rb
+++ b/app/controllers/groups/work_items_controller.rb
@@ -7,5 +7,9 @@ module Groups
def index
not_found unless Feature.enabled?(:namespace_level_work_items, group)
end
+
+ def show
+ not_found unless Feature.enabled?(:namespace_level_work_items, group)
+ end
end
end
diff --git a/app/helpers/routing/projects_helper.rb b/app/helpers/routing/projects_helper.rb
index 89536b9760d..06de9022be4 100644
--- a/app/helpers/routing/projects_helper.rb
+++ b/app/helpers/routing/projects_helper.rb
@@ -35,11 +35,6 @@ module Routing
end
def issue_url(entity, *args)
- # TODO: we do not have a route to access group level work items yet.
- # That is to be done as part of view group level work item issue:
- # see https://gitlab.com/gitlab-org/gitlab/-/work_items/393987
- return unless entity.project.present?
-
if use_work_items_path?(entity)
work_item_url(entity, *args)
else
@@ -48,12 +43,11 @@ module Routing
end
def work_item_url(entity, *args)
- # TODO: we do not have a route to access group level work items yet.
- # That is to be done as part of view group level work item issue:
- # see https://gitlab.com/gitlab-org/gitlab/-/work_items/393987
- return unless entity.project.present?
-
- project_work_items_url(entity.project, entity.iid, *args)
+ if entity.project.present?
+ project_work_items_url(entity.project, entity.iid, *args)
+ else
+ group_work_item_url(entity.namespace, entity.iid, *args)
+ end
end
def merge_request_url(entity, *args)
@@ -99,6 +93,8 @@ module Routing
private
def use_work_items_path?(issue)
+ return true if issue.project.blank? && issue.namespace.present?
+
issue.issue_type == 'task'
end
end
diff --git a/app/views/groups/work_items/show.html.haml b/app/views/groups/work_items/show.html.haml
new file mode 100644
index 00000000000..eb962cc0b69
--- /dev/null
+++ b/app/views/groups/work_items/show.html.haml
@@ -0,0 +1 @@
+.h1 Work Item
diff --git a/config/routes/group.rb b/config/routes/group.rb
index 19789999cfe..87e885e59a2 100644
--- a/config/routes/group.rb
+++ b/config/routes/group.rb
@@ -160,7 +160,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
resources :achievements, only: [:index, :new, :edit]
- resources :work_items, only: [:index]
+ resources :work_items, only: [:index, :show], param: :iid
end
scope(
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index 361a080a2e4..575dc713b51 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -351,6 +351,7 @@ Fastly
Fastzip
favicon
favorited
+Fediverse
ffaker
Figma
Filebeat
@@ -526,6 +527,7 @@ LaunchDarkly
ldapsearch
Lefthook
Leiningen
+Lemmy
libFuzzer
Libgcrypt
Libravatar
@@ -960,6 +962,7 @@ subqueried
subqueries
subquery
subquerying
+Subreddit
substring
substrings
subtask
diff --git a/doc/administration/geo/replication/datatypes.md b/doc/administration/geo/replication/datatypes.md
index f0487beb0f6..896501128f7 100644
--- a/doc/administration/geo/replication/datatypes.md
+++ b/doc/administration/geo/replication/datatypes.md
@@ -36,39 +36,40 @@ verification methods:
| Git | Personal Snippets | Geo with Gitaly | Gitaly Checksum |
| Git | Group wiki repository | Geo with Gitaly | Gitaly Checksum |
| Blobs | User uploads _(file system)_ | Geo with API | SHA256 checksum |
-| Blobs | User uploads _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | User uploads _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum (*3*) |
| Blobs | LFS objects _(file system)_ | Geo with API | SHA256 checksum |
-| Blobs | LFS objects _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
-| Blobs | CI job artifacts _(file system)_ | Geo with API | SHA256 checksum |
-| Blobs | CI job artifacts _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | LFS objects _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum (*3*) |
+| Blobs | CI job artifacts _(file system)_ | Geo with API | SHA256 checksum |
+| Blobs | CI job artifacts _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum (*3*) |
| Blobs | Archived CI build traces _(file system)_ | Geo with API | _Not implemented_ |
-| Blobs | Archived CI build traces _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Archived CI build traces _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum (*3*) |
| Blobs | Container registry _(file system)_ | Geo with API/Docker API | _SHA256 checksum_ |
-| Blobs | Container registry _(object storage)_ | Geo with API/Managed/Docker API (*2*) | _SHA256 checksum_ |
+| Blobs | Container registry _(object storage)_ | Geo with API/Managed/Docker API (*2*) | SHA256 checksum (*3*) |
| Blobs | Package registry _(file system)_ | Geo with API | SHA256 checksum |
-| Blobs | Package registry _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Package registry _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum (*3*) |
| Blobs | Terraform Module Registry _(file system)_ | Geo with API | SHA256 checksum |
-| Blobs | Terraform Module Registry _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Terraform Module Registry _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum (*3*) |
| Blobs | Versioned Terraform State _(file system)_ | Geo with API | SHA256 checksum |
-| Blobs | Versioned Terraform State _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Versioned Terraform State _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum (*3*) |
| Blobs | External Merge Request Diffs _(file system)_ | Geo with API | SHA256 checksum |
-| Blobs | External Merge Request Diffs _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | External Merge Request Diffs _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum (*3*) |
| Blobs | Pipeline artifacts _(file system)_ | Geo with API | SHA256 checksum |
-| Blobs | Pipeline artifacts _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Pipeline artifacts _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum (*3*) |
| Blobs | Pages _(file system)_ | Geo with API | SHA256 checksum |
-| Blobs | Pages _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Pages _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum (*3*) |
| Blobs | CI Secure Files _(file system)_ | Geo with API | SHA256 checksum |
-| Blobs | CI Secure Files _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | CI Secure Files _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum (*3*) |
| Blobs | Incident Metric Images _(file system)_ | Geo with API/Managed | SHA256 checksum |
-| Blobs | Incident Metric Images _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Incident Metric Images _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum (*3*) |
| Blobs | Alert Metric Images _(file system)_ | Geo with API | SHA256 checksum |
-| Blobs | Alert Metric Images _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Alert Metric Images _(object storage)_ | Geo with API/Managed (*2*) | SHA256 checksum (*3*) |
| Blobs | Dependency Proxy Images_(file system)_ | Geo with API | SHA256 checksum |
-| Blobs | Dependency Proxy Images _(object storage)_ | Geo with API/managed (*2*) | _Not implemented_ |
+| Blobs | Dependency Proxy Images _(object storage)_ | Geo with API/managed (*2*) | SHA256 checksum (*3*) |
- (*1*): Redis replication can be used as part of HA with Redis sentinel. It's not used between Geo sites.
- (*2*): Object storage replication can be performed by Geo or by your object storage provider/appliance
native replication feature.
+- (*3*): Object Storage verification is behind a [feature flag](../../feature_flags.md), `geo_object_storage_verification`, [introduced in 16.4](https://gitlab.com/groups/gitlab-org/-/epics/8056) and enabled by default. It uses a checksum of the file size to verify the files.
### Git repositories
@@ -192,27 +193,27 @@ successfully, you must replicate their data using some other means.
|[Project repository](../../../user/project/repository/index.md) | **Yes** (10.2) | **Yes** (10.7) | Not applicable | Not applicable | Migrated to [self-service framework](../../../development/geo/framework.md) in 16.2. See GitLab issue [#367925](https://gitlab.com/gitlab-org/gitlab/-/issues/367925) for more details.<br /><br />Behind feature flag `geo_project_repository_replication`, enabled by default in (16.3).<br /><br /> All projects, including [archived projects](../../../user/project/settings/index.md#archive-a-project), are replicated. |
|[Project wiki repository](../../../user/project/wiki/index.md) | **Yes** (10.2)<sup>2</sup> | **Yes** (10.7)<sup>2</sup> | Not applicable | Not applicable | Migrated to [self-service framework](../../../development/geo/framework.md) in 15.11. See GitLab issue [#367925](https://gitlab.com/gitlab-org/gitlab/-/issues/367925) for more details.<br /><br />Behind feature flag `geo_project_wiki_repository_replication`, enabled by default in (15.11). |
|[Group wiki repository](../../../user/project/wiki/group.md) | [**Yes** (13.10)](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | [**Yes** (16.3)](https://gitlab.com/gitlab-org/gitlab/-/issues/323897) | Not applicable | Not applicable | Behind feature flag `geo_group_wiki_repository_replication`, enabled by default. |
-|[Uploads](../../uploads.md) | **Yes** (10.2) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication is behind the feature flag `geo_upload_replication`, enabled by default. Verification was behind the feature flag `geo_upload_verification`, removed in 14.8. |
-|[LFS objects](../../lfs/index.md) | **Yes** (10.2) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | GitLab versions 11.11.x and 12.0.x are affected by [a bug that prevents any new LFS objects from replicating](https://gitlab.com/gitlab-org/gitlab/-/issues/32696).<br /><br />Replication is behind the feature flag `geo_lfs_object_replication`, enabled by default. Verification was behind the feature flag `geo_lfs_object_verification`, removed in 14.7. |
+|[Uploads](../../uploads.md) | **Yes** (10.2) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [**Yes** (16.4)](object_storage.md) | Replication is behind the feature flag `geo_upload_replication`, enabled by default. Verification was behind the feature flag `geo_upload_verification`, removed in 14.8. |
+|[LFS objects](../../lfs/index.md) | **Yes** (10.2) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [**Yes** (16.4)](object_storage.md) | GitLab versions 11.11.x and 12.0.x are affected by [a bug that prevents any new LFS objects from replicating](https://gitlab.com/gitlab-org/gitlab/-/issues/32696).<br /><br />Replication is behind the feature flag `geo_lfs_object_replication`, enabled by default. Verification was behind the feature flag `geo_lfs_object_verification`, removed in 14.7. |
|[Personal snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | Not applicable | Not applicable | |
|[Project snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | Not applicable | Not applicable | |
-|[CI job artifacts](../../../ci/jobs/job_artifacts.md) | **Yes** (10.4) | **Yes** (14.10) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Verification is behind the feature flag `geo_job_artifact_replication`, enabled by default in 14.10. |
-|[CI Pipeline Artifacts](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/pipeline_artifact.rb) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Persists additional artifacts after a pipeline completes. |
-|[CI Secure Files](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/secure_file.rb) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [No](object_storage.md#verification-of-files-in-object-storage) | Verification is behind the feature flag `geo_ci_secure_file_replication`, enabled by default in 15.3. |
+|[CI job artifacts](../../../ci/jobs/job_artifacts.md) | **Yes** (10.4) | **Yes** (14.10) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [**Yes** (16.4)](object_storage.md) | Verification is behind the feature flag `geo_job_artifact_replication`, enabled by default in 14.10. |
+|[CI Pipeline Artifacts](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/pipeline_artifact.rb) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [**Yes** (16.4)](object_storage.md) | Persists additional artifacts after a pipeline completes. |
+|[CI Secure Files](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/secure_file.rb) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [**Yes** (16.4)](object_storage.md) | Verification is behind the feature flag `geo_ci_secure_file_replication`, enabled by default in 15.3. |
|[Container Registry](../../packages/container_registry.md) | **Yes** (12.3)<sup>1</sup> | **Yes** (15.10) | **Yes** (12.3)<sup>1</sup> | **Yes** (15.10) | See [instructions](container_registry.md) to set up the Container Registry replication. |
-|[Terraform Module Registry](../../../user/packages/terraform_module_registry/index.md) | **Yes** (14.0) | **Yes** (14.0) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Terraform Module Registry](../../../user/packages/terraform_module_registry/index.md) | **Yes** (14.0) | **Yes** (14.0) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [**Yes** (16.4)](object_storage.md) | Behind feature flag `geo_package_file_replication`, enabled by default. |
|[Project designs repository](../../../user/project/issues/design_management.md) | **Yes** (12.7) | **Yes** (16.1) | Not applicable | Not applicable | Designs also require replication of LFS objects and Uploads. |
-|[Package Registry](../../../user/packages/package_registry/index.md) | **Yes** (13.2) | **Yes** (13.10) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Behind feature flag `geo_package_file_replication`, enabled by default. |
-|[Versioned Terraform State](../../terraform_state.md) | **Yes** (13.5) | **Yes** (13.12) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication is behind the feature flag `geo_terraform_state_version_replication`, enabled by default. Verification was behind the feature flag `geo_terraform_state_version_verification`, which was removed in 14.0. |
-|[External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication is behind the feature flag `geo_merge_request_diff_replication`, enabled by default. Verification was behind the feature flag `geo_merge_request_diff_verification`, removed in 14.7.|
+|[Package Registry](../../../user/packages/package_registry/index.md) | **Yes** (13.2) | **Yes** (13.10) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [**Yes** (16.4)](object_storage.md) | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Versioned Terraform State](../../terraform_state.md) | **Yes** (13.5) | **Yes** (13.12) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [**Yes** (16.4)](object_storage.md) | Replication is behind the feature flag `geo_terraform_state_version_replication`, enabled by default. Verification was behind the feature flag `geo_terraform_state_version_verification`, which was removed in 14.0. |
+|[External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [**Yes** (16.4)](object_storage.md) | Replication is behind the feature flag `geo_merge_request_diff_replication`, enabled by default. Verification was behind the feature flag `geo_merge_request_diff_verification`, removed in 14.7.|
|[Versioned snippets](../../../user/snippets.md#versioned-snippets) | [**Yes** (13.7)](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [**Yes** (14.2)](https://gitlab.com/groups/gitlab-org/-/epics/2810) | Not applicable | Not applicable | Verification was implemented behind the feature flag `geo_snippet_repository_verification` in 13.11, and the feature flag was removed in 14.2. |
-|[GitLab Pages](../../pages/index.md) | [**Yes** (14.3)](https://gitlab.com/groups/gitlab-org/-/epics/589) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Behind feature flag `geo_pages_deployment_replication`, enabled by default. Verification was behind the feature flag `geo_pages_deployment_verification`, removed in 14.7. |
-|[Project-level Secure files](../../../ci/secure_files/index.md) | **Yes** (15.3) | **Yes** (15.3) | **Yes** (15.3) | [No](object_storage.md#verification-of-files-in-object-storage) | |
-| [Incident Metric Images](../../../operations/incident_management/incidents.md#metrics) | **Yes** (15.5) | **Yes**(15.5) | **Yes** (15.5) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication/Verification is handled via the Uploads data type. | |
-|[Alert Metric Images](../../../operations/incident_management/alerts.md#metrics-tab) | **Yes** (15.5) | **Yes** (15.5) | **Yes** (15.5) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication/Verification is handled via the Uploads data type. |
+|[GitLab Pages](../../pages/index.md) | [**Yes** (14.3)](https://gitlab.com/groups/gitlab-org/-/epics/589) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [**Yes** (16.4)](object_storage.md) | Behind feature flag `geo_pages_deployment_replication`, enabled by default. Verification was behind the feature flag `geo_pages_deployment_verification`, removed in 14.7. |
+|[Project-level Secure files](../../../ci/secure_files/index.md) | **Yes** (15.3) | **Yes** (15.3) | **Yes** (15.3) | [**Yes** (16.4)](object_storage.md) | |
+| [Incident Metric Images](../../../operations/incident_management/incidents.md#metrics) | **Yes** (15.5) | **Yes**(15.5) | **Yes** (15.5) | [**Yes** (16.4)](object_storage.md) | Replication/Verification is handled via the Uploads data type. | |
+|[Alert Metric Images](../../../operations/incident_management/alerts.md#metrics-tab) | **Yes** (15.5) | **Yes** (15.5) | **Yes** (15.5) | [**Yes** (16.4)](object_storage.md) | Replication/Verification is handled via the Uploads data type. |
|[Server-side Git hooks](../../server_hooks.md) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/1867) | No | Not applicable | Not applicable | Not planned because of current implementation complexity, low customer interest, and availability of alternatives to hooks. |
|[Elasticsearch integration](../../../integration/advanced_search/elasticsearch.md) | [Not planned](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | No | No | Not planned because further product discovery is required and Elasticsearch (ES) clusters can be rebuilt. Secondaries use the same ES cluster as the primary. |
-|[Dependency Proxy Images](../../../user/packages/dependency_proxy/index.md) | [**Yes** (15.7)](https://gitlab.com/groups/gitlab-org/-/epics/8833) | [**Yes** (15.7)](https://gitlab.com/groups/gitlab-org/-/epics/8833) | [**Yes** (15.7)](https://gitlab.com/groups/gitlab-org/-/epics/8833) | [No](object_storage.md#verification-of-files-in-object-storage) | |
+|[Dependency Proxy Images](../../../user/packages/dependency_proxy/index.md) | [**Yes** (15.7)](https://gitlab.com/groups/gitlab-org/-/epics/8833) | [**Yes** (15.7)](https://gitlab.com/groups/gitlab-org/-/epics/8833) | [**Yes** (15.7)](https://gitlab.com/groups/gitlab-org/-/epics/8833) | [**Yes** (16.4)](object_storage.md) | |
|[Vulnerability Export](../../../user/application_security/vulnerability_report/index.md#export-vulnerability-details) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/3111) | No | No | No | Not planned because they are ephemeral and sensitive information. They can be regenerated on demand. |
<sup>1</sup> Migrated to [self-service framework](../../../development/geo/framework.md) in 15.5. See GitLab issue [#337436](https://gitlab.com/gitlab-org/gitlab/-/issues/337436) for more details.
diff --git a/doc/administration/geo/replication/object_storage.md b/doc/administration/geo/replication/object_storage.md
index c94c4caa60b..3b6b214d9e3 100644
--- a/doc/administration/geo/replication/object_storage.md
+++ b/doc/administration/geo/replication/object_storage.md
@@ -7,6 +7,8 @@ type: howto
# Geo with Object storage **(PREMIUM SELF)**
+> Verification of files stored in object storage was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/8056) in GitLab 16.4 [with a flag](../../feature_flags.md) named `geo_object_storage_verification`. Enabled by default.
+
Geo can be used in combination with Object Storage (AWS S3, or other compatible object storage).
**Secondary** sites can use one of the following:
@@ -86,7 +88,3 @@ For manual synchronization, or scheduled by `cron`, see:
- [`s3cmd sync`](https://s3tools.org/s3cmd-sync)
- [`gsutil rsync`](https://cloud.google.com/storage/docs/gsutil/commands/rsync)
-
-## Verification of files in object storage
-
-[Files stored in object storage are not verified.](https://gitlab.com/groups/gitlab-org/-/epics/8056)
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 03b49cb1075..77e240254f1 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -7165,7 +7165,7 @@ Input type: `VulnerabilitiesDismissInput`
| <a id="mutationvulnerabilitiesdismissclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationvulnerabilitiesdismisscomment"></a>`comment` | [`String`](#string) | Comment why vulnerability was dismissed (maximum 50,000 characters). |
| <a id="mutationvulnerabilitiesdismissdismissalreason"></a>`dismissalReason` | [`VulnerabilityDismissalReason`](#vulnerabilitydismissalreason) | Reason why vulnerability should be dismissed. |
-| <a id="mutationvulnerabilitiesdismissvulnerabilityids"></a>`vulnerabilityIds` | [`[VulnerabilityID!]!`](#vulnerabilityid) | IDs of the vulnerabilities to be dismissed. |
+| <a id="mutationvulnerabilitiesdismissvulnerabilityids"></a>`vulnerabilityIds` | [`[VulnerabilityID!]!`](#vulnerabilityid) | IDs of the vulnerabilities to be dismissed (maximum 100 entries). |
#### Fields
diff --git a/doc/architecture/blueprints/google_artifact_registry_integration/index.md b/doc/architecture/blueprints/google_artifact_registry_integration/index.md
new file mode 100644
index 00000000000..adde0f7f587
--- /dev/null
+++ b/doc/architecture/blueprints/google_artifact_registry_integration/index.md
@@ -0,0 +1,159 @@
+---
+status: proposed
+creation-date: "2023-08-31"
+authors: [ "@jdrpereira", "@10io" ]
+coach: "@grzesiek"
+approvers: [ "@trizzi", "@crystalpoole" ]
+owning-stage: "~devops::package"
+participating-stages: []
+---
+
+# Google Artifact Registry Integration
+
+## Summary
+
+GitLab and Google Cloud have recently [announced](https://about.gitlab.com/blog/2023/08/29/gitlab-google-partnership-s3c/) a partnership to combine the unique capabilities of their platforms.
+
+As highlighted in the announcement, one key goal is the ability to "_use Google's Artifact Registry with GitLab pipelines and packaging to create a security data plane_". The initial step toward this goal is to allow users to configure a new [Google Artifact Registry](https://cloud.google.com/artifact-registry) (abbreviated as GAR from now on) [project integration](../../../user/project/integrations/index.md) and display [container image artifacts](https://cloud.google.com/artifact-registry/docs/supported-formats) in the GitLab UI.
+
+## Motivation
+
+Please refer to the [announcement](https://about.gitlab.com/blog/2023/08/29/gitlab-google-partnership-s3c/) blog post for more details about the motivation and long-term goals of the GitLab and Google Cloud partnership.
+
+Regarding the scope of this design document, our primary focus is to fulfill the Product requirement of providing users with visibility over their container images in GAR. The motivation for this specific goal is rooted in foundational research on the use of external registries as a complement to the GitLab Container Registry ([internal](https://gitlab.com/gitlab-org/ux-research/-/issues/2602)).
+
+Since this marks the first step in the GAR integration, our aim is to achieve this goal in a way that establishes a foundation to facilitate reusability in the future. This groundwork could benefit potential future expansions, such as support for additional artifact formats (npm, Maven, etc.), and features beyond the Package stage (e.g., vulnerability scanning, deployments, etc.).
+
+### Goals
+
+- Allow GitLab users to configure a new [project integration](../../../user/project/integrations/index.md) for connecting to GAR.
+- Limited to a single top-level GAR [repository](https://cloud.google.com/artifact-registry/docs/repositories) per GitLab project.
+- Limited to GAR repositories in [Standard](https://cloud.google.com/artifact-registry/docs/repositories#mode) mode. Support for Remote and Virtual [repository modes](https://cloud.google.com/artifact-registry/docs/repositories#mode) (both in Preview) is a strech goal.
+- Limited to GAR repositories of format [Container images](https://cloud.google.com/artifact-registry/docs/supported-formats#container).
+- Use a Google Cloud [service account](https://cloud.google.com/iam/docs/service-account-overview) provided by the GitLab project owner/maintainer to interact with GAR.
+- Allow GitLab users to list container images under the connected GAR repository, including sub-repositories. The list should be paginable and sortable.
+- For each listed image, display its URI, list of tags, size, digest, upload time, media type, build time, and update time, as documented [here](https://cloud.google.com/artifact-registry/docs/reference/rest/v1/projects.locations.repositories.dockerImages#DockerImage).
+- Listing container images under the connected GAR repository is restricted to users with [Reporter+](../../../user/permissions.md#roles) roles.
+
+### Non-Goals
+
+While some of these may become goals for future iterations, they are currently out of scope:
+
+- Create, update and delete operations.
+- Connecting to multiple (top-level) GAR repositories under the same project.
+- Support for [repository formats](https://cloud.google.com/artifact-registry/docs/supported-formats) beyond container images.
+- Support for other [Identity and Access Management (IAM)](https://cloud.google.com/iam) permissions/credentials beyond [service accounts](https://cloud.google.com/iam/docs/service-account-overview).
+- GAR [cleanup policies](https://cloud.google.com/artifact-registry/docs/repositories/cleanup-policy).
+- Filtering the images list by their attributes (name or value). The current [GAR API](https://cloud.google.com/artifact-registry/docs/reference/rpc/google.devtools.artifactregistry.v1#listdockerimagesrequest) does not support filtering.
+- [Artifact analysis and vulnerability scanning](https://cloud.google.com/artifact-registry/docs/analysis).
+
+## Proposal
+
+### Design and Implementation Details
+
+#### Project Integration
+
+A new [project integration](../../../user/project/integrations/index.md) for GAR will be created. Once enabled, this will display a new "Google Artifact Registry" item in the "Operate" section of the sidebar. This is also where the [Harbor](../../../user/project/integrations/harbor.md) integration is displayed if enabled.
+
+The GAR integration can be enabled by project owner/maintainer(s), who must provide four configuration parameters during setup:
+
+- **GCP project ID**: The globally unique identifier for the GCP project where the target GAR repository lives.
+- **Repository location**: The [GCP location](https://cloud.google.com/about/locations) where the target GAR repository lives.
+- **Repository name**: The name of the target GAR repository.
+- **GCP service account key**: The _content_ (not the file) of the [service account key](https://cloud.google.com/iam/docs/keys-create-delete) in JSON format ([sample](https://cloud.google.com/iam/docs/keys-create-delete#creating)).
+
+#### Authentication
+
+The integration is simplified by using a single GCP service account for the integration. Users retain the ability to [audit usage](https://cloud.google.com/iam/docs/audit-logging/examples-service-accounts#access-with-key) of this service account on the GCP side and revoke permissions if/when necessary.
+
+The service account key provided during the integration setup must be granted at least with the [`Artifact Registry Reader`](https://cloud.google.com/artifact-registry/docs/access-control#permissions) role in the target GCP project.
+
+Saving the (encrypted) service account key JSON content in the backend allows us to easily grab and use it to initialize the GAR client (more about that later). Providing the content of the key file instead of uploading it is similar to what we do with users' public SSH keys.
+
+As previously highlighted, access to the GAR integration features is restricted to users with [Reporter+](../../../user/permissions.md#roles) roles.
+
+#### Resource Mapping
+
+For the [GitLab Container Registry](../../../user/packages/container_registry/index.md), repositories within a specific project must have a path that matches the project full path. This is essentially how we establish a resource mapping between GitLab Rails and the registry, which serves multiple purposes, including granular authorization, scoping storage usage to a given project/group/namespace, and more.
+
+Regarding the GAR integration, since there is no equivalent entities for GitLab project/group/namespace resources on the GAR side, we aim to simplify matters by allowing users to attach any [GAR repository](https://cloud.google.com/artifact-registry/docs/repositories) to any GitLab project, regardless of their respective paths. Similarly, we do not plan to restrict the attachment of a particular GAR repository to a single GitLab project. Ultimately, it is up to users to determine how to organize both datasets in the way that best suits their needs.
+
+#### GAR API
+
+GAR provides three APIs: Docker API, REST API, and RPC API.
+
+The [Docker API](https://cloud.google.com/artifact-registry/docs/reference/docker-api) is based on the [Docker Registry HTTP API V2](https://docs.docker.com/registry/spec/api), now superseded by the [OCI Distribution Specification API](https://github.com/opencontainers/distribution-spec/blob/main/spec.md) (from now on referred to as OCI API). This API is used for pushing/pulling images to/from GAR and also provides some discoverability operations. Please refer to [Alternative Solutions](#alternative-solutions) for the reasons why we don't intend to use it.
+
+Among the proprietary GAR APIs, the [REST API](https://cloud.google.com/artifact-registry/docs/reference/rest) provides basic functionality for managing repositories. This includes [`list`](https://cloud.google.com/artifact-registry/docs/reference/rest/v1/projects.locations.repositories.dockerImages/list) and [`get`](https://cloud.google.com/artifact-registry/docs/reference/rest/v1/projects.locations.repositories.dockerImages/get) operations for container image repositories, which could be used for this integration. Both operations return the same data structure, represented by the [`DockerImage`](https://cloud.google.com/artifact-registry/docs/reference/rest/v1/projects.locations.repositories.dockerImages#DockerImage) object, so both provide the same level of detail.
+
+Last but not least, there is also an [RPC API](https://cloud.google.com/artifact-registry/docs/reference/rpc/google.devtools.artifactregistry.v1), backed by gRPC and Protocol Buffers. This API provides the most functionality, covering all GAR features. From the available operations, we can make use of the [`ListDockerImagesRequest`](https://cloud.google.com/artifact-registry/docs/reference/rpc/google.devtools.artifactregistry.v1#listdockerimagesrequest) and [`GetDockerImageRequest`](https://cloud.google.com/artifact-registry/docs/reference/rpc/google.devtools.artifactregistry.v1#google.devtools.artifactregistry.v1.GetDockerImageRequest) operations. As with the REST API, both responses are composed of [`DockerImage`](https://cloud.google.com/artifact-registry/docs/reference/rpc/google.devtools.artifactregistry.v1#google.devtools.artifactregistry.v1.DockerImage) objects.
+
+Between the two proprietary API options, we chose the RPC one because it provides support not only for the operations we need today but also offers better coverage of all GAR features, which will be beneficial in future iterations. Finally, we do not intend to make direct use of this API but rather use it through the official Ruby client SDK. Please see [Client SDK](#client-sdk) below for more details.
+
+#### Backend Integration
+
+##### Client SDK
+
+To interact with GAR we will make use of the official GAR [Ruby client SDK](https://cloud.google.com/ruby/docs/reference/google-cloud-artifact_registry/latest).
+
+*TODO: Add more details about the client SDK integration and its limitations (no filtering for example).*
+
+##### Database Changes
+
+*TODO: Describe any necessary changes to the database to support this integration.*
+
+##### CI/CD variables
+
+Similar to the [Harbor](../../../user/project/integrations/harbor.md#configure-gitlab) integration, once users activates the GAR integration, additional CI/CD variables will be automatically available if the integration is enabled. These will be set according to the requirements described in the [documentation](https://cloud.google.com/artifact-registry/docs/docker/authentication#json-key):
+
+- `GCP_ARTIFACT_REGISTRY_URL`: This will be set to `https://LOCATION-docker.pkg.dev`, where `LOCATION` is the GCP project location configured for the integration.
+- `GCP_ARTIFACT_REGISTRY_PROJECT_URI`: This will be set to `LOCATION-docker.pkg.dev/PROJECT-ID`. `PROJECT-ID` is the GCP project ID of the GAR repository configured for the integration.
+- `GCP_ARTIFACT_REGISTRY_PASSWORD`: This will be set to the base64-encode version of the service account JSON key file configured for the integration.
+- `GCP_ARTIFACT_REGISTRY_USER`: This will be set to `_json_key_base64`.
+
+These can then be used to log in using `docker login`:
+
+```shell
+docker login -u $GCP_ARTIFACT_REGISTRY_USER -p $GCP_ARTIFACT_REGISTRY_PASSWORD $GCP_ARTIFACT_REGISTRY_URL
+```
+
+Similarly, these can be used to download images from the repository with `docker pull`:
+
+```shell
+docker pull $GCP_ARTIFACT_REGISTRY_PROJECT_URI/REPOSITORY/myapp:latest
+```
+
+Finally, provided that the configured service account has the `Artifact Registry Writer` role, one can also push images to GAR:
+
+```shell
+docker build -t $GCP_ARTIFACT_REGISTRY_REPOSITORY_URI/myapp:latest .
+docker push $GCP_ARTIFACT_REGISTRY_REPOSITORY_URI/myapp:latest
+```
+
+For forward compatibility reasons, the repository name (`REPOSITORY` in the command above) must be appended to `GCP_ARTIFACT_REGISTRY_PROJECT_URI` by the user. In the first iteration we will only support a single GAR repository, and therefore we could technically provide an e.g. `GCP_ARTIFACT_REGISTRY_REPOSITORY_URI` variable with the repository name already included. However, once we add support for multiple repositories, there is no way we can tell what repository a user will want to target for a specific instruction. So it must be the user to tell that.
+
+#### UI/UX
+
+This integration will include a dedicated page named "Google Artifact Registry," listed under the "Operate" section of the sidebar. This page will enable users to view the list of all container images in the configured GAR repository. See the [UI/UX](ui_ux.md) page for additional details.
+
+#### GraphQL APIs
+
+*TODO: Describe any GraphQL APIs or changes to existing APIs that will be needed for this integration.*
+
+## Alternative Solutions
+
+### Use Docker/OCI API
+
+One alternative solution considered was to use the Docker/OCI API provided by GAR, as it is a common standard for container registries. This approach would have allowed GitLab to reuse [existing logic](https://gitlab.com/gitlab-org/gitlab/-/blob/20df77103147c0c8ff1c22a888516eba4bab3c46/lib/container_registry/client.rb) for connecting to container registries, which could potentially speed up development. However, there were several drawbacks to this approach:
+
+- **Authentication Complexity**: The API requires authentication tokens, which need to be requested at the [login endpoint](https://docs.docker.com/registry/spec/auth/token). These tokens have limited validity, adding complexity to the authentication process. Handling expiring tokens would have been necessary.
+
+- **Limited Focus**: The API is solely focused on container registry objects, which does not align with the goal of creating a flexible integration framework for adopting additional GAR artifacts (e.g. package registry formats) down the road.
+
+- **Discoverability Limitations**: The API has severe limitations when it comes to discoverability, lacking features like filtering or sorting.
+
+- **Multiple Requests**: To retrieve all the required information about each image, multiple requests to different endpoints (listing tags, obtaining image manifests, and image configuration blobs) would have been necessary, leading to a `1+N` performance issue.
+
+GitLab had previously faced significant challenges with the last two limitations, prompting the development of a custom [GitLab Container Registry API](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs-gitlab/api.md) to address them. Additionally, GitLab decided to [deprecate support](../../../update/deprecations.md#use-of-third-party-container-registries-is-deprecated) for connecting to third-party container registries using the Docker/OCI API due to these same limitations and the increased cost of maintaining two solutions in parallel. As a result, there is an ongoing effort to replace the use of the Docker/OCI API endpoints with custom API endpoints for all container registry functionalities in GitLab.
+
+Considering these factors, the decision was made to build the GAR integration from scratch using the proprietary GAR API. This approach provides more flexibility and control over the integration and can serve as a foundation for future expansions, such as support for other GAR artifact formats.
diff --git a/doc/architecture/blueprints/google_artifact_registry_integration/ui_ux.md b/doc/architecture/blueprints/google_artifact_registry_integration/ui_ux.md
new file mode 100644
index 00000000000..5cb862d50e7
--- /dev/null
+++ b/doc/architecture/blueprints/google_artifact_registry_integration/ui_ux.md
@@ -0,0 +1,17 @@
+---
+stage: package
+group: container registry
+description: 'UI/UX for Google Artifact Registry Integration'
+---
+
+# UI/UX for Google Artifact Registry Integration
+
+## Structure and Organization
+
+Unlike the GitLab Container Registry (and therefore the Docker Registry and OCI Distribution), GAR does not treat tags as the primary "artifacts" in a repository. Instead, the primary "artifacts" are the image manifests. For each manifest object (represented by [`DockerImage`](https://cloud.google.com/artifact-registry/docs/reference/rpc/google.devtools.artifactregistry.v1#google.devtools.artifactregistry.v1.DockerImage)), there is a list of assigned tags (if any). Consequently, when listing the contents of a repository through the GAR API, the response comprises a collection of manifest objects (along with their associated tags as properties), rather than a collection of tag objects. Additionally, due to this design choice, untagged manifests are also present in the response.
+
+To maximize flexibility, extensibility, and maintain familiarity for GAR users, we plan to fully embrace the GAR API data structures while surfacing data in the GitLab UI. We won't attempt to emulate a "list of tags" response to match the UI/UX that we already have for the GitLab Container Registry.
+
+Considering the above, there will be a view that provides a pageable and sortable list of all images in the configured GAR repository. Additionally, there will be a detail view to display more information about a single image. You can find a list of available image attributes documented [here](https://cloud.google.com/artifact-registry/docs/reference/rpc/google.devtools.artifactregistry.v1#google.devtools.artifactregistry.v1.DockerImage).
+
+## Designs
diff --git a/doc/ci/components/index.md b/doc/ci/components/index.md
index a5712a271ca..d4ed98893af 100644
--- a/doc/ci/components/index.md
+++ b/doc/ci/components/index.md
@@ -116,6 +116,9 @@ namespace named `my-username`:
└── .gitlab-ci.yml
```
+ The `.gitlab-ci.yml` file is not required for a CI/CD component to work, but [testing the component](#test-a-component)
+ in a pipeline in the project is recommended.
+
This component is referenced with the path `gitlab.com/my-username/my-component@<version>`.
- Containing one default component and multiple sub-components, then the file structure
@@ -153,9 +156,9 @@ Nesting of components is not possible. For example:
### Test a component
-Testing components as part of the development workflow to ensure that quality maintains high standards is strongly recommended.
+Testing CI/CD components as part of the development workflow is strongly recommended and helps ensure consistent behavior.
-Testing changes in a CI/CD pipeline can be done, like any other project, by creating a `.gitlab-ci.yml` in the root directory.
+Test changes in a CI/CD pipeline like any other project, by creating a `.gitlab-ci.yml` file in the root directory of the component repository.
For example:
@@ -199,12 +202,17 @@ After committing and pushing changes, the pipeline tests the component then rele
### Release a component
-Component repositories are released using the [`release`](../yaml/index.md#release) keyword within a CI pipeline.
+To create a release for a CI/CD component, you can use:
+
+- The [`release`](../yaml/index.md#release) keyword in a CI/CD pipeline.
+- The [UI for creating a release](../../user/project/releases/index.md#create-a-release).
Like in the [example above](#test-a-component), after all tests pass in a pipeline running for a tag ref, we can release a new version of the components repository.
All released versions of the components repository are displayed in the Components Catalog page for the given resource, providing users with information about official releases.
+Components [can be used](#use-a-component-in-a-cicd-configuration) without being released, but only with a commit SHA or a branch name. To enable the use of tags or the `~latest` version keyword, you must create a release.
+
### Use a component in a CI/CD configuration
A pipeline component is identified by a unique address in the form `<fully-qualified-doman-name>/<component-path>@<version>`
@@ -313,7 +321,7 @@ include:
stages: [verify, deploy]
##
-# inside the component YAML:
+# inside the component's template.yml file:
spec:
inputs:
stage:
diff --git a/doc/ci/migration/examples/jenkins-maven.md b/doc/ci/migration/examples/jenkins-maven.md
index a3590c41094..f529e12558a 100644
--- a/doc/ci/migration/examples/jenkins-maven.md
+++ b/doc/ci/migration/examples/jenkins-maven.md
@@ -5,96 +5,109 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, howto
---
-# Migrating a Maven build from Jenkins to GitLab CI
+# Migrate a Maven build from Jenkins to GitLab CI/CD
If you have a Maven build in Jenkins, you can use a [Java Spring](https://gitlab.com/gitlab-org/project-templates/spring)
project template to migrate to GitLab. The template uses Maven for its underlying dependency management.
-## Jenkins job options
+## Sample Jenkins configurations
-We are going to use three different options in Jenkins to test, build, and install the project:
+The following three Jenkins examples each use different methods to test, build, and install a
+Maven project into a shell agent:
- Freestyle with shell execution
- Freestyle with the Maven task plugin
- A declarative pipeline using a Jenkinsfile
-All three of these options execute the same three commands:
+All three examples run the same three commands in order, in three different stages:
- `mvn test`: Run any tests found in the codebase
-- `mvn package -DskipTests`: Compile the code into an executable type defined in the POM and skip running any tests since we did that already
-- `mvn install -DskipTests`: Install the compiled executable into the local maven `.m2` repository and skip running any tests
+- `mvn package -DskipTests`: Compile the code into an executable type defined in the POM
+ and skip running any tests because that was done in the first stage.
+- `mvn install -DskipTests`: Install the compiled executable into the agent's local Maven
+ `.m2` repository and again skip running the tests.
-We are using a single, persistent Jenkins agent to handle running these three methods, which requires Maven to be pre-installed on the agent.
-This method of execution is similar to a GitLab Shell runner.
+These examples use a single, persistent Jenkins agent, which requires Maven to be
+pre-installed on the agent. This method of execution is similar to a GitLab Runner
+using the [shell executor](https://docs.gitlab.com/runner/executors/shell.html).
### Freestyle with shell execution
-This example utilizes Jenkins' built-in shell execution option so we can directly call `mvn` commands from the shell on the agent.
+If using Jenkins' built-in shell execution option to directly call `mvn` commands
+from the shell on the agent, the configuration might look like:
![freestyle shell](img/maven-freestyle-shell.png)
### Freestyle with Maven task plugin
-This example utilizes the Maven plugin in Jenkins to declare and execute any specific goals in the [Maven build lifecycle](https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html)
-
-NOTE:
-This plugin does not install Maven on the Jenkins agent, but rather provides a script wrapper around calling Maven commands. Maven must be installed before you use this method.
+If using the Maven plugin in Jenkins to declare and execute any specific goals
+in the [Maven build lifecycle](https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html),
+the configuration might look like:
![freestyle plugin](img/maven-freestyle-plugin.png)
+This plugin requires Maven to be installed on the Jenkins agent, and uses a script wrapper
+for calling Maven commands.
+
### Using a declarative pipeline
-Finally, we can run these Maven commands through a declarative pipeline stored either in the Jenkins pipeline configuration or directly in the Git repository. By default, this file is named `Jenksinfile`.
-
-This example uses shell execution commands instead of plugins.
+If using a declarative pipeline, the configuration might look like:
```groovy
- pipeline {
- agent any
- stages {
- stage('Test') {
- steps {
- sh "mvn test"
- }
+pipeline {
+ agent any
+ stages {
+ stage('Test') {
+ steps {
+ sh "mvn test"
}
- stage('Build') {
- steps {
- sh "mvn package -DskipTests"
- }
+ }
+ stage('Build') {
+ steps {
+ sh "mvn package -DskipTests"
}
- stage('Install') {
- steps {
- sh "mvn install -DskipTests"
- }
+ }
+ stage('Install') {
+ steps {
+ sh "mvn install -DskipTests"
}
}
}
+}
```
-## Converting to GitLab CI
+This example uses shell execution commands instead of plugins.
+
+By default, a declarative pipeline configuration is stored either in the Jenkins
+pipeline configuration or directly in the Git repository in a `Jenksinfile`.
-Now that we have seen a few examples in Jenkins, let's refactor this process into GitLab CI.
+## Convert Jenkins configuration to GitLab CI/CD
+
+While the examples above are all slightly different, they can all be migrated to GitLab CI/CD
+with the same pipeline configuration.
Prerequisites:
-- An available runner in GitLab
-- Docker installed on the runner
-- The runner is registered for this project and is using the Docker executor
+- A GitLab Runner with the Docker executor that can be used by the project.
+ If you are using GitLab.com, you can use the public shared runners.
-Instead of using a persistent machine for handling this build process, we are going to rely on an ephemeral Docker container to handle this execution.
-This removes the need for maintaining a virtual machine and the Maven version installed on the virtual machine and allows us some more flexiblity with expanding and extending the functionality of our CI pipeline.
+Instead of using a persistent machine for handling this build process like the Jenkins samples,
+this example uses an ephemeral Docker container to handle execution. Using a container
+removes the need for maintaining a virtual machine and the Maven version installed on it.
+It also increases flexibility for expanding and extending the functionality of the pipeline.
-Here is the final `.gitlab-ci.yml` file:
+In a GitLab CI/CD pipeline, the commands run in "jobs", which are grouped into stages.
+The migrated configuration in the `.gitlab-ci.yml` configuration file consists of
+three global keywords (`stages`, `default`, and `variables`) followed by 3 jobs:
```yaml
-image: maven:3.6.3-openjdk-11
-
stages:
- test
- build
- install
default:
+ image: maven:3.6.3-openjdk-11
cache:
key: $CI_COMMIT_REF_SLUG
paths:
@@ -107,35 +120,47 @@ variables:
MAVEN_CLI_OPTS: >-
-DskipTests
-test code:
+test-code:
stage: test
script:
- mvn test
-build JAR:
+build-JAR:
stage: build
script:
- mvn $MAVEN_CLI_OPTS package
-install JAR:
+install-JAR:
stage: install
script:
- mvn $MAVEN_CLI_OPTS install
```
-Let's break down the sections of this YAML file:
-
-- **Image**: The base Docker image where we execute all of our commands. In this case, it's an official Maven Docker image with everything we need already installed.
-- **Stages**: Similar to the Jenkinsfile, we are defining three stages that run in order. Test jobs execute first, followed by build jobs, and finally install jobs.
-- **Default**: Global default settings for the pipeline.
- - **Cache**: Any data to be cached and reused between jobs.
- - **Key**: The unique identifier for the specific cache archive. In this case, it's a shortened version of the Git commit ref.
- - **Paths**: Any specific directories or files to include in the cache. In this case, we are caching the `.m2/` directory to avoid re-installing dependencies between jobs.
-- **Variables**: We are setting a few environment variables to be used by each job.
- - `MAVEN_OPTS`: These are Maven environment variables referenced whenever Maven is executed.
- - `-Dhttps.protocols=TLSv1.2` sets our TLS protocol to version 1.2 for any HTTP requests we may make in the pipeline.
- - `-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository` sets the location of our local Maven repository to the GitLab project directory on the runner. This is to make sure we can access and modify the repository.
- - `MAVEN_CLI_OPTS`: These are specific arguments to be injected into `mvn` commands.
- - `-DskipTests` skips the 'test' stage in the Maven build lifecycle.
-
-- **Test code**, **Build JAR**, and **Install JAR**: These are the jobs to run in the pipeline. The top line of each section is a user-defined name for the job that shows up in the pipeline. The stage clause defines which stage the job runs in. (A pipeline contains one to many stages and a stage contains one to many jobs). The script section covers commands to run in that job. In this case, each job runs a single command.
+In this example:
+
+- `stages` defines three stages that run in order. Like the Jenkins examples above,
+ the test job runs first, followed by the build job, and finally the install job.
+- `default` defines standard configuration to reuse in all jobs by default:
+ - `image` defines the Docker image container to use and execute commands in. In this example,
+ it's an official Maven Docker image with everything needed already installed.
+ - `cache` is used to cache and reuse dependencies:
+ - `key` is the unique identifier for the specific cache archive. In this example,
+ it's a shortened version of the Git commit ref, autogenerated as a [predefined CI/CD variable](../../variables/predefined_variables.md).
+ Any job that runs for the same commit ref reuses the same cache.
+ - `paths` are the directories or files to include in the cache. In this example,
+ we cache the `.m2/` directory to avoid re-installing dependencies between job runs.
+- `variables` defines [CI/CD variables](../../variables/index.md) that can be used by all jobs:
+ - `MAVEN_OPTS` are Maven environment variables needed whenever Maven is executed:
+ - `-Dhttps.protocols=TLSv1.2` sets the TLS protocol to version 1.2 for any HTTP requests in the pipeline.
+ - `-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository` sets the location of the
+ local Maven repository to the GitLab project directory on the runner, so the job
+ can access and modify the repository.
+ - `MAVEN_CLI_OPTS` are specific arguments to be added to `mvn` commands:
+ - `-DskipTests` skips the `test` stage in the Maven build lifecycle.
+- `test-code`, `build-JAR`, and `install-JAR` are the user-defined names for the jobs
+ to run in the pipeline:
+ - `stage` defines which stage the job runs in. A pipeline contains one or more stages
+ and a stage contains one or more jobs. This example has three stages, each with a single job.
+ - `script` defines the commands to run in that job, similar to `steps` in a `Jenkinsfile`.
+ Jobs can run multiple commands in sequence, which run in the image container,
+ but in this example the jobs run only one command each.
diff --git a/doc/development/testing_guide/end_to_end/resources.md b/doc/development/testing_guide/end_to_end/resources.md
index 09ce882ddab..bf3f1c25f5e 100644
--- a/doc/development/testing_guide/end_to_end/resources.md
+++ b/doc/development/testing_guide/end_to_end/resources.md
@@ -392,7 +392,7 @@ In this case, the result is similar to calling `Resource::Shirt.fabricate!`.
### Factories
-You may also use [FactoryBot](https://github.com/thoughtbot/factory_bot/) invocations to create resources within your tests.
+You may also use [FactoryBot](https://github.com/thoughtbot/factory_bot/) invocations to create, build, and fetch resources within your tests.
```ruby
# create a project via the API to use in the test
@@ -403,6 +403,22 @@ let(:issue) { create(:issue, project: project) }
# create a private project via the API with a specific name
let(:project) { create(:project, :private, name: 'my-project-name', add_name_uuid: false) }
+
+###
+
+# instantiate an Issue but don't create it via API yet
+let(:issue) { build(:issue) }
+
+# instantiate a Project and perform some actions before creating
+let(:project) do
+ build(:project) do |p|
+ p.name = 'Test'
+ p.add_name_uuid = false
+ end
+end
+
+# fetch an existing issue via the API with attributes
+let(:existing_issue) { build(:issue, project: project, iid: issue.iid).reload! }
```
All factories are defined in [`qa/qa/factories`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/factories/) and are representative of
diff --git a/doc/user/infrastructure/clusters/index.md b/doc/user/infrastructure/clusters/index.md
index ad587154021..1cdb1470344 100644
--- a/doc/user/infrastructure/clusters/index.md
+++ b/doc/user/infrastructure/clusters/index.md
@@ -13,9 +13,9 @@ To connect clusters to GitLab, use the [GitLab agent](../../clusters/agent/index
WARNING:
In GitLab 14.5, the certificate-based method to connect Kubernetes clusters
to GitLab was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8),
-as well as its related [features](#deprecated-features). In self-managed GitLab 15.0 and later,
+as well as its related [features](#deprecated-features). In self-managed GitLab 17.0 and later,
this feature is disabled by default. For GitLab SaaS users, this feature is available until
-GitLab 15.6 for users who have at least one certificate-based cluster enabled in their namespace hierarchy.
+GitLab 15.9 for users who have at least one certificate-based cluster enabled in their namespace hierarchy.
For GitLab SaaS users that never used this feature previously, it is no longer available.
The certificate-based Kubernetes integration with GitLab is deprecated.
diff --git a/rubocop/cop/lint/last_keyword_argument.rb b/rubocop/cop/lint/last_keyword_argument.rb
deleted file mode 100644
index f50c25f7924..00000000000
--- a/rubocop/cop/lint/last_keyword_argument.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-# frozen_string_literal: true
-
-module RuboCop
- module Cop
- module Lint
- # This cop only works if there are files from deprecation_toolkit. You can
- # generate these files by:
- #
- # 1. Running specs with RECORD_DEPRECATIONS=1
- # 1. Downloading the complete set of deprecations/ files from a CI
- # pipeline (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47720)
- class LastKeywordArgument < RuboCop::Cop::Base
- extend RuboCop::Cop::AutoCorrector
-
- MSG = 'Using the last argument as keyword parameters is deprecated'
-
- DEPRECATIONS_GLOB = File.expand_path('../../../deprecations/**/*.yml', __dir__)
- KEYWORD_DEPRECATION_STR = 'maybe ** should be added to the call'
-
- def on_send(node)
- return if target_ruby_version >= 3.0
-
- arg = get_last_argument(node)
- return unless arg
-
- return unless known_match?(processed_source.file_path, node.first_line, node.method_name.to_s)
-
- return if arg.children.first.respond_to?(:kwsplat_type?) && arg.children.first&.kwsplat_type?
-
- # parser thinks `a: :b, c: :d` is hash type, it's actually kwargs
- return if arg.hash_type? && !arg.source.match(/\A{/)
-
- add_offense(arg) do |corrector|
- if arg.hash_type?
- kwarg = arg.source.sub(/\A{\s*/, '').sub(/\s*}\z/, '')
- corrector.replace(arg, kwarg)
- elsif arg.splat_type?
- corrector.insert_before(arg, '*')
- else
- corrector.insert_before(arg, '**')
- end
- end
- end
-
- private
-
- def get_last_argument(node)
- return node.arguments[-2] if node.block_argument?
-
- node.arguments.last
- end
-
- def known_match?(file_path, line_number, method_name)
- method_name = 'initialize' if method_name == 'new'
-
- return unless self.class.keyword_warnings[method_name]
-
- file_path_from_root = file_path.sub(File.expand_path('../../..', __dir__), '')
- file_and_line = "#{file_path_from_root}:#{line_number}"
-
- self.class.keyword_warnings[method_name].any? do |warning|
- warning.include?(file_and_line)
- end
- end
-
- def self.keyword_warnings
- @keyword_warnings ||= keywords_list
- end
-
- def self.keywords_list
- hash = Dir.glob(DEPRECATIONS_GLOB).each_with_object({}) do |file, hash|
- hash.merge!(YAML.safe_load(File.read(file)))
- end
-
- hash.values.flatten.each_with_object({}) do |str, results|
- next unless str.include?(KEYWORD_DEPRECATION_STR)
-
- match_data = str.match(/called method `([^\s]+)'/)
- next unless match_data
-
- key = match_data[1]
- results[key] ||= []
- results[key] << str
- end
- end
- end
- end
- end
-end
diff --git a/rubocop/rubocop-ruby27.yml b/rubocop/rubocop-ruby27.yml
deleted file mode 100644
index 29957defeb0..00000000000
--- a/rubocop/rubocop-ruby27.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-# RuboCop configuration adjustments during the transition time from Ruby 2.7 to
-# Ruby 3.0. This configuration should be removed after the transition has been
-# completed.
-
-# These cops are enabled in Ruby 3.0 (rubocop-30.yml).
-Style/MutableConstant:
- Enabled: false
-Style/RedundantFreeze:
- Enabled: false
diff --git a/rubocop/rubocop-ruby30.yml b/rubocop/rubocop-ruby30.yml
deleted file mode 100644
index b984d761b80..00000000000
--- a/rubocop/rubocop-ruby30.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-# RuboCop configuration adjustments during the transition time from Ruby 2.7 to
-# Ruby 3.0.
-#
-# After the transition has been completed:
-# * Move all configuration which enabled or tweaked cops to .rubocop.yml.
-# * Remove all remaining configuration.
-
-# These cops are disabled in Ruby 2.7 (rubocop-27.yml).
-Style/MutableConstant:
- Enabled: true
-Style/RedundantFreeze:
- Enabled: true
-
-# No longer needed because Ruby 3.0 will fail due to kwargs issues.
-Lint/LastKeywordArgument:
- Enabled: false
diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb
index 73627d3e6ff..865a8384405 100644
--- a/spec/lib/gitlab/url_builder_spec.rb
+++ b/spec/lib/gitlab/url_builder_spec.rb
@@ -32,6 +32,9 @@ RSpec.describe Gitlab::UrlBuilder do
:ci_build | ->(build) { "/#{build.project.full_path}/-/jobs/#{build.id}" }
:design | ->(design) { "/#{design.project.full_path}/-/design_management/designs/#{design.id}/raw_image" }
+ [:issue, :group_level] | ->(issue) { "/groups/#{issue.namespace.full_path}/-/work_items/#{issue.iid}" }
+ [:work_item, :group_level] | ->(work_item) { "/groups/#{work_item.namespace.full_path}/-/work_items/#{work_item.iid}" }
+
:group | ->(group) { "/groups/#{group.full_path}" }
:group_milestone | ->(milestone) { "/groups/#{milestone.group.full_path}/-/milestones/#{milestone.iid}" }
diff --git a/spec/requests/groups/work_items_controller_spec.rb b/spec/requests/groups/work_items_controller_spec.rb
index c47b3f03ec1..e5dd88a5471 100644
--- a/spec/requests/groups/work_items_controller_spec.rb
+++ b/spec/requests/groups/work_items_controller_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
RSpec.describe 'Group Level Work Items', feature_category: :team_planning do
let_it_be(:group) { create(:group, :private) }
- let_it_be(:project) { create(:project, group: group) }
let_it_be(:developer) { create(:user).tap { |u| group.add_developer(u) } }
describe 'GET /groups/:group/-/work_items' do
@@ -46,4 +45,47 @@ RSpec.describe 'Group Level Work Items', feature_category: :team_planning do
end
end
end
+
+ describe 'GET /groups/:group/-/work_items/:iid' do
+ let_it_be(:work_item) { create(:work_item, :group_level, namespace: group) }
+ let(:work_items_path) do
+ url_for(controller: 'groups/work_items', action: :show, group_id: group.full_path, iid: work_item.iid)
+ end
+
+ before do
+ sign_in(current_user)
+ end
+
+ context 'when the user can read the group' do
+ let(:current_user) { developer }
+
+ it 'renders index' do
+ get work_items_path
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ context 'when the namespace_level_work_items feature flag is disabled' do
+ before do
+ stub_feature_flags(namespace_level_work_items: false)
+ end
+
+ it 'returns not found' do
+ get work_items_path
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'when the user cannot read the group' do
+ let(:current_user) { create(:user) }
+
+ it 'returns not found' do
+ get work_items_path
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
end
diff --git a/spec/rubocop/cop/lint/last_keyword_argument_spec.rb b/spec/rubocop/cop/lint/last_keyword_argument_spec.rb
deleted file mode 100644
index edd54a40b79..00000000000
--- a/spec/rubocop/cop/lint/last_keyword_argument_spec.rb
+++ /dev/null
@@ -1,168 +0,0 @@
-# frozen_string_literal: true
-
-require 'rubocop_spec_helper'
-require_relative '../../../../rubocop/cop/lint/last_keyword_argument'
-
-RSpec.describe RuboCop::Cop::Lint::LastKeywordArgument, :ruby27, feature_category: :shared do
- before do
- described_class.instance_variable_set(:@keyword_warnings, nil)
- allow(Dir).to receive(:glob).and_call_original
- allow(File).to receive(:read).and_call_original
- end
-
- context 'deprecation files does not exist' do
- before do
- allow(Dir).to receive(:glob).with(described_class::DEPRECATIONS_GLOB).and_return([])
- end
-
- it 'does not register an offense' do
- expect_no_offenses(<<~SOURCE)
- users.call(params)
- SOURCE
- end
- end
-
- context 'deprecation files does exist' do
- let(:create_spec_yaml) do
- <<~YAML
- ---
- test_mutations/boards/lists/create#resolve_with_proper_permissions_backlog_list_creates_one_and_only_one_backlog:
- - |
- DEPRECATION WARNING: /Users/tkuah/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/batch-loader-1.4.0/lib/batch_loader/graphql.rb:38: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
- /Users/tkuah/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/batch-loader-1.4.0/lib/batch_loader.rb:26: warning: The called method `batch' is defined here
- test_mutations/boards/lists/create#ready?_raises_an_error_if_required_arguments_are_missing:
- - |
- DEPRECATION WARNING: /Users/tkuah/code/ee-gdk/gitlab/create_service.rb:1: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
- /Users/tkuah/code/ee-gdk/gitlab/user.rb:17: warning: The called method `call' is defined here
- - |
- DEPRECATION WARNING: /Users/tkuah/code/ee-gdk/gitlab/other_warning_type.rb:1: warning: Some other warning type
- YAML
- end
-
- let(:projects_spec_yaml) do
- <<~YAML
- ---
- test_api/projects_get_/projects_when_unauthenticated_behaves_like_projects_response_returns_an_array_of_projects:
- - |
- DEPRECATION WARNING: /Users/tkuah/code/ee-gdk/gitlab/projects_spec.rb:1: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
- /Users/tkuah/code/ee-gdk/gitlab/lib/gitlab/project.rb:15: warning: The called method `initialize' is defined here
- - |
- DEPRECATION WARNING: /Users/tkuah/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/state_machines-activerecord-0.6.0/lib/state_machines/integrations/active_record.rb:511: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
- /Users/tkuah/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/activerecord-6.0.3.3/lib/active_record/suppressor.rb:43: warning: The called method `save' is defined here
- - |
- DEPRECATION WARNING: /Users/tkuah/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/rack-2.2.3/lib/rack/builder.rb:158: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
- /Users/tkuah/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/grape-1.4.0/lib/grape/middleware/error.rb:30: warning: The called method `initialize' is defined here
- YAML
- end
-
- before do
- allow(Dir).to receive(:glob).and_return(['deprecations/service/create_spec.yml', 'deprecations/api/projects_spec.yml'])
- allow(File).to receive(:read).with('deprecations/service/create_spec.yml').and_return(create_spec_yaml)
- allow(File).to receive(:read).with('deprecations/api/projects_spec.yml').and_return(projects_spec_yaml)
- end
-
- it 'registers an offense for last keyword warning' do
- expect_offense(<<~SOURCE, 'create_service.rb')
- users.call(params)
- ^^^^^^ Using the last argument as keyword parameters is deprecated
- SOURCE
-
- expect_correction(<<~SOURCE)
- users.call(**params)
- SOURCE
- end
-
- it 'does not register an offense for other warning types' do
- expect_no_offenses(<<~SOURCE, 'other_warning_type.rb')
- users.call(params)
- SOURCE
- end
-
- it 'registers an offense for the new method call' do
- expect_offense(<<~SOURCE, 'projects_spec.rb')
- Project.new(params)
- ^^^^^^ Using the last argument as keyword parameters is deprecated
- SOURCE
-
- expect_correction(<<~SOURCE)
- Project.new(**params)
- SOURCE
- end
-
- it 'registers an offense and corrects by converting hash to kwarg' do
- expect_offense(<<~SOURCE, 'create_service.rb')
- users.call(id, { a: :b, c: :d })
- ^^^^^^^^^^^^^^^^ Using the last argument as keyword parameters is deprecated
- SOURCE
-
- expect_correction(<<~SOURCE)
- users.call(id, a: :b, c: :d)
- SOURCE
- end
-
- it 'registers an offense on the last non-block argument' do
- expect_offense(<<~SOURCE, 'create_service.rb')
- users.call(id, params, &block)
- ^^^^^^ Using the last argument as keyword parameters is deprecated
- SOURCE
-
- expect_correction(<<~SOURCE)
- users.call(id, **params, &block)
- SOURCE
- end
-
- it 'does not register an offense if the only argument is a block argument' do
- expect_no_offenses(<<~SOURCE, 'create_service.rb')
- users.call(&block)
- SOURCE
- end
-
- it 'registers an offense and corrects by converting splat to double splat' do
- expect_offense(<<~SOURCE, 'create_service.rb')
- users.call(id, *params)
- ^^^^^^^ Using the last argument as keyword parameters is deprecated
- SOURCE
-
- expect_correction(<<~SOURCE)
- users.call(id, **params)
- SOURCE
- end
-
- it 'does not register an offense if already a kwarg', :aggregate_failures do
- expect_no_offenses(<<~SOURCE, 'create_service.rb')
- users.call(**params)
- SOURCE
-
- expect_no_offenses(<<~SOURCE, 'create_service.rb')
- users.call(id, a: :b, c: :d)
- SOURCE
- end
-
- it 'does not register an offense if the method name does not match' do
- expect_no_offenses(<<~SOURCE, 'create_service.rb')
- users.process(params)
- SOURCE
- end
-
- it 'does not register an offense if the line number does not match' do
- expect_no_offenses(<<~SOURCE, 'create_service.rb')
- users.process
- users.call(params)
- SOURCE
- end
-
- it 'does not register an offense if the filename does not match' do
- expect_no_offenses(<<~SOURCE, 'update_service.rb')
- users.call(params)
- SOURCE
- end
-
- context 'with Ruby 3.0', :ruby30 do
- it 'does not register an offense with known warning' do
- expect_no_offenses(<<~SOURCE, 'create_service.rb')
- users.call(params)
- SOURCE
- end
- end
- end
-end