Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
		
							parent
							
								
									15e998c5bf
								
							
						
					
					
						commit
						39b47b75cf
					
				|  | @ -3980,7 +3980,6 @@ RSpec/FeatureCategory: | ||||||
|     - 'spec/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter_spec.rb' |     - 'spec/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter_spec.rb' | ||||||
|     - 'spec/lib/gitlab/usage_data_counters/note_counter_spec.rb' |     - 'spec/lib/gitlab/usage_data_counters/note_counter_spec.rb' | ||||||
|     - 'spec/lib/gitlab/usage_data_counters/package_event_counter_spec.rb' |     - 'spec/lib/gitlab/usage_data_counters/package_event_counter_spec.rb' | ||||||
|     - 'spec/lib/gitlab/usage_data_counters/productivity_analytics_counter_spec.rb' |  | ||||||
|     - 'spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb' |     - 'spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb' | ||||||
|     - 'spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb' |     - 'spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb' | ||||||
|     - 'spec/lib/gitlab/usage_data_counters/search_counter_spec.rb' |     - 'spec/lib/gitlab/usage_data_counters/search_counter_spec.rb' | ||||||
|  |  | ||||||
|  | @ -510,7 +510,6 @@ Style/ClassAndModuleChildren: | ||||||
|     - 'lib/gitlab/usage_data_counters/ci_template_unique_counter.rb' |     - 'lib/gitlab/usage_data_counters/ci_template_unique_counter.rb' | ||||||
|     - 'lib/gitlab/usage_data_counters/designs_counter.rb' |     - 'lib/gitlab/usage_data_counters/designs_counter.rb' | ||||||
|     - 'lib/gitlab/usage_data_counters/note_counter.rb' |     - 'lib/gitlab/usage_data_counters/note_counter.rb' | ||||||
|     - 'lib/gitlab/usage_data_counters/productivity_analytics_counter.rb' |  | ||||||
|     - 'lib/gitlab/usage_data_counters/snippet_counter.rb' |     - 'lib/gitlab/usage_data_counters/snippet_counter.rb' | ||||||
|     - 'lib/gitlab/usage_data_counters/source_code_counter.rb' |     - 'lib/gitlab/usage_data_counters/source_code_counter.rb' | ||||||
|     - 'lib/gitlab/usage_data_counters/wiki_page_counter.rb' |     - 'lib/gitlab/usage_data_counters/wiki_page_counter.rb' | ||||||
|  |  | ||||||
							
								
								
									
										34
									
								
								CHANGELOG.md
								
								
								
								
							
							
						
						
									
										34
									
								
								CHANGELOG.md
								
								
								
								
							|  | @ -2,6 +2,16 @@ | ||||||
| documentation](doc/development/changelog.md) for instructions on adding your own | documentation](doc/development/changelog.md) for instructions on adding your own | ||||||
| entry. | entry. | ||||||
| 
 | 
 | ||||||
|  | ## 16.11.1 (2024-04-24) | ||||||
|  | 
 | ||||||
|  | ### Security (5 changes) | ||||||
|  | 
 | ||||||
|  | - [Validation for encoded formatting characters](gitlab-org/security/gitlab@fc42e4b96ae1ac3cd766569d62d025cbf23ef16c) ([merge request](gitlab-org/security/gitlab!3979)) | ||||||
|  | - [Forbid untrusted sign-ins to GitLab with Bitbucket and fix related uid](gitlab-org/security/gitlab@ef083c319e67072029787cd5c6a588562984a58c) ([merge request](gitlab-org/security/gitlab!3983)) | ||||||
|  | - [Ensure PAT scope is validated everywhere for GraphQL/ActionCable](gitlab-org/security/gitlab@1847435210161d95b9c5fcd079380e7f2892195f) ([merge request](gitlab-org/security/gitlab!3975)) | ||||||
|  | - [Protect against ReDoS in FileFinder with wildcard filters](gitlab-org/security/gitlab@dc16f3baa640ca8d5b223782ef3d58369423a1dd) ([merge request](gitlab-org/security/gitlab!3969)) | ||||||
|  | - [fix: Validate security report version against schema during parsing](gitlab-org/security/gitlab@55e58d49051aa42938ec1d159b5e7eb3c47d2eb1) ([merge request](gitlab-org/security/gitlab!3967)) | ||||||
|  | 
 | ||||||
| ## 16.11.0 (2024-04-17) | ## 16.11.0 (2024-04-17) | ||||||
| 
 | 
 | ||||||
| ### Added (121 changes) | ### Added (121 changes) | ||||||
|  | @ -605,6 +615,20 @@ entry. | ||||||
| - [Finalize the backfill migration for onboarding status step url](gitlab-org/gitlab@f986c1b1cf00968ff106136893bfe68d47895c69) ([merge request](gitlab-org/gitlab!147278)) | - [Finalize the backfill migration for onboarding status step url](gitlab-org/gitlab@f986c1b1cf00968ff106136893bfe68d47895c69) ([merge request](gitlab-org/gitlab!147278)) | ||||||
| - [Remove ClusterRepositoryCache migration helper class](gitlab-org/gitlab@f71a7a94ce8d70d9d378ebc225b802b58f0ae006) ([merge request](gitlab-org/gitlab!147244)) | - [Remove ClusterRepositoryCache migration helper class](gitlab-org/gitlab@f71a7a94ce8d70d9d378ebc225b802b58f0ae006) ([merge request](gitlab-org/gitlab!147244)) | ||||||
| 
 | 
 | ||||||
|  | ## 16.10.4 (2024-04-24) | ||||||
|  | 
 | ||||||
|  | ### Fixed (1 change) | ||||||
|  | 
 | ||||||
|  | - [Update vulnerability_reads scanner in the ingestion pipeline](gitlab-org/security/gitlab@14b8876233e5dd29149426fd88bab0fc4f014d46) **GitLab Enterprise Edition** | ||||||
|  | 
 | ||||||
|  | ### Security (5 changes) | ||||||
|  | 
 | ||||||
|  | - [Validation for encoded formatting characters](gitlab-org/security/gitlab@4cd13c705ce1a94152fb2fd6fcaa77e90e6441e5) ([merge request](gitlab-org/security/gitlab!3950)) | ||||||
|  | - [Forbid untrusted sign-ins to GitLab with Bitbucket and fix related uid](gitlab-org/security/gitlab@5d3c3a599cc5560dea2236474309537536428cdc) ([merge request](gitlab-org/security/gitlab!3984)) | ||||||
|  | - [Ensure PAT scope is validated everywhere for GraphQL/ActionCable](gitlab-org/security/gitlab@079dfee8cff9da9075eec7c03ce002e87eeebfff) ([merge request](gitlab-org/security/gitlab!3976)) | ||||||
|  | - [Protect against ReDoS in FileFinder with wildcard filters](gitlab-org/security/gitlab@0e7e54050f1c4829b1d55aac85bd4e9cd96f1580) ([merge request](gitlab-org/security/gitlab!3960)) | ||||||
|  | - [fix: Validate security report version against schema during parsing](gitlab-org/security/gitlab@217040b1062caad501d60af387c47cff758788a1) ([merge request](gitlab-org/security/gitlab!3956)) | ||||||
|  | 
 | ||||||
| ## 16.10.3 (2024-04-12) | ## 16.10.3 (2024-04-12) | ||||||
| 
 | 
 | ||||||
| No changes. | No changes. | ||||||
|  | @ -1319,6 +1343,16 @@ No changes. | ||||||
| - [Add sharding keys for system_access](gitlab-org/gitlab@62c2fd4788e62e46f1469e2f18d178840e8e3df2) ([merge request](gitlab-org/gitlab!142501)) | - [Add sharding keys for system_access](gitlab-org/gitlab@62c2fd4788e62e46f1469e2f18d178840e8e3df2) ([merge request](gitlab-org/gitlab!142501)) | ||||||
| - [Add sharding keys for purchase](gitlab-org/gitlab@9c3843da74714c72483c17489d5d3d68ceffd2c8) ([merge request](gitlab-org/gitlab!142505)) | - [Add sharding keys for purchase](gitlab-org/gitlab@9c3843da74714c72483c17489d5d3d68ceffd2c8) ([merge request](gitlab-org/gitlab!142505)) | ||||||
| 
 | 
 | ||||||
|  | ## 16.9.6 (2024-04-24) | ||||||
|  | 
 | ||||||
|  | ### Security (5 changes) | ||||||
|  | 
 | ||||||
|  | - [Validation for encoded formatting characters](gitlab-org/security/gitlab@de8dc151e5ef3f07cf50839e50645df6ec12f5a5) ([merge request](gitlab-org/security/gitlab!3951)) | ||||||
|  | - [Forbid untrusted sign-ins to GitLab with Bitbucket and fix related uid](gitlab-org/security/gitlab@94496a91c17a0f73202cd5c55abc93395825c68c) ([merge request](gitlab-org/security/gitlab!3985)) | ||||||
|  | - [Ensure PAT scope is validated everywhere for GraphQL/ActionCable](gitlab-org/security/gitlab@0dccf32b71614584e05a8590b21a902220e8c701) ([merge request](gitlab-org/security/gitlab!3977)) | ||||||
|  | - [Protect against ReDoS in FileFinder with wildcard filters](gitlab-org/security/gitlab@60a7418ec10f7c6f4ef9bcc75b2fec71255ddcc3) ([merge request](gitlab-org/security/gitlab!3961)) | ||||||
|  | - [fix: Validate security report version against schema during parsing](gitlab-org/security/gitlab@ce709ff78fd8f18024383085d6ac0bf43fa2efbb) ([merge request](gitlab-org/security/gitlab!3957)) | ||||||
|  | 
 | ||||||
| ## 16.9.5 (2024-04-12) | ## 16.9.5 (2024-04-12) | ||||||
| 
 | 
 | ||||||
| No changes. | No changes. | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								Gemfile
								
								
								
								
							
							
						
						
									
										4
									
								
								Gemfile
								
								
								
								
							|  | @ -358,7 +358,6 @@ gem 'gitlab-license', '~> 2.4', feature_category: :shared | ||||||
| gem 'rack-attack', '~> 6.7.0' # rubocop:todo Gemfile/MissingFeatureCategory | gem 'rack-attack', '~> 6.7.0' # rubocop:todo Gemfile/MissingFeatureCategory | ||||||
| 
 | 
 | ||||||
| # Sentry integration | # Sentry integration | ||||||
| gem 'sentry-raven', '~> 3.1', feature_category: :error_tracking |  | ||||||
| gem 'sentry-ruby', '~> 5.10.0', feature_category: :error_tracking | gem 'sentry-ruby', '~> 5.10.0', feature_category: :error_tracking | ||||||
| gem 'sentry-rails', '~> 5.10.0', feature_category: :error_tracking | gem 'sentry-rails', '~> 5.10.0', feature_category: :error_tracking | ||||||
| gem 'sentry-sidekiq', '~> 5.10.0', feature_category: :error_tracking | gem 'sentry-sidekiq', '~> 5.10.0', feature_category: :error_tracking | ||||||
|  | @ -411,7 +410,6 @@ group :opentelemetry do | ||||||
|   gem 'opentelemetry-instrumentation-action_view', feature_category: :tooling |   gem 'opentelemetry-instrumentation-action_view', feature_category: :tooling | ||||||
|   gem 'opentelemetry-instrumentation-aws_sdk', feature_category: :tooling |   gem 'opentelemetry-instrumentation-aws_sdk', feature_category: :tooling | ||||||
|   gem 'opentelemetry-instrumentation-http', feature_category: :tooling |   gem 'opentelemetry-instrumentation-http', feature_category: :tooling | ||||||
|   gem 'opentelemetry-instrumentation-active_model_serializers', feature_category: :tooling |  | ||||||
|   gem 'opentelemetry-instrumentation-concurrent_ruby', feature_category: :tooling |   gem 'opentelemetry-instrumentation-concurrent_ruby', feature_category: :tooling | ||||||
|   gem 'opentelemetry-instrumentation-ethon', feature_category: :tooling |   gem 'opentelemetry-instrumentation-ethon', feature_category: :tooling | ||||||
|   gem 'opentelemetry-instrumentation-excon', feature_category: :tooling |   gem 'opentelemetry-instrumentation-excon', feature_category: :tooling | ||||||
|  | @ -592,7 +590,7 @@ gem 'ssh_data', '~> 1.3' # rubocop:todo Gemfile/MissingFeatureCategory | ||||||
| gem 'spamcheck', '~> 1.3.0' # rubocop:todo Gemfile/MissingFeatureCategory | gem 'spamcheck', '~> 1.3.0' # rubocop:todo Gemfile/MissingFeatureCategory | ||||||
| 
 | 
 | ||||||
| # Gitaly GRPC protocol definitions | # Gitaly GRPC protocol definitions | ||||||
| gem 'gitaly', '~> 16.11.0.pre.rc1', feature_category: :gitaly | gem 'gitaly', '~> 17.0.0.pre.rc2', feature_category: :gitaly | ||||||
| 
 | 
 | ||||||
| # KAS GRPC protocol definitions | # KAS GRPC protocol definitions | ||||||
| gem 'kas-grpc', '~> 0.4.0', feature_category: :deployment_management | gem 'kas-grpc', '~> 0.4.0', feature_category: :deployment_management | ||||||
|  |  | ||||||
|  | @ -206,7 +206,7 @@ | ||||||
| {"name":"gettext","version":"3.4.9","platform":"ruby","checksum":"292864fe6a15c224cee4125a4a72fab426fdbb280e4cff3cfe44935f549b009a"}, | {"name":"gettext","version":"3.4.9","platform":"ruby","checksum":"292864fe6a15c224cee4125a4a72fab426fdbb280e4cff3cfe44935f549b009a"}, | ||||||
| {"name":"gettext_i18n_rails","version":"1.12.0","platform":"ruby","checksum":"6ac4817731a9e2ce47e1e83381ac34f9142263bc2911aaaafb2526d2f1afc1be"}, | {"name":"gettext_i18n_rails","version":"1.12.0","platform":"ruby","checksum":"6ac4817731a9e2ce47e1e83381ac34f9142263bc2911aaaafb2526d2f1afc1be"}, | ||||||
| {"name":"git","version":"1.18.0","platform":"ruby","checksum":"c9b80462e4565cd3d7a9ba8440c41d2c52244b17b0dad0bfddb46de70630c465"}, | {"name":"git","version":"1.18.0","platform":"ruby","checksum":"c9b80462e4565cd3d7a9ba8440c41d2c52244b17b0dad0bfddb46de70630c465"}, | ||||||
| {"name":"gitaly","version":"16.11.0.pre.rc1","platform":"ruby","checksum":"24334f5f3fd5b6c3d278eea9fe2b6732dd08e87a4146cd4374615506b1a6e7ae"}, | {"name":"gitaly","version":"17.0.0.pre.rc2","platform":"ruby","checksum":"2fa5998d3cbc37ba66bef428fb7150ab3f8b4105a4bd29ea48d965fae98ead43"}, | ||||||
| {"name":"gitlab","version":"4.19.0","platform":"ruby","checksum":"3f645e3e195dbc24f0834fbf83e8ccfb2056d8e9712b01a640aad418a6949679"}, | {"name":"gitlab","version":"4.19.0","platform":"ruby","checksum":"3f645e3e195dbc24f0834fbf83e8ccfb2056d8e9712b01a640aad418a6949679"}, | ||||||
| {"name":"gitlab-chronic","version":"0.10.5","platform":"ruby","checksum":"f80f18dc699b708870a80685243331290bc10cfeedb6b99c92219722f729c875"}, | {"name":"gitlab-chronic","version":"0.10.5","platform":"ruby","checksum":"f80f18dc699b708870a80685243331290bc10cfeedb6b99c92219722f729c875"}, | ||||||
| {"name":"gitlab-dangerfiles","version":"4.7.0","platform":"ruby","checksum":"2576876a8dcb7290853fc3aef8048001cfe593b87318dd0016959d42e0e145ca"}, | {"name":"gitlab-dangerfiles","version":"4.7.0","platform":"ruby","checksum":"2576876a8dcb7290853fc3aef8048001cfe593b87318dd0016959d42e0e145ca"}, | ||||||
|  | @ -453,7 +453,6 @@ | ||||||
| {"name":"opentelemetry-instrumentation-action_pack","version":"0.9.0","platform":"ruby","checksum":"c5df8472afc9cdbfc1425d9af7816b9cfc1a1a69b86621f1fc624974bd9acb9a"}, | {"name":"opentelemetry-instrumentation-action_pack","version":"0.9.0","platform":"ruby","checksum":"c5df8472afc9cdbfc1425d9af7816b9cfc1a1a69b86621f1fc624974bd9acb9a"}, | ||||||
| {"name":"opentelemetry-instrumentation-action_view","version":"0.7.0","platform":"ruby","checksum":"bc7c714be0b4bb76843085c29ecc9465e65cb7fe6722e34c71629e44f8c3cb75"}, | {"name":"opentelemetry-instrumentation-action_view","version":"0.7.0","platform":"ruby","checksum":"bc7c714be0b4bb76843085c29ecc9465e65cb7fe6722e34c71629e44f8c3cb75"}, | ||||||
| {"name":"opentelemetry-instrumentation-active_job","version":"0.7.1","platform":"ruby","checksum":"da24806c9d92fe580db42638f6c763fe1324ff90aa147d45d4247f8052c68089"}, | {"name":"opentelemetry-instrumentation-active_job","version":"0.7.1","platform":"ruby","checksum":"da24806c9d92fe580db42638f6c763fe1324ff90aa147d45d4247f8052c68089"}, | ||||||
| {"name":"opentelemetry-instrumentation-active_model_serializers","version":"0.20.1","platform":"ruby","checksum":"8c47f859fc925c4c078d37f5a13c55f4ba9751f880aa64d0c9568f3f59a3efaa"}, |  | ||||||
| {"name":"opentelemetry-instrumentation-active_record","version":"0.7.0","platform":"ruby","checksum":"327ca53ebb74187b463ab05c1d89508552e9cd9122db0843ad1f27930ee91797"}, | {"name":"opentelemetry-instrumentation-active_record","version":"0.7.0","platform":"ruby","checksum":"327ca53ebb74187b463ab05c1d89508552e9cd9122db0843ad1f27930ee91797"}, | ||||||
| {"name":"opentelemetry-instrumentation-active_support","version":"0.5.1","platform":"ruby","checksum":"03898327e8284410b8935a3d3b980bda56e2063eb5a7d30acf75487dd6934a66"}, | {"name":"opentelemetry-instrumentation-active_support","version":"0.5.1","platform":"ruby","checksum":"03898327e8284410b8935a3d3b980bda56e2063eb5a7d30acf75487dd6934a66"}, | ||||||
| {"name":"opentelemetry-instrumentation-aws_sdk","version":"0.5.1","platform":"ruby","checksum":"496a8d13c59ff4d08dcd69b16db97c013398173295058593aa0c2f3ef3090cce"}, | {"name":"opentelemetry-instrumentation-aws_sdk","version":"0.5.1","platform":"ruby","checksum":"496a8d13c59ff4d08dcd69b16db97c013398173295058593aa0c2f3ef3090cce"}, | ||||||
|  | @ -623,7 +622,6 @@ | ||||||
| {"name":"selenium-webdriver","version":"4.19.0","platform":"ruby","checksum":"4c8bd1d6016a456154b4ba71a3bb4d532a0ae185a38acf9cec0acbd38b4e5066"}, | {"name":"selenium-webdriver","version":"4.19.0","platform":"ruby","checksum":"4c8bd1d6016a456154b4ba71a3bb4d532a0ae185a38acf9cec0acbd38b4e5066"}, | ||||||
| {"name":"semver_dialects","version":"2.0.2","platform":"ruby","checksum":"60059c9f416f931b5212d862fad2879d6b9affb8e0b9afb0d91b793639c116fe"}, | {"name":"semver_dialects","version":"2.0.2","platform":"ruby","checksum":"60059c9f416f931b5212d862fad2879d6b9affb8e0b9afb0d91b793639c116fe"}, | ||||||
| {"name":"sentry-rails","version":"5.10.0","platform":"ruby","checksum":"99aa2fac136c26942eb1897c65de65dac88ad43ac5eb183ff20711287a137ebd"}, | {"name":"sentry-rails","version":"5.10.0","platform":"ruby","checksum":"99aa2fac136c26942eb1897c65de65dac88ad43ac5eb183ff20711287a137ebd"}, | ||||||
| {"name":"sentry-raven","version":"3.1.2","platform":"ruby","checksum":"103d3b122958810d34898ce2e705bcf549ddb9d855a70ce9a3970ee2484f364a"}, |  | ||||||
| {"name":"sentry-ruby","version":"5.10.0","platform":"ruby","checksum":"115c24c0aee1309210f3a2988fb118e2bec1f11609feeda90e694388b1183619"}, | {"name":"sentry-ruby","version":"5.10.0","platform":"ruby","checksum":"115c24c0aee1309210f3a2988fb118e2bec1f11609feeda90e694388b1183619"}, | ||||||
| {"name":"sentry-sidekiq","version":"5.10.0","platform":"ruby","checksum":"cc81018d0733fb1be3fb5641c9e0b61030bbeaa1d0b23ca64797d70def7aea1a"}, | {"name":"sentry-sidekiq","version":"5.10.0","platform":"ruby","checksum":"cc81018d0733fb1be3fb5641c9e0b61030bbeaa1d0b23ca64797d70def7aea1a"}, | ||||||
| {"name":"sexp_processor","version":"4.17.1","platform":"ruby","checksum":"91110946720307f30bf1d549e90d9a529fef40d1fc471c069c8cca7667015da0"}, | {"name":"sexp_processor","version":"4.17.1","platform":"ruby","checksum":"91110946720307f30bf1d549e90d9a529fef40d1fc471c069c8cca7667015da0"}, | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								Gemfile.lock
								
								
								
								
							
							
						
						
									
										11
									
								
								Gemfile.lock
								
								
								
								
							|  | @ -680,7 +680,7 @@ GEM | ||||||
|     git (1.18.0) |     git (1.18.0) | ||||||
|       addressable (~> 2.8) |       addressable (~> 2.8) | ||||||
|       rchardet (~> 1.8) |       rchardet (~> 1.8) | ||||||
|     gitaly (16.11.0.pre.rc1) |     gitaly (17.0.0.pre.rc2) | ||||||
|       grpc (~> 1.0) |       grpc (~> 1.0) | ||||||
|     gitlab (4.19.0) |     gitlab (4.19.0) | ||||||
|       httparty (~> 0.20) |       httparty (~> 0.20) | ||||||
|  | @ -1253,9 +1253,6 @@ GEM | ||||||
|     opentelemetry-instrumentation-active_job (0.7.1) |     opentelemetry-instrumentation-active_job (0.7.1) | ||||||
|       opentelemetry-api (~> 1.0) |       opentelemetry-api (~> 1.0) | ||||||
|       opentelemetry-instrumentation-base (~> 0.22.1) |       opentelemetry-instrumentation-base (~> 0.22.1) | ||||||
|     opentelemetry-instrumentation-active_model_serializers (0.20.1) |  | ||||||
|       opentelemetry-api (~> 1.0) |  | ||||||
|       opentelemetry-instrumentation-base (~> 0.22.1) |  | ||||||
|     opentelemetry-instrumentation-active_record (0.7.0) |     opentelemetry-instrumentation-active_record (0.7.0) | ||||||
|       opentelemetry-api (~> 1.0) |       opentelemetry-api (~> 1.0) | ||||||
|       opentelemetry-instrumentation-base (~> 0.22.1) |       opentelemetry-instrumentation-base (~> 0.22.1) | ||||||
|  | @ -1669,8 +1666,6 @@ GEM | ||||||
|     sentry-rails (5.10.0) |     sentry-rails (5.10.0) | ||||||
|       railties (>= 5.0) |       railties (>= 5.0) | ||||||
|       sentry-ruby (~> 5.10.0) |       sentry-ruby (~> 5.10.0) | ||||||
|     sentry-raven (3.1.2) |  | ||||||
|       faraday (>= 1.0) |  | ||||||
|     sentry-ruby (5.10.0) |     sentry-ruby (5.10.0) | ||||||
|       concurrent-ruby (~> 1.0, >= 1.0.2) |       concurrent-ruby (~> 1.0, >= 1.0.2) | ||||||
|     sentry-sidekiq (5.10.0) |     sentry-sidekiq (5.10.0) | ||||||
|  | @ -2008,7 +2003,7 @@ DEPENDENCIES | ||||||
|   gdk-toogle (~> 0.9) |   gdk-toogle (~> 0.9) | ||||||
|   gettext (~> 3.4, >= 3.4.9) |   gettext (~> 3.4, >= 3.4.9) | ||||||
|   gettext_i18n_rails (~> 1.12.0) |   gettext_i18n_rails (~> 1.12.0) | ||||||
|   gitaly (~> 16.11.0.pre.rc1) |   gitaly (~> 17.0.0.pre.rc2) | ||||||
|   gitlab-backup-cli! |   gitlab-backup-cli! | ||||||
|   gitlab-chronic (~> 0.10.5) |   gitlab-chronic (~> 0.10.5) | ||||||
|   gitlab-dangerfiles (~> 4.7.0) |   gitlab-dangerfiles (~> 4.7.0) | ||||||
|  | @ -2142,7 +2137,6 @@ DEPENDENCIES | ||||||
|   opentelemetry-instrumentation-action_pack |   opentelemetry-instrumentation-action_pack | ||||||
|   opentelemetry-instrumentation-action_view |   opentelemetry-instrumentation-action_view | ||||||
|   opentelemetry-instrumentation-active_job |   opentelemetry-instrumentation-active_job | ||||||
|   opentelemetry-instrumentation-active_model_serializers |  | ||||||
|   opentelemetry-instrumentation-active_record |   opentelemetry-instrumentation-active_record | ||||||
|   opentelemetry-instrumentation-active_support |   opentelemetry-instrumentation-active_support | ||||||
|   opentelemetry-instrumentation-aws_sdk |   opentelemetry-instrumentation-aws_sdk | ||||||
|  | @ -2224,7 +2218,6 @@ DEPENDENCIES | ||||||
|   selenium-webdriver (~> 4.19) |   selenium-webdriver (~> 4.19) | ||||||
|   semver_dialects (~> 2.0, >= 2.0.2) |   semver_dialects (~> 2.0, >= 2.0.2) | ||||||
|   sentry-rails (~> 5.10.0) |   sentry-rails (~> 5.10.0) | ||||||
|   sentry-raven (~> 3.1) |  | ||||||
|   sentry-ruby (~> 5.10.0) |   sentry-ruby (~> 5.10.0) | ||||||
|   sentry-sidekiq (~> 5.10.0) |   sentry-sidekiq (~> 5.10.0) | ||||||
|   shoulda-matchers (~> 5.1.0) |   shoulda-matchers (~> 5.1.0) | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils'; | ||||||
| import { cleanLeadingSeparator } from '~/lib/utils/url_utility'; | import { cleanLeadingSeparator } from '~/lib/utils/url_utility'; | ||||||
| import { formatDate } from '~/lib/utils/datetime_utility'; | import { formatDate } from '~/lib/utils/datetime_utility'; | ||||||
| import AbuseCategorySelector from '~/abuse_reports/components/abuse_category_selector.vue'; | import AbuseCategorySelector from '~/abuse_reports/components/abuse_category_selector.vue'; | ||||||
|  | import Markdown from '~/vue_shared/components/markdown/non_gfm_markdown.vue'; | ||||||
| import CiVerificationBadge from '../shared/ci_verification_badge.vue'; | import CiVerificationBadge from '../shared/ci_verification_badge.vue'; | ||||||
| import CiResourceAbout from './ci_resource_about.vue'; | import CiResourceAbout from './ci_resource_about.vue'; | ||||||
| import CiResourceHeaderSkeletonLoader from './ci_resource_header_skeleton_loader.vue'; | import CiResourceHeaderSkeletonLoader from './ci_resource_header_skeleton_loader.vue'; | ||||||
|  | @ -35,6 +36,7 @@ export default { | ||||||
|     GlDisclosureDropdown, |     GlDisclosureDropdown, | ||||||
|     GlDisclosureDropdownItem, |     GlDisclosureDropdownItem, | ||||||
|     GlLink, |     GlLink, | ||||||
|  |     Markdown, | ||||||
|   }, |   }, | ||||||
|   directives: { |   directives: { | ||||||
|     GlTooltip: GlTooltipDirective, |     GlTooltip: GlTooltipDirective, | ||||||
|  | @ -198,9 +200,7 @@ export default { | ||||||
|       v-if="isLoadingSharedData" |       v-if="isLoadingSharedData" | ||||||
|       class="gl-animate-skeleton-loader gl-h-4 gl-rounded-base gl-my-3 gl-max-w-20!" |       class="gl-animate-skeleton-loader gl-h-4 gl-rounded-base gl-my-3 gl-max-w-20!" | ||||||
|     ></div> |     ></div> | ||||||
|     <p v-else class="gl-mt-2"> |     <markdown v-else class="gl-mt-2" :markdown="resource.description" /> | ||||||
|       {{ resource.description }} |  | ||||||
|     </p> |  | ||||||
|     <abuse-category-selector |     <abuse-category-selector | ||||||
|       v-if="hasLatestVersion && isReportAbuseDrawerOpen && reportAbusePath" |       v-if="hasLatestVersion && isReportAbuseDrawerOpen && reportAbusePath" | ||||||
|       :reported-user-id="authorId" |       :reported-user-id="authorId" | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils'; | ||||||
| import { formatDate, getTimeago } from '~/lib/utils/datetime_utility'; | import { formatDate, getTimeago } from '~/lib/utils/datetime_utility'; | ||||||
| import { toNounSeriesText } from '~/lib/utils/grammar'; | import { toNounSeriesText } from '~/lib/utils/grammar'; | ||||||
| import { cleanLeadingSeparator } from '~/lib/utils/url_utility'; | import { cleanLeadingSeparator } from '~/lib/utils/url_utility'; | ||||||
|  | import Markdown from '~/vue_shared/components/markdown/non_gfm_markdown.vue'; | ||||||
| import { CI_RESOURCE_DETAILS_PAGE_NAME } from '../../router/constants'; | import { CI_RESOURCE_DETAILS_PAGE_NAME } from '../../router/constants'; | ||||||
| import CiVerificationBadge from '../shared/ci_verification_badge.vue'; | import CiVerificationBadge from '../shared/ci_verification_badge.vue'; | ||||||
| 
 | 
 | ||||||
|  | @ -30,6 +31,7 @@ export default { | ||||||
|     GlLink, |     GlLink, | ||||||
|     GlSprintf, |     GlSprintf, | ||||||
|     GlTruncate, |     GlTruncate, | ||||||
|  |     Markdown, | ||||||
|   }, |   }, | ||||||
|   directives: { |   directives: { | ||||||
|     GlTooltip: GlTooltipDirective, |     GlTooltip: GlTooltipDirective, | ||||||
|  | @ -183,7 +185,10 @@ export default { | ||||||
|         class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-justify-content-space-between gl-font-sm" |         class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-justify-content-space-between gl-font-sm" | ||||||
|       > |       > | ||||||
|         <div> |         <div> | ||||||
|           <span class="gl-display-flex gl-flex-basis-two-thirds">{{ resource.description }}</span> |           <markdown | ||||||
|  |             class="gl-display-flex gl-flex-basis-two-thirds" | ||||||
|  |             :markdown="resource.description" | ||||||
|  |           /> | ||||||
|           <div |           <div | ||||||
|             v-if="hasComponents" |             v-if="hasComponents" | ||||||
|             data-testid="ci-resource-component-names" |             data-testid="ci-resource-component-names" | ||||||
|  |  | ||||||
|  | @ -9,6 +9,13 @@ function reportErrorAndThrow(e) { | ||||||
|   Sentry.captureException(e); |   Sentry.captureException(e); | ||||||
|   throw e; |   throw e; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /** **** | ||||||
|  |  * | ||||||
|  |  * Provisioning API | ||||||
|  |  * | ||||||
|  |  * ***** */ | ||||||
|  | 
 | ||||||
| // Provisioning API spec: https://gitlab.com/gitlab-org/opstrace/opstrace/-/blob/main/provisioning-api/pkg/provisioningapi/routes.go#L59
 | // Provisioning API spec: https://gitlab.com/gitlab-org/opstrace/opstrace/-/blob/main/provisioning-api/pkg/provisioningapi/routes.go#L59
 | ||||||
| async function enableObservability(provisioningUrl) { | async function enableObservability(provisioningUrl) { | ||||||
|   try { |   try { | ||||||
|  | @ -40,6 +47,97 @@ async function isObservabilityEnabled(provisioningUrl) { | ||||||
|   return reportErrorAndThrow(new Error('Failed to check provisioning')); // eslint-disable-line @gitlab/require-i18n-strings
 |   return reportErrorAndThrow(new Error('Failed to check provisioning')); // eslint-disable-line @gitlab/require-i18n-strings
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** **** | ||||||
|  |  * | ||||||
|  |  * Common utils | ||||||
|  |  * | ||||||
|  |  * ***** */ | ||||||
|  | 
 | ||||||
|  | const FILTER_OPERATORS_PREFIX = { | ||||||
|  |   '!=': 'not', | ||||||
|  |   '>': 'gt', | ||||||
|  |   '<': 'lt', | ||||||
|  |   '!~': 'not_like', | ||||||
|  |   '=~': 'like', | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const SEARCH_FILTER_NAME = 'search'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Return the query parameter name, given an operator and param key | ||||||
|  |  * | ||||||
|  |  * e.g | ||||||
|  |  *    if paramKey is 'foo' and operator is "=", param name is 'foo' | ||||||
|  |  *    if paramKey is 'foo' and operator is "!=", param name is 'not[foo]' | ||||||
|  |  * | ||||||
|  |  * @param {String} paramKey - The parameter name | ||||||
|  |  * @param {String} operator - The operator | ||||||
|  |  * @returns String | undefined - Query param name | ||||||
|  |  */ | ||||||
|  | function getFilterParamName(filterName, operator, filterToQueryMapping) { | ||||||
|  |   const paramKey = filterToQueryMapping[filterName]; | ||||||
|  |   if (!paramKey) return undefined; | ||||||
|  | 
 | ||||||
|  |   if (operator === '=' || filterName === SEARCH_FILTER_NAME) { | ||||||
|  |     return paramKey; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const prefix = FILTER_OPERATORS_PREFIX[operator]; | ||||||
|  |   if (prefix) { | ||||||
|  |     return `${prefix}[${paramKey}]`; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return undefined; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Process `filterValue` and append the proper query params to the  `searchParams` arg, using `nameParam` and `valueParam` | ||||||
|  |  * | ||||||
|  |  * It mutates `searchParams` | ||||||
|  |  * | ||||||
|  |  * @param {String} filterValue The filter value, in the format `attribute_name=attribute_value` | ||||||
|  |  * @param {String} filterOperator The filter operator | ||||||
|  |  * @param {URLSearchParams} searchParams The URLSearchParams object where to append the proper query params | ||||||
|  |  * @param {String} nameParam The query param name for the attribute name | ||||||
|  |  * @param {String} nameParam The query param name for the attribute value | ||||||
|  |  * | ||||||
|  |  * e.g. | ||||||
|  |  * | ||||||
|  |  *    handleAttributeFilter('foo=bar', '=', searchParams, 'attr_name', 'attr_value') | ||||||
|  |  * | ||||||
|  |  *        it adds { attr_name: 'foo', attr_value: 'bar'} to `searchParams` | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | function handleAttributeFilter(filterValue, filterOperator, searchParams, nameParam, valueParam) { | ||||||
|  |   const [attrName, attrValue] = filterValue.split('='); | ||||||
|  |   if (attrName && attrValue) { | ||||||
|  |     if (filterOperator === '=') { | ||||||
|  |       searchParams.append(nameParam, attrName); | ||||||
|  |       searchParams.append(valueParam, attrValue); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function addDateRangeFilterToQueryParams(dateRangeFilter, params) { | ||||||
|  |   if (!dateRangeFilter || !params) return; | ||||||
|  | 
 | ||||||
|  |   const { value, endDate, startDate } = dateRangeFilter; | ||||||
|  |   if (value === CUSTOM_DATE_RANGE_OPTION) { | ||||||
|  |     if (isValidDate(startDate) && isValidDate(endDate)) { | ||||||
|  |       params.append('start_time', startDate.toISOString()); | ||||||
|  |       params.append('end_time', endDate.toISOString()); | ||||||
|  |     } | ||||||
|  |   } else if (typeof value === 'string') { | ||||||
|  |     params.append('period', value); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** **** | ||||||
|  |  * | ||||||
|  |  * Tracing API | ||||||
|  |  * | ||||||
|  |  * ***** */ | ||||||
|  | 
 | ||||||
| async function fetchTrace(tracingUrl, traceId) { | async function fetchTrace(tracingUrl, traceId) { | ||||||
|   try { |   try { | ||||||
|     if (!traceId) { |     if (!traceId) { | ||||||
|  | @ -67,88 +165,23 @@ const SUPPORTED_TRACING_FILTERS = { | ||||||
|   traceId: ['=', '!='], |   traceId: ['=', '!='], | ||||||
|   attribute: ['='], |   attribute: ['='], | ||||||
|   status: ['=', '!='], |   status: ['=', '!='], | ||||||
|   // free-text 'search' temporarily ignored https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2309
 |   // 'search' temporarily ignored https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2309
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Mapping of filter name to query param |  * Mapping of filter name to tracing query param | ||||||
|  */ |  */ | ||||||
| const TRACING_FILTER_TO_QUERY_PARAM = { | const TRACING_FILTER_TO_QUERY_PARAM = { | ||||||
|   durationMs: 'duration_nano', |   durationMs: 'duration_nano', | ||||||
|   operation: 'operation', |   operation: 'operation', | ||||||
|   service: 'service_name', |   service: 'service_name', | ||||||
|   period: 'period', |  | ||||||
|   traceId: 'trace_id', |   traceId: 'trace_id', | ||||||
|   attribute: 'attribute', |  | ||||||
|   status: 'status', |   status: 'status', | ||||||
|  |   // `attribute` is handled separately, see `handleAttributeFilter` method
 | ||||||
|  |   // `period` is handled separately, see `handleTracingPeriodFilter` method
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const FILTER_OPERATORS_PREFIX = { | function handleTracingPeriodFilter(rawValue, filterName, filterParams) { | ||||||
|   '!=': 'not', |  | ||||||
|   '>': 'gt', |  | ||||||
|   '<': 'lt', |  | ||||||
|   '!~': 'not_like', |  | ||||||
|   '=~': 'like', |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Return the query parameter name, given an operator and param key |  | ||||||
|  * |  | ||||||
|  * e.g |  | ||||||
|  *    if paramKey is 'foo' and operator is "=", param name is 'foo' |  | ||||||
|  *    if paramKey is 'foo' and operator is "!=", param name is 'not[foo]' |  | ||||||
|  * |  | ||||||
|  * @param {String} paramKey - The parameter name |  | ||||||
|  * @param {String} operator - The operator |  | ||||||
|  * @returns String | undefined - Query param name |  | ||||||
|  */ |  | ||||||
| function getFilterParamName(paramKey, operator) { |  | ||||||
|   if (operator === '=') { |  | ||||||
|     return paramKey; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   const prefix = FILTER_OPERATORS_PREFIX[operator]; |  | ||||||
|   if (prefix) { |  | ||||||
|     return `${prefix}[${paramKey}]`; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return undefined; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Builds the tracing query param name for the given filter and operator |  | ||||||
|  * |  | ||||||
|  * @param {String} filterName - The filter name |  | ||||||
|  * @param {String} operator - The operator |  | ||||||
|  * @returns String | undefined - Query param name |  | ||||||
|  */ |  | ||||||
| function getTracingFilterParamName(filterName, operator) { |  | ||||||
|   const paramKey = TRACING_FILTER_TO_QUERY_PARAM[filterName]; |  | ||||||
|   if (!paramKey) return undefined; |  | ||||||
| 
 |  | ||||||
|   return getFilterParamName(paramKey, operator); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Process `filterValue` and append the proper query params to the  `searchParams` arg |  | ||||||
|  * |  | ||||||
|  * It mutates `searchParams` |  | ||||||
|  * |  | ||||||
|  * @param {String} filterValue The filter value, in the format `attribute_name=attribute_value` |  | ||||||
|  * @param {String} filterOperator The filter operator |  | ||||||
|  * @param {URLSearchParams} searchParams The URLSearchParams object where to append the proper query params |  | ||||||
|  */ |  | ||||||
| function handleAttributeFilter(filterValue, filterOperator, searchParams) { |  | ||||||
|   const [attrName, attrValue] = filterValue.split('='); |  | ||||||
|   if (attrName && attrValue) { |  | ||||||
|     if (filterOperator === '=') { |  | ||||||
|       searchParams.append('attr_name', attrName); |  | ||||||
|       searchParams.append('attr_value', attrValue); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function handlePeriodFilter(rawValue, filterName, filterParams) { |  | ||||||
|   if (rawValue.trim().indexOf(' ') < 0) { |   if (rawValue.trim().indexOf(' ') < 0) { | ||||||
|     filterParams.append(filterName, rawValue.trim()); |     filterParams.append(filterName, rawValue.trim()); | ||||||
|     return; |     return; | ||||||
|  | @ -189,13 +222,14 @@ function tracingFilterObjToQueryParams(filterObj) { | ||||||
|     const validFilters = filterValues.filter((f) => |     const validFilters = filterValues.filter((f) => | ||||||
|       SUPPORTED_TRACING_FILTERS[filterName].includes(f.operator), |       SUPPORTED_TRACING_FILTERS[filterName].includes(f.operator), | ||||||
|     ); |     ); | ||||||
|  | 
 | ||||||
|     validFilters.forEach(({ operator, value: rawValue }) => { |     validFilters.forEach(({ operator, value: rawValue }) => { | ||||||
|       if (filterName === 'attribute') { |       if (filterName === 'attribute') { | ||||||
|         handleAttributeFilter(rawValue, operator, filterParams); |         handleAttributeFilter(rawValue, operator, filterParams, 'attr_name', 'attr_value'); | ||||||
|       } else if (filterName === 'period') { |       } else if (filterName === 'period') { | ||||||
|         handlePeriodFilter(rawValue, filterName, filterParams); |         handleTracingPeriodFilter(rawValue, filterName, filterParams); | ||||||
|       } else { |       } else { | ||||||
|         const paramName = getTracingFilterParamName(filterName, operator); |         const paramName = getFilterParamName(filterName, operator, TRACING_FILTER_TO_QUERY_PARAM); | ||||||
|         let value = rawValue; |         let value = rawValue; | ||||||
|         if (filterName === 'durationMs') { |         if (filterName === 'durationMs') { | ||||||
|           // converting durationMs to duration_nano
 |           // converting durationMs to duration_nano
 | ||||||
|  | @ -318,6 +352,12 @@ function handleMetricsAttributeFilters(attributeFilters, params) { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** **** | ||||||
|  |  * | ||||||
|  |  * Metrics API | ||||||
|  |  * | ||||||
|  |  * ***** */ | ||||||
|  | 
 | ||||||
| async function fetchMetrics(metricsUrl, { filters = {}, limit } = {}) { | async function fetchMetrics(metricsUrl, { filters = {}, limit } = {}) { | ||||||
|   try { |   try { | ||||||
|     const params = new URLSearchParams(); |     const params = new URLSearchParams(); | ||||||
|  | @ -359,6 +399,7 @@ const SUPPORTED_METRICS_DIMENSIONS_OPERATORS = { | ||||||
|   '=~': 're', |   '=~': 're', | ||||||
|   '!~': 'nre', |   '!~': 'nre', | ||||||
| }; | }; | ||||||
|  | 
 | ||||||
| function addMetricsAttributeFilterToQueryParams(dimensionFilter, params) { | function addMetricsAttributeFilterToQueryParams(dimensionFilter, params) { | ||||||
|   if (!dimensionFilter || !params) return; |   if (!dimensionFilter || !params) return; | ||||||
| 
 | 
 | ||||||
|  | @ -374,21 +415,7 @@ function addMetricsAttributeFilterToQueryParams(dimensionFilter, params) { | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function addDateRangeFilterToQueryParams(dateRangeFilter, params) { | function addMetricsGroupByFilterToQueryParams(groupByFilter, params) { | ||||||
|   if (!dateRangeFilter || !params) return; |  | ||||||
| 
 |  | ||||||
|   const { value, endDate, startDate } = dateRangeFilter; |  | ||||||
|   if (value === CUSTOM_DATE_RANGE_OPTION) { |  | ||||||
|     if (isValidDate(startDate) && isValidDate(endDate)) { |  | ||||||
|       params.append('start_time', startDate.toISOString()); |  | ||||||
|       params.append('end_time', endDate.toISOString()); |  | ||||||
|     } |  | ||||||
|   } else if (typeof value === 'string') { |  | ||||||
|     params.append('period', value); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function addGroupByFilterToQueryParams(groupByFilter, params) { |  | ||||||
|   if (!groupByFilter || !params) return; |   if (!groupByFilter || !params) return; | ||||||
| 
 | 
 | ||||||
|   const { func, attributes } = groupByFilter; |   const { func, attributes } = groupByFilter; | ||||||
|  | @ -429,7 +456,7 @@ async function fetchMetric(searchUrl, name, type, options = {}) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (groupBy) { |     if (groupBy) { | ||||||
|       addGroupByFilterToQueryParams(groupBy, params); |       addMetricsGroupByFilterToQueryParams(groupBy, params); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const { data } = await axios.get(searchUrl, { |     const { data } = await axios.get(searchUrl, { | ||||||
|  | @ -470,15 +497,95 @@ async function fetchMetricSearchMetadata(searchMetadataUrl, name, type) { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** **** | ||||||
|  |  * | ||||||
|  |  * Logs API | ||||||
|  |  * | ||||||
|  |  * ***** */ | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Filters (and operators) allowed by logs query API | ||||||
|  |  */ | ||||||
|  | const SUPPORTED_LOGS_FILTERS = { | ||||||
|  |   service: ['=', '!='], | ||||||
|  |   severityName: ['=', '!='], | ||||||
|  |   traceId: ['='], | ||||||
|  |   spanId: ['='], | ||||||
|  |   fingerprint: ['='], | ||||||
|  |   traceFlags: ['=', '!='], | ||||||
|  |   attribute: ['='], | ||||||
|  |   resourceAttribute: ['='], | ||||||
|  |   search: [], // 'search' filter does not have any operator
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Mapping of filter name to query param | ||||||
|  |  */ | ||||||
|  | const LOGS_FILTER_TO_QUERY_PARAM = { | ||||||
|  |   service: 'service_name', | ||||||
|  |   severityName: 'severity_name', | ||||||
|  |   traceId: 'trace_id', | ||||||
|  |   spanId: 'span_id', | ||||||
|  |   fingerprint: 'fingerprint', | ||||||
|  |   traceFlags: 'trace_flags', | ||||||
|  |   search: 'body', | ||||||
|  |   // `attribute` and `resource_attribute` are handled separately
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Builds URLSearchParams from a filter object of type { [filterName]: undefined | null | Array<{operator: String, value: any} } | ||||||
|  |  *  e.g: | ||||||
|  |  * | ||||||
|  |  *  filterObj =  { | ||||||
|  |  *      severityName: [{operator: '=', value: 'info' }], | ||||||
|  |  *      service: [{operator: '!=', value: 'foo' }] | ||||||
|  |  *    } | ||||||
|  |  * | ||||||
|  |  * It handles converting the filter to the proper supported query params | ||||||
|  |  * | ||||||
|  |  * @param {Object} filterObj : An Object representing handleAttributeFilter | ||||||
|  |  * @returns URLSearchParams | ||||||
|  |  */ | ||||||
|  | function addLogsAttributesFiltersToQueryParams(filterObj, filterParams) { | ||||||
|  |   Object.keys(SUPPORTED_LOGS_FILTERS).forEach((filterName) => { | ||||||
|  |     const filterValues = Array.isArray(filterObj[filterName]) | ||||||
|  |       ? filterObj[filterName].filter(({ value }) => Boolean(value)) // ignore empty strings
 | ||||||
|  |       : []; | ||||||
|  |     const validFilters = filterValues.filter( | ||||||
|  |       (f) => | ||||||
|  |         (filterName === SEARCH_FILTER_NAME && SUPPORTED_LOGS_FILTERS[filterName]) || | ||||||
|  |         SUPPORTED_LOGS_FILTERS[filterName].includes(f.operator), | ||||||
|  |     ); | ||||||
|  |     validFilters.forEach(({ operator, value: rawValue }) => { | ||||||
|  |       if (filterName === 'attribute') { | ||||||
|  |         handleAttributeFilter(rawValue, operator, filterParams, 'log_attr_name', 'log_attr_value'); | ||||||
|  |       } else if (filterName === 'resourceAttribute') { | ||||||
|  |         handleAttributeFilter(rawValue, operator, filterParams, 'res_attr_name', 'res_attr_value'); | ||||||
|  |       } else { | ||||||
|  |         const paramName = getFilterParamName(filterName, operator, LOGS_FILTER_TO_QUERY_PARAM); | ||||||
|  |         const value = rawValue; | ||||||
|  |         if (paramName && value) { | ||||||
|  |           filterParams.append(paramName, value); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |   return filterParams; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export async function fetchLogs(logsSearchUrl, { pageToken, pageSize, filters = {} } = {}) { | export async function fetchLogs(logsSearchUrl, { pageToken, pageSize, filters = {} } = {}) { | ||||||
|   try { |   try { | ||||||
|     const params = new URLSearchParams(); |     const params = new URLSearchParams(); | ||||||
| 
 | 
 | ||||||
|     const { dateRange } = filters; |     const { dateRange, attributes } = filters; | ||||||
|     if (dateRange) { |     if (dateRange) { | ||||||
|       addDateRangeFilterToQueryParams(dateRange, params); |       addDateRangeFilterToQueryParams(dateRange, params); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (attributes) { | ||||||
|  |       addLogsAttributesFiltersToQueryParams(attributes, params); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     if (pageToken) { |     if (pageToken) { | ||||||
|       params.append('page_token', pageToken); |       params.append('page_token', pageToken); | ||||||
|     } |     } | ||||||
|  | @ -501,6 +608,12 @@ export async function fetchLogs(logsSearchUrl, { pageToken, pageSize, filters = | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** **** | ||||||
|  |  * | ||||||
|  |  * ObservabilityClient | ||||||
|  |  * | ||||||
|  |  * ***** */ | ||||||
|  | 
 | ||||||
| export function buildClient(config) { | export function buildClient(config) { | ||||||
|   if (!config) { |   if (!config) { | ||||||
|     throw new Error('No options object provided'); // eslint-disable-line @gitlab/require-i18n-strings
 |     throw new Error('No options object provided'); // eslint-disable-line @gitlab/require-i18n-strings
 | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ export const avatarI18n = { | ||||||
|   uploadNewAvatar: s__('Profiles|Upload new avatar'), |   uploadNewAvatar: s__('Profiles|Upload new avatar'), | ||||||
|   chooseFile: s__('Profiles|Choose file...'), |   chooseFile: s__('Profiles|Choose file...'), | ||||||
|   noFileChosen: s__('Profiles|No file chosen.'), |   noFileChosen: s__('Profiles|No file chosen.'), | ||||||
|   maximumFileSize: s__('Profiles|The maximum file size allowed is 200KB.'), |   maximumFileSize: s__('Profiles|The maximum file size allowed is 200 KiB.'), | ||||||
|   imageDimensions: s__('Profiles|The ideal image size is 192 x 192 pixels.'), |   imageDimensions: s__('Profiles|The ideal image size is 192 x 192 pixels.'), | ||||||
|   removeAvatar: s__('Profiles|Remove avatar'), |   removeAvatar: s__('Profiles|Remove avatar'), | ||||||
|   removeAvatarConfirmation: s__('Profiles|Avatar will be removed. Are you sure?'), |   removeAvatarConfirmation: s__('Profiles|Avatar will be removed. Are you sure?'), | ||||||
|  |  | ||||||
|  | @ -14,15 +14,14 @@ import Vue from 'vue'; | ||||||
|  * @returns {HTMLElement} |  * @returns {HTMLElement} | ||||||
|  */ |  */ | ||||||
| export const renderVueComponentForLegacyJS = (Component, data, children) => { | export const renderVueComponentForLegacyJS = (Component, data, children) => { | ||||||
|   const mountEl = document.createElement('div'); |  | ||||||
| 
 |  | ||||||
|   const vm = new Vue({ |   const vm = new Vue({ | ||||||
|     el: mountEl, |  | ||||||
|     render(h) { |     render(h) { | ||||||
|       return h(Component, data, children); |       return h(Component, data, children); | ||||||
|     }, |     }, | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|  |   vm.$mount(); | ||||||
|  | 
 | ||||||
|   // Ensure it's rendered
 |   // Ensure it's rendered
 | ||||||
|   vm.$forceUpdate(); |   vm.$forceUpdate(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -67,7 +67,7 @@ export default { | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|   <div> |   <div> | ||||||
|     <h5 :id="labelId" class="gl-mt-0 gl-mb-5 gl-font-sm"> |     <h5 :id="labelId" class="gl-mt-0 gl-mb-2 gl-font-sm"> | ||||||
|       {{ $options.i18n.groupFieldLabel }} |       {{ $options.i18n.groupFieldLabel }} | ||||||
|     </h5> |     </h5> | ||||||
|     <searchable-dropdown |     <searchable-dropdown | ||||||
|  |  | ||||||
|  | @ -76,7 +76,7 @@ export default { | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|   <div> |   <div> | ||||||
|     <h5 :id="labelId" class="gl-mt-0 gl-mb-5 gl-font-sm"> |     <h5 :id="labelId" class="gl-mt-0 gl-mb-2 gl-font-sm"> | ||||||
|       {{ $options.i18n.projectFieldLabel }} |       {{ $options.i18n.projectFieldLabel }} | ||||||
|     </h5> |     </h5> | ||||||
|     <searchable-dropdown |     <searchable-dropdown | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ export default { | ||||||
|   i18n: { |   i18n: { | ||||||
|     searchPlaceholder: s__(`GlobalSearch|Search for projects, issues, etc.`), |     searchPlaceholder: s__(`GlobalSearch|Search for projects, issues, etc.`), | ||||||
|     searchLabel: s__(`GlobalSearch|What are you searching for?`), |     searchLabel: s__(`GlobalSearch|What are you searching for?`), | ||||||
|     syntaxOptionsLabel: s__('GlobalSearch|Syntax options'), |     syntaxOptionsLabel: s__('GlobalSearch|View syntax options.'), | ||||||
|     groupFieldLabel: s__('GlobalSearch|Group'), |     groupFieldLabel: s__('GlobalSearch|Group'), | ||||||
|     projectFieldLabel: s__('GlobalSearch|Project'), |     projectFieldLabel: s__('GlobalSearch|Project'), | ||||||
|   }, |   }, | ||||||
|  | @ -102,43 +102,27 @@ export default { | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|   <section> |   <section> | ||||||
|     <div |     <div class="search-page-form gl-mt-5"> | ||||||
|       class="gl-lg-display-flex gl-flex-direction-row gl-py-5" |       <search-type-indicator /> | ||||||
|       :class="{ |  | ||||||
|         'gl-justify-content-space-between': showSyntaxOptions, |  | ||||||
|         'gl-justify-content-end': !showSyntaxOptions, |  | ||||||
|       }" |  | ||||||
|     > |  | ||||||
|       <template v-if="showSyntaxOptions"> |       <template v-if="showSyntaxOptions"> | ||||||
|         <div> |         <div class="gl-display-inline-block"> | ||||||
|           <gl-button |           <gl-button category="tertiary" variant="link" @click="onToggleDrawer" | ||||||
|             category="tertiary" |  | ||||||
|             variant="link" |  | ||||||
|             size="small" |  | ||||||
|             button-text-classes="gl-font-sm!" |  | ||||||
|             @click="onToggleDrawer" |  | ||||||
|             >{{ $options.i18n.syntaxOptionsLabel }} |             >{{ $options.i18n.syntaxOptionsLabel }} | ||||||
|           </gl-button> |           </gl-button> | ||||||
|         </div> |         </div> | ||||||
|         <markdown-drawer ref="markdownDrawer" :document-path="documentBasedOnSearchType" /> |         <markdown-drawer ref="markdownDrawer" :document-path="documentBasedOnSearchType" /> | ||||||
|       </template> |       </template> | ||||||
|       <search-type-indicator /> |       <gl-search-box-by-type | ||||||
|     </div> |         id="dashboard_search" | ||||||
|     <div class="search-page-form gl-lg-display-flex gl-flex-direction-column"> |         v-model="search" | ||||||
|       <div class="gl-lg-display-flex gl-flex-direction-row gl-align-items-flex-start"> |         name="search" | ||||||
|         <div class="gl-flex-grow-1 gl-pb-8 gl-lg-mb-0 gl-lg-mr-2"> |         class="gl-mt-2" | ||||||
|           <gl-search-box-by-type |         :regex-button-is-visible="isRegexButtonVisible" | ||||||
|             id="dashboard_search" |         :regex-button-state="regexEnabled" | ||||||
|             v-model="search" |         :regex-button-handler="regexButtonHandler" | ||||||
|             name="search" |         :placeholder="$options.i18n.searchPlaceholder" | ||||||
|             :regex-button-is-visible="isRegexButtonVisible" |         @keydown.enter.stop.prevent="applyQuery" | ||||||
|             :regex-button-state="regexEnabled" |       /> | ||||||
|             :regex-button-handler="regexButtonHandler" |  | ||||||
|             :placeholder="$options.i18n.searchPlaceholder" |  | ||||||
|             @keydown.enter.stop.prevent="applyQuery" |  | ||||||
|           /> |  | ||||||
|         </div> |  | ||||||
|       </div> |  | ||||||
|     </div> |     </div> | ||||||
|   </section> |   </section> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ export default { | ||||||
|   }, |   }, | ||||||
|   i18n: { |   i18n: { | ||||||
|     zoekt_enabled: s__( |     zoekt_enabled: s__( | ||||||
|       'GlobalSearch|%{linkStart}Exact code search (powered by Zoekt)%{linkEnd} is enabled', |       'GlobalSearch|%{linkStart}Exact code search (powered by Zoekt)%{linkEnd} is enabled.', | ||||||
|     ), |     ), | ||||||
|     zoekt_disabled: s__( |     zoekt_disabled: s__( | ||||||
|       'GlobalSearch|%{linkStart}Exact code search (powered by Zoekt)%{linkEnd} is disabled since %{ref_elem} is not the default branch. %{docs_link}', |       'GlobalSearch|%{linkStart}Exact code search (powered by Zoekt)%{linkEnd} is disabled since %{ref_elem} is not the default branch. %{docs_link}', | ||||||
|  | @ -119,19 +119,19 @@ export default { | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|   <div class="gl-text-gray-600"> |   <div class="gl-inline gl-text-gray-600"> | ||||||
|     <div v-if="isBasicSearch" data-testid="basic"> </div> |     <div v-if="isBasicSearch" data-testid="basic"></div> | ||||||
|     <div v-else-if="isEnabled" :data-testid="`${searchTypeTestId}-enabled`"> |     <div v-else-if="isEnabled" :data-testid="`${searchTypeTestId}-enabled`" class="gl-inline"> | ||||||
|       <gl-sprintf :message="enabledMessage"> |       <gl-sprintf :message="enabledMessage"> | ||||||
|         <template #link="{ content }"> |         <template #link="{ content }"> | ||||||
|           <gl-link :href="helpUrl" target="_blank" data-testid="docs-link">{{ content }} </gl-link> |           <gl-link :href="helpUrl" target="_blank" data-testid="docs-link">{{ content }}</gl-link> | ||||||
|         </template> |         </template> | ||||||
|       </gl-sprintf> |       </gl-sprintf> | ||||||
|     </div> |     </div> | ||||||
|     <div v-else :data-testid="`${searchTypeTestId}-disabled`"> |     <div v-else :data-testid="`${searchTypeTestId}-disabled`" class="gl-inline"> | ||||||
|       <gl-sprintf :message="disabledMessage"> |       <gl-sprintf :message="disabledMessage"> | ||||||
|         <template #link="{ content }"> |         <template #link="{ content }"> | ||||||
|           <gl-link :href="helpUrl" target="_blank" data-testid="docs-link">{{ content }} </gl-link> |           <gl-link :href="helpUrl" target="_blank" data-testid="docs-link">{{ content }}</gl-link> | ||||||
|         </template> |         </template> | ||||||
|         <template #ref_elem> |         <template #ref_elem> | ||||||
|           <code v-gl-tooltip :title="query.repository_ref">{{ query.repository_ref }}</code> |           <code v-gl-tooltip :title="query.repository_ref">{{ query.repository_ref }}</code> | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | /* eslint-disable no-restricted-imports */ | ||||||
| import { | import { | ||||||
|   BrowserClient, |   BrowserClient, | ||||||
|   getCurrentHub, |   getCurrentHub, | ||||||
|  | @ -9,7 +10,7 @@ import { | ||||||
|   // exports
 |   // exports
 | ||||||
|   captureException, |   captureException, | ||||||
|   SDK_VERSION, |   SDK_VERSION, | ||||||
| } from 'sentrybrowser'; | } from '@sentry/browser'; | ||||||
| 
 | 
 | ||||||
| const initSentry = () => { | const initSentry = () => { | ||||||
|   if (!gon?.sentry_dsn) { |   if (!gon?.sentry_dsn) { | ||||||
|  |  | ||||||
|  | @ -1,46 +0,0 @@ | ||||||
| import { __ } from '~/locale'; |  | ||||||
| 
 |  | ||||||
| // https://docs.sentry.io/platforms/javascript/configuration/filtering/#decluttering-sentry
 |  | ||||||
| export const IGNORE_ERRORS = [ |  | ||||||
|   // Random plugins/extensions
 |  | ||||||
|   'top.GLOBALS', |  | ||||||
|   // See: http://blog.errorception.com/2012/03/tale-of-unfindable-js-error. html
 |  | ||||||
|   'originalCreateNotification', |  | ||||||
|   'canvas.contentDocument', |  | ||||||
|   'MyApp_RemoveAllHighlights', |  | ||||||
|   'http://tt.epicplay.com', |  | ||||||
|   __("Can't find variable: ZiteReader"), |  | ||||||
|   __('jigsaw is not defined'), |  | ||||||
|   __('ComboSearch is not defined'), |  | ||||||
|   'http://loading.retry.widdit.com/', |  | ||||||
|   'atomicFindClose', |  | ||||||
|   // Facebook borked
 |  | ||||||
|   'fb_xd_fragment', |  | ||||||
|   // ISP "optimizing" proxy - `Cache-Control: no-transform` seems to
 |  | ||||||
|   // reduce this. (thanks @acdha)
 |  | ||||||
|   'bmi_SafeAddOnload', |  | ||||||
|   'EBCallBackMessageReceived', |  | ||||||
|   // See http://toolbar.conduit.com/Developer/HtmlAndGadget/Methods/JSInjection.aspx
 |  | ||||||
|   'conduitPage', |  | ||||||
|   // Exclude errors from polling when navigating away from a page
 |  | ||||||
|   'TypeError: Failed to fetch', |  | ||||||
| ]; |  | ||||||
| 
 |  | ||||||
| export const DENY_URLS = [ |  | ||||||
|   // Facebook flakiness
 |  | ||||||
|   /graph\.facebook\.com/i, |  | ||||||
|   // Facebook blocked
 |  | ||||||
|   /connect\.facebook\.net\/en_US\/all\.js/i, |  | ||||||
|   // Woopra flakiness
 |  | ||||||
|   /eatdifferent\.com\.woopra-ns\.com/i, |  | ||||||
|   /static\.woopra\.com\/js\/woopra\.js/i, |  | ||||||
|   // Chrome extensions
 |  | ||||||
|   /extensions\//i, |  | ||||||
|   /^chrome:\/\//i, |  | ||||||
|   // Other plugins
 |  | ||||||
|   /127\.0\.0\.1:4001\/isrunning/i, // Cacaoweb
 |  | ||||||
|   /webappstoolbarba\.texthelp\.com\//i, |  | ||||||
|   /metrics\.itunes\.apple\.com\.edgesuite\.net\//i, |  | ||||||
| ]; |  | ||||||
| 
 |  | ||||||
| export const SAMPLE_RATE = 0.95; |  | ||||||
|  | @ -1,34 +0,0 @@ | ||||||
| import '../webpack'; |  | ||||||
| 
 |  | ||||||
| import * as Sentry5 from 'sentrybrowser5'; |  | ||||||
| import LegacySentryConfig from './legacy_sentry_config'; |  | ||||||
| 
 |  | ||||||
| const index = function index() { |  | ||||||
|   // Configuration for legacy versions of Sentry SDK (v5)
 |  | ||||||
|   LegacySentryConfig.init({ |  | ||||||
|     dsn: gon.sentry_dsn, |  | ||||||
|     currentUserId: gon.current_user_id, |  | ||||||
|     whitelistUrls: |  | ||||||
|       process.env.NODE_ENV === 'production' |  | ||||||
|         ? [gon.gitlab_url] |  | ||||||
|         : [gon.gitlab_url, 'webpack-internal://'], |  | ||||||
|     environment: gon.sentry_environment, |  | ||||||
|     release: gon.revision, |  | ||||||
|     tags: { |  | ||||||
|       revision: gon.revision, |  | ||||||
|       feature_category: gon.feature_category, |  | ||||||
|     }, |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| index(); |  | ||||||
| 
 |  | ||||||
| // The _Sentry object is globally exported so it can be used by
 |  | ||||||
| //   ./sentry_browser_wrapper.js
 |  | ||||||
| // This hack allows us to load a single version of `~/sentry/sentry_browser_wrapper`
 |  | ||||||
| // in the browser, see app/views/layouts/_head.html.haml to find how it is imported.
 |  | ||||||
| 
 |  | ||||||
| // eslint-disable-next-line no-underscore-dangle
 |  | ||||||
| window._Sentry = Sentry5; |  | ||||||
| 
 |  | ||||||
| export default index; |  | ||||||
|  | @ -1,64 +0,0 @@ | ||||||
| import * as Sentry5 from 'sentrybrowser5'; |  | ||||||
| import $ from 'jquery'; |  | ||||||
| import { __ } from '~/locale'; |  | ||||||
| import { IGNORE_ERRORS, DENY_URLS, SAMPLE_RATE } from './legacy_constants'; |  | ||||||
| 
 |  | ||||||
| const SentryConfig = { |  | ||||||
|   IGNORE_ERRORS, |  | ||||||
|   DENYLIST_URLS: DENY_URLS, |  | ||||||
|   SAMPLE_RATE, |  | ||||||
|   init(options = {}) { |  | ||||||
|     this.options = options; |  | ||||||
| 
 |  | ||||||
|     this.configure(); |  | ||||||
|     this.bindSentryErrors(); |  | ||||||
|     if (this.options.currentUserId) this.setUser(); |  | ||||||
|   }, |  | ||||||
| 
 |  | ||||||
|   configure() { |  | ||||||
|     const { dsn, release, tags, whitelistUrls, environment } = this.options; |  | ||||||
| 
 |  | ||||||
|     Sentry5.init({ |  | ||||||
|       dsn, |  | ||||||
|       release, |  | ||||||
|       whitelistUrls, |  | ||||||
|       environment, |  | ||||||
|       ignoreErrors: this.IGNORE_ERRORS, // TODO: Remove in favor of https://gitlab.com/gitlab-org/gitlab/issues/35144
 |  | ||||||
|       blacklistUrls: this.DENYLIST_URLS, |  | ||||||
|       sampleRate: SAMPLE_RATE, |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     Sentry5.setTags(tags); |  | ||||||
|   }, |  | ||||||
| 
 |  | ||||||
|   setUser() { |  | ||||||
|     Sentry5.setUser({ |  | ||||||
|       id: this.options.currentUserId, |  | ||||||
|     }); |  | ||||||
|   }, |  | ||||||
| 
 |  | ||||||
|   bindSentryErrors() { |  | ||||||
|     $(document).on('ajaxError.sentry', this.handleSentryErrors); |  | ||||||
|   }, |  | ||||||
| 
 |  | ||||||
|   handleSentryErrors(event, req, config, err) { |  | ||||||
|     const error = err || req.statusText; |  | ||||||
|     const { responseText = __('Unknown response text') } = req; |  | ||||||
|     const { type, url, data } = config; |  | ||||||
|     const { status } = req; |  | ||||||
| 
 |  | ||||||
|     Sentry5.captureMessage(error, { |  | ||||||
|       extra: { |  | ||||||
|         type, |  | ||||||
|         url, |  | ||||||
|         data, |  | ||||||
|         status, |  | ||||||
|         response: responseText, |  | ||||||
|         error, |  | ||||||
|         event, |  | ||||||
|       }, |  | ||||||
|     }); |  | ||||||
|   }, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| export default SentryConfig; |  | ||||||
|  | @ -1,6 +1,8 @@ | ||||||
| import $ from 'jquery'; | import $ from 'jquery'; | ||||||
|  | import { GlButton } from '@gitlab/ui'; | ||||||
| import { createAlert } from '~/alert'; | import { createAlert } from '~/alert'; | ||||||
| import { loadingIconForLegacyJS } from '~/loading_icon_for_legacy_js'; | import { loadingIconForLegacyJS } from '~/loading_icon_for_legacy_js'; | ||||||
|  | import { renderVueComponentForLegacyJS } from '~/render_vue_component_for_legacy_js'; | ||||||
| import { spriteIcon } from '~/lib/utils/common_utils'; | import { spriteIcon } from '~/lib/utils/common_utils'; | ||||||
| import FilesCommentButton from './files_comment_button'; | import FilesCommentButton from './files_comment_button'; | ||||||
| import initImageDiffHelper from './image_diff/helpers/init_image_diff'; | import initImageDiffHelper from './image_diff/helpers/init_image_diff'; | ||||||
|  | @ -14,8 +16,15 @@ const ERROR_HTML = `<div class="nothing-here-block">${spriteIcon( | ||||||
|   'warning-solid', |   'warning-solid', | ||||||
|   's16', |   's16', | ||||||
| )} Could not load diff</div>`; | )} Could not load diff</div>`; | ||||||
| const COLLAPSED_HTML = | const CLICK_TO_EXPAND_BUTTON_HTML = renderVueComponentForLegacyJS( | ||||||
|   '<div class="nothing-here-block diff-collapsed">This diff is collapsed. <button class="click-to-expand btn btn-link gl-button">Click to expand it.</button></div>'; |   GlButton, | ||||||
|  |   { | ||||||
|  |     class: 'click-to-expand', | ||||||
|  |     props: { variant: 'link' }, | ||||||
|  |   }, | ||||||
|  |   __('Click to expand it.'), | ||||||
|  | ).outerHTML; | ||||||
|  | const COLLAPSED_HTML = `<div class="nothing-here-block diff-collapsed">This diff is collapsed. ${CLICK_TO_EXPAND_BUTTON_HTML}</div>`; | ||||||
| 
 | 
 | ||||||
| export default class SingleFileDiff { | export default class SingleFileDiff { | ||||||
|   constructor(file) { |   constructor(file) { | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants'; | ||||||
| export default { | export default { | ||||||
|   i18n: { |   i18n: { | ||||||
|     uploadText: __('Drop or %{linkStart}upload%{linkEnd} an avatar.'), |     uploadText: __('Drop or %{linkStart}upload%{linkEnd} an avatar.'), | ||||||
|     maxFileSize: s__('Profiles|The maximum file size allowed is 200KB.'), |     maxFileSize: s__('Profiles|The maximum file size allowed is 200 KiB.'), | ||||||
|     imageDimensions: s__('Profiles|The ideal image size is 192 x 192 pixels.'), |     imageDimensions: s__('Profiles|The ideal image size is 192 x 192 pixels.'), | ||||||
|     removeAvatar: __('Remove avatar'), |     removeAvatar: __('Remove avatar'), | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|  | @ -3,6 +3,15 @@ | ||||||
| module ApplicationCable | module ApplicationCable | ||||||
|   class Channel < ActionCable::Channel::Base |   class Channel < ActionCable::Channel::Base | ||||||
|     include Logging |     include Logging | ||||||
|  |     include Gitlab::Auth::AuthFinders | ||||||
|  | 
 | ||||||
|  |     before_subscribe :validate_token_scope | ||||||
|  | 
 | ||||||
|  |     def validate_token_scope | ||||||
|  |       validate_access_token!(scopes: [:api, :read_api]) | ||||||
|  |     rescue Gitlab::Auth::InsufficientScopeError | ||||||
|  |       reject | ||||||
|  |     end | ||||||
| 
 | 
 | ||||||
|     private |     private | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -48,7 +48,8 @@ class GraphqlChannel < ApplicationCable::Channel # rubocop:disable Gitlab/Namesp | ||||||
|   # Objects added to the context may also need to be reloaded in |   # Objects added to the context may also need to be reloaded in | ||||||
|   # `Subscriptions::BaseSubscription` so that they are not stale |   # `Subscriptions::BaseSubscription` so that they are not stale | ||||||
|   def context |   def context | ||||||
|     # is_sessionless_user is always false because we only support cookie auth in ActionCable |     request_authenticator = Gitlab::Auth::RequestAuthenticator.new(request) | ||||||
|     { channel: self, current_user: current_user, is_sessionless_user: false } |     scope_validator = ::Gitlab::Auth::ScopeValidator.new(current_user, request_authenticator) | ||||||
|  |     { channel: self, current_user: current_user, is_sessionless_user: false, scope_validator: scope_validator } | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -222,6 +222,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController | ||||||
|     else |     else | ||||||
|       fail_login(@user) |       fail_login(@user) | ||||||
|     end |     end | ||||||
|  |   rescue Gitlab::Auth::OAuth::User::IdentityWithUntrustedExternUidError | ||||||
|  |     handle_identity_with_untrusted_extern_uid | ||||||
|   rescue Gitlab::Auth::OAuth::User::SigninDisabledForProviderError |   rescue Gitlab::Auth::OAuth::User::SigninDisabledForProviderError | ||||||
|     handle_disabled_provider |     handle_disabled_provider | ||||||
|   rescue Gitlab::Auth::OAuth::User::SignupDisabledError |   rescue Gitlab::Auth::OAuth::User::SignupDisabledError | ||||||
|  | @ -271,6 +273,13 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController | ||||||
|     redirect_to profile_account_path, notice: _('Request to link SAML account must be authorized') |     redirect_to profile_account_path, notice: _('Request to link SAML account must be authorized') | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   def handle_identity_with_untrusted_extern_uid | ||||||
|  |     label = Gitlab::Auth::OAuth::Provider.label_for(oauth['provider']) | ||||||
|  |     flash[:alert] = format(_("Signing in using your %{label} account has been disabled for security reasons. Please sign in to your GitLab account using another authentication method and reconnect to your %{label} account."), label: label) | ||||||
|  | 
 | ||||||
|  |     redirect_to new_user_session_path | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   def handle_disabled_provider |   def handle_disabled_provider | ||||||
|     label = Gitlab::Auth::OAuth::Provider.label_for(oauth['provider']) |     label = Gitlab::Auth::OAuth::Provider.label_for(oauth['provider']) | ||||||
|     flash[:alert] = _("Signing in using %{label} has been disabled") % { label: label } |     flash[:alert] = _("Signing in using %{label} has been disabled") % { label: label } | ||||||
|  |  | ||||||
|  | @ -174,7 +174,7 @@ module Resolvers | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def self.authorized?(object, context) |     def self.authorized?(object, context) | ||||||
|       authorization.ok?(object, context[:current_user]) |       authorization.ok?(object, context[:current_user], scope_validator: context[:scope_validator]) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -65,7 +65,7 @@ module Types | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       def authorized?(object, context) |       def authorized?(object, context) | ||||||
|         authorization.ok?(object, context[:current_user]) |         authorization.ok?(object, context[:current_user], scope_validator: context[:scope_validator]) | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  | @ -97,7 +97,7 @@ module Types | ||||||
|     def field_authorized?(object, ctx) |     def field_authorized?(object, ctx) | ||||||
|       object = object.node if object.is_a?(GraphQL::Pagination::Connection::Edge) |       object = object.node if object.is_a?(GraphQL::Pagination::Connection::Edge) | ||||||
| 
 | 
 | ||||||
|       authorization.ok?(object, ctx[:current_user]) |       authorization.ok?(object, ctx[:current_user], scope_validator: ctx[:scope_validator]) | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     # Historically our resolvers have used declarative permission checks only |     # Historically our resolvers have used declarative permission checks only | ||||||
|  |  | ||||||
|  | @ -32,7 +32,7 @@ module Types | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def self.authorized?(object, context) |     def self.authorized?(object, context) | ||||||
|       authorization.ok?(object, context[:current_user]) |       authorization.ok?(object, context[:current_user], scope_validator: context[:scope_validator]) | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def current_user |     def current_user | ||||||
|  |  | ||||||
|  | @ -411,6 +411,9 @@ module ApplicationSettingsHelper | ||||||
|       :throttle_unauthenticated_files_api_enabled, |       :throttle_unauthenticated_files_api_enabled, | ||||||
|       :throttle_unauthenticated_files_api_period_in_seconds, |       :throttle_unauthenticated_files_api_period_in_seconds, | ||||||
|       :throttle_unauthenticated_files_api_requests_per_period, |       :throttle_unauthenticated_files_api_requests_per_period, | ||||||
|  |       :throttle_unauthenticated_git_http_enabled, | ||||||
|  |       :throttle_unauthenticated_git_http_period_in_seconds, | ||||||
|  |       :throttle_unauthenticated_git_http_requests_per_period, | ||||||
|       :throttle_unauthenticated_deprecated_api_enabled, |       :throttle_unauthenticated_deprecated_api_enabled, | ||||||
|       :throttle_unauthenticated_deprecated_api_period_in_seconds, |       :throttle_unauthenticated_deprecated_api_period_in_seconds, | ||||||
|       :throttle_unauthenticated_deprecated_api_requests_per_period, |       :throttle_unauthenticated_deprecated_api_requests_per_period, | ||||||
|  |  | ||||||
|  | @ -553,6 +553,8 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord | ||||||
|       :throttle_unauthenticated_deprecated_api_requests_per_period, |       :throttle_unauthenticated_deprecated_api_requests_per_period, | ||||||
|       :throttle_unauthenticated_files_api_period_in_seconds, |       :throttle_unauthenticated_files_api_period_in_seconds, | ||||||
|       :throttle_unauthenticated_files_api_requests_per_period, |       :throttle_unauthenticated_files_api_requests_per_period, | ||||||
|  |       :throttle_unauthenticated_git_http_period_in_seconds, | ||||||
|  |       :throttle_unauthenticated_git_http_requests_per_period, | ||||||
|       :throttle_unauthenticated_packages_api_period_in_seconds, |       :throttle_unauthenticated_packages_api_period_in_seconds, | ||||||
|       :throttle_unauthenticated_packages_api_requests_per_period, |       :throttle_unauthenticated_packages_api_requests_per_period, | ||||||
|       :throttle_unauthenticated_period_in_seconds, |       :throttle_unauthenticated_period_in_seconds, | ||||||
|  | @ -612,6 +614,11 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord | ||||||
|   jsonb_accessor :service_ping_settings, |   jsonb_accessor :service_ping_settings, | ||||||
|     gitlab_environment_toolkit_instance: [:boolean, { default: false }] |     gitlab_environment_toolkit_instance: [:boolean, { default: false }] | ||||||
| 
 | 
 | ||||||
|  |   jsonb_accessor :rate_limits_unauthenticated_git_http, | ||||||
|  |     throttle_unauthenticated_git_http_enabled: [:boolean, { default: false }], | ||||||
|  |     throttle_unauthenticated_git_http_requests_per_period: [:integer, { default: 3600 }], | ||||||
|  |     throttle_unauthenticated_git_http_period_in_seconds: [:integer, { default: 3600 }] | ||||||
|  | 
 | ||||||
|   validates :rate_limits, json_schema: { filename: "application_setting_rate_limits" } |   validates :rate_limits, json_schema: { filename: "application_setting_rate_limits" } | ||||||
| 
 | 
 | ||||||
|   validates :search_rate_limit_allowlist, |   validates :search_rate_limit_allowlist, | ||||||
|  |  | ||||||
|  | @ -2148,8 +2148,12 @@ class MergeRequest < ApplicationRecord | ||||||
|     merge_request_reviewers.where(user_id: user_ids) |     merge_request_reviewers.where(user_id: user_ids) | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def has_changes_requested? |   def create_requested_changes(user) | ||||||
|     merge_request_reviewers.exists?(state: :requested_changes) |     # Overridden in EE | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def destroy_requested_changes(user) | ||||||
|  |     # Overridden in EE | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def batch_update_reviewer_state(user_ids, state) |   def batch_update_reviewer_state(user_ids, state) | ||||||
|  |  | ||||||
|  | @ -320,7 +320,7 @@ class User < MainClusterwide::ApplicationRecord | ||||||
|   validates :name, presence: true, length: { maximum: 255 } |   validates :name, presence: true, length: { maximum: 255 } | ||||||
|   validates :first_name, length: { maximum: 127 } |   validates :first_name, length: { maximum: 127 } | ||||||
|   validates :last_name, length: { maximum: 127 } |   validates :last_name, length: { maximum: 127 } | ||||||
|   validates :email, confirmation: true |   validates :email, confirmation: true, devise_email: true | ||||||
|   validates :notification_email, devise_email: true, allow_blank: true |   validates :notification_email, devise_email: true, allow_blank: true | ||||||
|   validates :public_email, uniqueness: true, devise_email: true, allow_blank: true |   validates :public_email, uniqueness: true, devise_email: true, allow_blank: true | ||||||
|   validates :commit_email, devise_email: true, allow_blank: true, unless: ->(user) { user.commit_email == Gitlab::PrivateCommitEmail::TOKEN } |   validates :commit_email, devise_email: true, allow_blank: true, unless: ->(user) { user.commit_email == Gitlab::PrivateCommitEmail::TOKEN } | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ module MergeRequests | ||||||
| 
 | 
 | ||||||
|       return success unless save_approval(approval) |       return success unless save_approval(approval) | ||||||
| 
 | 
 | ||||||
|       update_reviewer_state(merge_request, current_user, :approved) |       update_reviewer_state(merge_request, current_user, 'approved') | ||||||
| 
 | 
 | ||||||
|       reset_approvals_cache(merge_request) |       reset_approvals_cache(merge_request) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -15,7 +15,7 @@ module MergeRequests | ||||||
|       trigger_approval_hooks(merge_request, skip_notification) do |       trigger_approval_hooks(merge_request, skip_notification) do | ||||||
|         next unless approval.destroy_all # rubocop: disable Cop/DestroyAll |         next unless approval.destroy_all # rubocop: disable Cop/DestroyAll | ||||||
| 
 | 
 | ||||||
|         update_reviewer_state(merge_request, current_user, :unapproved) unless skip_updating_state |         update_reviewer_state(merge_request, current_user, 'unapproved') unless skip_updating_state | ||||||
|         reset_approvals_cache(merge_request) |         reset_approvals_cache(merge_request) | ||||||
| 
 | 
 | ||||||
|         unless skip_system_note |         unless skip_system_note | ||||||
|  |  | ||||||
|  | @ -12,8 +12,12 @@ module MergeRequests | ||||||
| 
 | 
 | ||||||
|         trigger_merge_request_reviewers_updated(merge_request) |         trigger_merge_request_reviewers_updated(merge_request) | ||||||
| 
 | 
 | ||||||
|  |         destroy_requested_changes(merge_request) if state == 'approved' | ||||||
|  | 
 | ||||||
|         return success if state != 'requested_changes' |         return success if state != 'requested_changes' | ||||||
| 
 | 
 | ||||||
|  |         create_requested_changes(merge_request) | ||||||
|  | 
 | ||||||
|         if merge_request.approved_by?(current_user) && !remove_approval(merge_request, current_user) |         if merge_request.approved_by?(current_user) && !remove_approval(merge_request, current_user) | ||||||
|           return error("Failed to remove approval") |           return error("Failed to remove approval") | ||||||
|         end |         end | ||||||
|  | @ -23,5 +27,17 @@ module MergeRequests | ||||||
|         error("Reviewer not found") |         error("Reviewer not found") | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
|  | 
 | ||||||
|  |     private | ||||||
|  | 
 | ||||||
|  |     def create_requested_changes(merge_request) | ||||||
|  |       merge_request.create_requested_changes(current_user) | ||||||
|  | 
 | ||||||
|  |       trigger_merge_request_merge_status_updated(merge_request) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def destroy_requested_changes(merge_request) | ||||||
|  |       merge_request.destroy_requested_changes(current_user) | ||||||
|  |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -19,7 +19,8 @@ | ||||||
| #   end | #   end | ||||||
| class DeviseEmailValidator < ActiveModel::EachValidator | class DeviseEmailValidator < ActiveModel::EachValidator | ||||||
|   DEFAULT_OPTIONS = { |   DEFAULT_OPTIONS = { | ||||||
|     regexp: Devise.email_regexp |     regexp: Devise.email_regexp, | ||||||
|  |     invalid_characters_regexp: %r{[?!#$%&*\/=^<>]} | ||||||
|   }.freeze |   }.freeze | ||||||
| 
 | 
 | ||||||
|   def initialize(options) |   def initialize(options) | ||||||
|  | @ -31,6 +32,14 @@ class DeviseEmailValidator < ActiveModel::EachValidator | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def validate_each(record, attribute, value) |   def validate_each(record, attribute, value) | ||||||
|     record.errors.add(attribute, :invalid) unless options[:regexp].match?(value) |     return if record.errors.include?(attribute) | ||||||
|  | 
 | ||||||
|  |     record.errors.add(attribute, :invalid) unless valid_email?(value) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   private | ||||||
|  | 
 | ||||||
|  |   def valid_email?(value) | ||||||
|  |     options[:regexp].match?(value) && !options[:invalid_characters_regexp].match?(value) | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | = gitlab_ui_form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-git-http-limits-settings'), html: { class: 'fieldset-form' } do |f| | ||||||
|  |   = form_errors(@application_setting) | ||||||
|  | 
 | ||||||
|  |   %fieldset | ||||||
|  |     %h5 | ||||||
|  |       = _('Unauthenticated Git HTTP request rate limit') | ||||||
|  |     .form-group | ||||||
|  |       = f.gitlab_ui_checkbox_component :throttle_unauthenticated_git_http_enabled, | ||||||
|  |         _('Enable unauthenticated Git HTTP request rate limit'), | ||||||
|  |         help_text: _('Helps reduce unauthenticated Git HTTP request volume for git paths.') | ||||||
|  |     .form-group | ||||||
|  |       = f.label :throttle_unauthenticated_git_http_requests_per_period, _('Maximum unauthenticated Git HTTP requests per period per IP'), class: 'gl-font-weight-bold' | ||||||
|  |       = f.number_field :throttle_unauthenticated_git_http_requests_per_period, class: 'form-control gl-form-input' | ||||||
|  |     .form-group | ||||||
|  |       = f.label :throttle_unauthenticated_git_http_period_in_seconds, _('Unauthenticated Git HTTP rate limit period in seconds'), class: 'gl-font-weight-bold' | ||||||
|  |       = f.number_field :throttle_unauthenticated_git_http_period_in_seconds, class: 'form-control gl-form-input' | ||||||
|  | 
 | ||||||
|  |   = f.submit _('Save changes'), pajamas_button: true | ||||||
|  | @ -1,12 +1,8 @@ | ||||||
| = gitlab_ui_form_for @application_setting, url: metrics_and_profiling_admin_application_settings_path(anchor: 'js-sentry-settings'), html: { class: 'fieldset-form', id: 'sentry-settings' } do |f| | = gitlab_ui_form_for @application_setting, url: metrics_and_profiling_admin_application_settings_path(anchor: 'js-sentry-settings'), html: { class: 'fieldset-form', id: 'sentry-settings' } do |f| | ||||||
|   = form_errors(@application_setting) |   = form_errors(@application_setting) | ||||||
| 
 | 
 | ||||||
|   - if Feature.disabled?(:enable_new_sentry_integration) |   %fieldset.gl-text-secondary | ||||||
|     %fieldset.gl-text-secondary |     = safe_format(s_('AdminSettings|GitLab uses the %{bold_start}Rails%{bold_end} and %{bold_start}Browser JavaScript%{bold_end} Sentry SDKs to send events to Sentry. For changes to Rails integration settings to take effect, restart GitLab.'), tag_pair(tag.b, :bold_start, :bold_end)) | ||||||
|       = safe_format(s_('AdminSettings|GitLab uses the %{bold_start}Rails%{bold_end} and %{bold_start}Browser JavaScript%{bold_end} Sentry SDKs to send events to Sentry. For changes to Rails integration settings to take effect, enable the %{code_start}enable_new_sentry_integration%{code_end} feature flag and restart GitLab.'), tag_pair(tag.b, :bold_start, :bold_end), tag_pair(tag.code, :code_start, :code_end)) |  | ||||||
|   - else |  | ||||||
|     %fieldset.gl-text-secondary |  | ||||||
|       = safe_format(s_('AdminSettings|GitLab uses the %{bold_start}Rails%{bold_end} and %{bold_start}Browser JavaScript%{bold_end} Sentry SDKs to send events to Sentry. For changes to Rails integration settings to take effect, restart GitLab.'), tag_pair(tag.b, :bold_start, :bold_end)) |  | ||||||
| 
 | 
 | ||||||
|   %fieldset |   %fieldset | ||||||
|     .form-group |     .form-group | ||||||
|  |  | ||||||
|  | @ -72,6 +72,18 @@ | ||||||
|   .settings-content |   .settings-content | ||||||
|     = render partial: 'network_rate_limits', locals: { anchor: 'js-deprecated-limits-settings', setting_fragment: 'deprecated_api' } |     = render partial: 'network_rate_limits', locals: { anchor: 'js-deprecated-limits-settings', setting_fragment: 'deprecated_api' } | ||||||
| 
 | 
 | ||||||
|  | %section.settings.as-git-http-limits.no-animate#js-git-http-limits-settings{ class: ('expanded' if expanded_by_default?) } | ||||||
|  |   .settings-header | ||||||
|  |     %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only | ||||||
|  |       = _('Git HTTP rate limits') | ||||||
|  |     = render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do | ||||||
|  |       = expanded_by_default? ? _('Collapse') : _('Expand') | ||||||
|  |     %p.gl-text-secondary | ||||||
|  |       = _('Configure specific limits for Git HTTP requests.') | ||||||
|  |       = link_to _('Learn more.'), help_page_path('administration/settings/git_http_rate_limits'), target: '_blank', rel: 'noopener noreferrer' | ||||||
|  |   .settings-content | ||||||
|  |     = render 'git_http_limits' | ||||||
|  | 
 | ||||||
| %section.settings.as-git-lfs-limits.no-animate#js-git-lfs-limits-settings{ class: ('expanded' if expanded_by_default?) } | %section.settings.as-git-lfs-limits.no-animate#js-git-lfs-limits-settings{ class: ('expanded' if expanded_by_default?) } | ||||||
|   .settings-header |   .settings-header | ||||||
|     %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only |     %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only | ||||||
|  |  | ||||||
|  | @ -48,10 +48,8 @@ | ||||||
|   = render 'layouts/loading_hints' |   = render 'layouts/loading_hints' | ||||||
| 
 | 
 | ||||||
|   = render_if_exists 'layouts/header/translations' |   = render_if_exists 'layouts/header/translations' | ||||||
|   - if Feature.enabled?(:enable_new_sentry_integration) && Gitlab::CurrentSettings.sentry_enabled |   - if Gitlab::CurrentSettings.sentry_enabled | ||||||
|     = webpack_bundle_tag 'sentry' |     = webpack_bundle_tag 'sentry' | ||||||
|   - elsif Gitlab.config.sentry.enabled |  | ||||||
|     = webpack_bundle_tag 'legacy_sentry' |  | ||||||
|   = webpack_bundle_tag 'performance_bar' if performance_bar_enabled? |   = webpack_bundle_tag 'performance_bar' if performance_bar_enabled? | ||||||
| 
 | 
 | ||||||
|   = yield :page_specific_javascripts |   = yield :page_specific_javascripts | ||||||
|  |  | ||||||
|  | @ -1,30 +1,25 @@ | ||||||
| .section{ class: ('gl-lg-display-none' if @search_objects.to_a.empty?) } | .search-results-status.gl-sm-display-flex.gl-flex-wrap.gl-justify-content-space-between.gl-my-4{ class: ('gl-lg-display-none' if @search_objects.to_a.empty?) } | ||||||
|   .search-results-status |   - unless @search_objects.to_a.empty? | ||||||
|     .gl-display-flex.gl-flex-direction-column |     %p.gl-text-truncate.gl-my-auto | ||||||
|       .gl-p-5.gl-display-flex.gl-flex-wrap |       - unless @search_service_presenter.without_count? | ||||||
|         - unless @search_objects.to_a.empty? |         = search_entries_info(@search_objects, @scope, @search_term) | ||||||
|           .gl-display-flex.gl-text-left.gl-flex-grow-1.gl-flex-shrink-1.gl-white-space-nowrap.gl-flex-wrap.gl-sm-w-half |       - unless @search_service_presenter.show_snippets? | ||||||
|  |         - if @project | ||||||
|  |           - link_to_project = link_to(@project.full_name, @project, class: 'search-wrap-f-md-down') | ||||||
|  |           - if @scope == 'blobs' | ||||||
|  |             = _("in") | ||||||
|  |             .mx-md-1.gl-my-auto | ||||||
|  |               #js-blob-ref-switcher{ data: { "project-id" => @project.id, "ref" => repository_ref(@project), "field-name": "repository_ref" } } | ||||||
|             %p.gl-text-truncate.gl-my-auto |             %p.gl-text-truncate.gl-my-auto | ||||||
|               - unless @search_service_presenter.without_count? |               = s_('SearchCodeResults|of %{link_to_project}').html_safe % { link_to_project: link_to_project } | ||||||
|                 = search_entries_info(@search_objects, @scope, @search_term) |           - else | ||||||
|               - unless @search_service_presenter.show_snippets? |             = _("in project %{link_to_project}").html_safe % { link_to_project: link_to_project } | ||||||
|                 - if @project |         - elsif @group | ||||||
|                   - link_to_project = link_to(@project.full_name, @project, class: 'search-wrap-f-md-down') |           - link_to_group = link_to(@group.name, @group, class: 'ml-md-1') | ||||||
|                   - if @scope == 'blobs' |           = _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group } | ||||||
|                     = _("in") |   .gl-display-flex | ||||||
|                     .mx-md-1.gl-my-auto |     = render Pajamas::ButtonComponent.new(category: 'primary', icon: 'filter', button_options: {id: 'js-open-mobile-filters', class: 'gl-lg-display-none'}) do | ||||||
|                       #js-blob-ref-switcher{ data: { "project-id" => @project.id, "ref" => repository_ref(@project), "field-name": "repository_ref" } } |       = s_('GlobalSearch|Filters') | ||||||
|                     %p.gl-text-truncate.gl-my-auto |     - if @search_service_presenter.show_sort_dropdown? && !@search_objects.to_a.empty? | ||||||
|                       = s_('SearchCodeResults|of %{link_to_project}').html_safe % { link_to_project: link_to_project } |       .gl-ml-3 | ||||||
|                   - else |         #js-search-sort{ data: { "search-sort-options" => search_sort_options.to_json } } | ||||||
|                     = _("in project %{link_to_project}").html_safe % { link_to_project: link_to_project } |  | ||||||
|                 - elsif @group |  | ||||||
|                   - link_to_group = link_to(@group.name, @group, class: 'ml-md-1') |  | ||||||
|                   = _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group } |  | ||||||
|         .gl-display-flex.gl-my-3.gl-flex-grow-1.gl-flex-shrink-1.gl-justify-content-end |  | ||||||
|           = render Pajamas::ButtonComponent.new(category: 'primary', icon: 'filter', button_options: {id: 'js-open-mobile-filters', class: 'gl-lg-display-none'}) do |  | ||||||
|             = s_('GlobalSearch|Filters') |  | ||||||
|           - if @search_service_presenter.show_sort_dropdown? && !@search_objects.to_a.empty? |  | ||||||
|             .gl-ml-3 |  | ||||||
|               #js-search-sort{ data: { "search-sort-options" => search_sort_options.to_json } } |  | ||||||
|     %hr.gl-mb-5.gl-mt-0.gl-border-gray-100.gl-w-full |  | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| %div{ class: 'search-result-row gl-display-flex gl-sm-flex-direction-row gl-flex-direction-column gl-align-items-center gl-pb-5! gl-mt-5 gl-mb-0!' } | .search-result-row.row.gl-display-flex.gl-sm-flex-direction-row.gl-flex-direction-column.gl-align-items-center.gl-mt-5{ class: 'gl-pb-5! gl-mb-0!' } | ||||||
|   .col-sm-9 |   .col-sm-9 | ||||||
|     %span.gl-display-flex.gl-align-items-center |     %span.gl-display-flex.gl-align-items-center | ||||||
|       = gl_badge_tag issuable_state_text(issuable), variant: issuable_state_to_badge_class(issuable), size: :sm |       = gl_badge_tag issuable_state_text(issuable), variant: issuable_state_to_badge_class(issuable), size: :sm | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| = render 'shared/file_picker_button', f: f, field: :avatar, help_text: s_("Profiles|The ideal image size is 192 x 192 pixels.") + " " + s_("Profiles|The maximum file size allowed is 200KB.") | = render 'shared/file_picker_button', f: f, field: :avatar, help_text: s_("Profiles|The ideal image size is 192 x 192 pixels.") + " " + s_("Profiles|The maximum file size allowed is 200 KiB.") | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ | ||||||
|         = f.file_field :avatar, class: 'js-user-avatar-input hidden', accept: 'image/*' |         = f.file_field :avatar, class: 'js-user-avatar-input hidden', accept: 'image/*' | ||||||
|       .gl-text-gray-500 |       .gl-text-gray-500 | ||||||
|         = s_("Profiles|The ideal image size is 192 x 192 pixels.") |         = s_("Profiles|The ideal image size is 192 x 192 pixels.") | ||||||
|         = s_("Profiles|The maximum file size allowed is 200KB.") |         = s_("Profiles|The maximum file size allowed is 200 KiB.") | ||||||
|       - if @user.avatar? |       - if @user.avatar? | ||||||
|         = render Pajamas::ButtonComponent.new(variant: :danger, |         = render Pajamas::ButtonComponent.new(variant: :danger, | ||||||
|           category: :secondary, |           category: :secondary, | ||||||
|  |  | ||||||
|  | @ -1,8 +0,0 @@ | ||||||
| --- |  | ||||||
| name: enable_new_sentry_integration |  | ||||||
| introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72428 |  | ||||||
| rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344832 |  | ||||||
| milestone: '14.9' |  | ||||||
| type: development |  | ||||||
| group: group::pipeline execution |  | ||||||
| default_enabled: false |  | ||||||
|  | @ -1,8 +0,0 @@ | ||||||
| --- |  | ||||||
| name: enable_old_sentry_integration |  | ||||||
| introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72428 |  | ||||||
| rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344832 |  | ||||||
| milestone: '14.9' |  | ||||||
| type: development |  | ||||||
| group: group::pipeline execution |  | ||||||
| default_enabled: true |  | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | --- | ||||||
|  | name: native_header_anchors | ||||||
|  | feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/440733 | ||||||
|  | introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144690 | ||||||
|  | rollout_issue_url: | ||||||
|  | milestone: '17.0' | ||||||
|  | group: group::project management | ||||||
|  | type: gitlab_com_derisk | ||||||
|  | default_enabled: false | ||||||
|  | @ -245,6 +245,16 @@ merge_request_metrics: | ||||||
|   - table: ci_pipelines |   - table: ci_pipelines | ||||||
|     column: pipeline_id |     column: pipeline_id | ||||||
|     on_delete: async_nullify |     on_delete: async_nullify | ||||||
|  | merge_request_requested_changes: | ||||||
|  |   - table: merge_requests | ||||||
|  |     column: merge_request_id | ||||||
|  |     on_delete: async_delete | ||||||
|  |   - table: projects | ||||||
|  |     column: project_id | ||||||
|  |     on_delete: async_delete | ||||||
|  |   - table: users | ||||||
|  |     column: user_id | ||||||
|  |     on_delete: async_delete | ||||||
| merge_requests: | merge_requests: | ||||||
|   - table: ci_pipelines |   - table: ci_pipelines | ||||||
|     column: head_pipeline_id |     column: head_pipeline_id | ||||||
|  |  | ||||||
|  | @ -261,7 +261,6 @@ module.exports = { | ||||||
|      */ |      */ | ||||||
|     return { |     return { | ||||||
|       default: defaultEntries, |       default: defaultEntries, | ||||||
|       legacy_sentry: './sentry/legacy_index.js', |  | ||||||
|       sentry: './sentry/index.js', |       sentry: './sentry/index.js', | ||||||
|       performance_bar: './performance_bar/index.js', |       performance_bar: './performance_bar/index.js', | ||||||
|       jira_connect_app: './jira_connect/subscriptions/index.js', |       jira_connect_app: './jira_connect/subscriptions/index.js', | ||||||
|  |  | ||||||
|  | @ -0,0 +1,40 @@ | ||||||
|  | - title: 'Runner `active` GraphQL fields replaced by `paused`' | ||||||
|  |   # The milestones for the deprecation announcement, and the removal. | ||||||
|  |   removal_milestone: '18.0' | ||||||
|  |   announcement_milestone: '14.8' | ||||||
|  |   # Change breaking_change to false if needed. | ||||||
|  |   breaking_change: true | ||||||
|  |   # The stage and GitLab username of the person reporting the change, | ||||||
|  |   # and a link to the deprecation issue | ||||||
|  |   reporter: pedropombeiro | ||||||
|  |   stage: Verify | ||||||
|  |   issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351109 | ||||||
|  |   impact: low | ||||||
|  |   scope: # Can be one or a combination of: [instance, group, project] | ||||||
|  |   resolution_role: Developer | ||||||
|  |   manual_task: true | ||||||
|  |   body: | # (required) Don't change this line. | ||||||
|  |     Occurrences of the `active` identifier in the GitLab GraphQL API endpoints will be renamed to `paused` in GitLab 18.0: | ||||||
|  | 
 | ||||||
|  |     - The `CiRunner` property. | ||||||
|  |     - The `RunnerUpdateInput` input type for the `runnerUpdate` mutation. | ||||||
|  |     - The `runners`, `Group.runners`, and `Project.runners` queries. | ||||||
|  | 
 | ||||||
|  |   # ============================== | ||||||
|  |   # OPTIONAL END-OF-SUPPORT FIELDS | ||||||
|  |   # ============================== | ||||||
|  |   # | ||||||
|  |   # If an End of Support period applies: | ||||||
|  |   # 1) Share this announcement in the `#spt_managers` Support channel in Slack | ||||||
|  |   # 2) Mention `@gitlab-com/support` in this merge request. | ||||||
|  |   # | ||||||
|  |   # When support for this feature ends, in XX.YY milestone format. | ||||||
|  |   end_of_support_milestone: | ||||||
|  |   # Array of tiers the feature is currently available to, | ||||||
|  |   # like [Free, Silver, Gold, Core, Premium, Ultimate] | ||||||
|  |   tiers: | ||||||
|  |   # Links to documentation and thumbnail image | ||||||
|  |   documentation_url: https://docs.gitlab.com/ee/api/graphql/reference/index.html#cirunner | ||||||
|  |   image_url: | ||||||
|  |   # Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg | ||||||
|  |   video_url: | ||||||
|  | @ -10,7 +10,7 @@ | ||||||
|   stage: ai-powered |   stage: ai-powered | ||||||
|   self-managed: true |   self-managed: true | ||||||
|   gitlab-com: true |   gitlab-com: true | ||||||
|   available_in: [Free, Premium, Ultimate] |   available_in: [Premium, Ultimate] | ||||||
|   documentation_link: https://docs.gitlab.com/ee/user/gitlab_duo_chat.html |   documentation_link: https://docs.gitlab.com/ee/user/gitlab_duo_chat.html | ||||||
|   image_url: https://img.youtube.com/vi/ZQBAuf-CTAY/hqdefault.jpg |   image_url: https://img.youtube.com/vi/ZQBAuf-CTAY/hqdefault.jpg | ||||||
|   published_at: 2024-04-18 |   published_at: 2024-04-18 | ||||||
|  | @ -52,7 +52,7 @@ | ||||||
|   stage: govern |   stage: govern | ||||||
|   self-managed: true |   self-managed: true | ||||||
|   gitlab-com: true |   gitlab-com: true | ||||||
|   available_in: [Free, Premium, Ultimate] |   available_in: [Premium, Ultimate] | ||||||
|   documentation_link: https://docs.gitlab.com/ee/editor_extensions/jetbrains_ide/index.html |   documentation_link: https://docs.gitlab.com/ee/editor_extensions/jetbrains_ide/index.html | ||||||
|   image_url: https://about.gitlab.com/images/16_11/create-duo-chat-in-jetbrains.png |   image_url: https://about.gitlab.com/images/16_11/create-duo-chat-in-jetbrains.png | ||||||
|   published_at: 2024-04-18 |   published_at: 2024-04-18 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | --- | ||||||
|  | migration_job_name: BackfillWorkspaceVariablesProjectId | ||||||
|  | description: Backfills sharding key `workspace_variables.project_id` from `workspaces`. | ||||||
|  | feature_category: remote_development | ||||||
|  | introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/150074 | ||||||
|  | milestone: '17.0' | ||||||
|  | queued_migration_version: 20240419035360 | ||||||
|  | finalize_after: '2024-05-22' | ||||||
|  | finalized_by: # version of the migration that finalized this BBM | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | --- | ||||||
|  | table_name: merge_request_requested_changes | ||||||
|  | classes: | ||||||
|  | - MergeRequests::RequestedChange | ||||||
|  | feature_categories: | ||||||
|  | - code_review_workflow | ||||||
|  | description: Blocker for changes requested on a merge request | ||||||
|  | introduced_by_url:  | ||||||
|  | milestone: '17.0' | ||||||
|  | gitlab_schema: gitlab_main_cell | ||||||
|  | sharding_key: | ||||||
|  |   project_id: projects | ||||||
|  | @ -23,3 +23,4 @@ desired_sharding_key: | ||||||
|         table: workspaces |         table: workspaces | ||||||
|         sharding_key: project_id |         sharding_key: project_id | ||||||
|         belongs_to: workspace |         belongs_to: workspace | ||||||
|  | desired_sharding_key_migration_job_name: BackfillWorkspaceVariablesProjectId | ||||||
|  |  | ||||||
|  | @ -0,0 +1,22 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class AddThrottleUnauthenticatedGitHttpToApplicationSettings < Gitlab::Database::Migration[2.2] | ||||||
|  |   milestone '17.0' | ||||||
|  | 
 | ||||||
|  |   disable_ddl_transaction! | ||||||
|  | 
 | ||||||
|  |   def up | ||||||
|  |     add_column :application_settings, :rate_limits_unauthenticated_git_http, :jsonb, default: {}, null: false, | ||||||
|  |       if_not_exists: true | ||||||
|  | 
 | ||||||
|  |     add_check_constraint( | ||||||
|  |       :application_settings, | ||||||
|  |       "(jsonb_typeof(rate_limits_unauthenticated_git_http) = 'object')", | ||||||
|  |       'check_application_settings_rate_limits_unauth_git_http_is_hash' | ||||||
|  |     ) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def down | ||||||
|  |     remove_column :application_settings, :rate_limits_unauthenticated_git_http, it_exists: true | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,24 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class UpdateThrottleUnauthenticatedGitHttpInApplicationSettings < Gitlab::Database::Migration[2.2] | ||||||
|  |   restrict_gitlab_migration gitlab_schema: :gitlab_main | ||||||
|  | 
 | ||||||
|  |   milestone '17.0' | ||||||
|  | 
 | ||||||
|  |   disable_ddl_transaction! | ||||||
|  | 
 | ||||||
|  |   def up | ||||||
|  |     execute <<~SQL | ||||||
|  |       UPDATE application_settings | ||||||
|  |       SET rate_limits_unauthenticated_git_http = jsonb_build_object( | ||||||
|  |         'throttle_unauthenticated_git_http_enabled', throttle_unauthenticated_enabled, | ||||||
|  |         'throttle_unauthenticated_git_http_requests_per_period', throttle_unauthenticated_requests_per_period, | ||||||
|  |         'throttle_unauthenticated_git_http_period_in_seconds', throttle_unauthenticated_period_in_seconds | ||||||
|  |       ); | ||||||
|  |     SQL | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def down | ||||||
|  |     execute "UPDATE application_settings SET rate_limits_unauthenticated_git_http = CAST('{}' AS jsonb)" | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class AddTrustedExternUidToIdentities < Gitlab::Database::Migration[2.2] | ||||||
|  |   milestone '17.0' | ||||||
|  | 
 | ||||||
|  |   enable_lock_retries! | ||||||
|  | 
 | ||||||
|  |   def change | ||||||
|  |     add_column :identities, :trusted_extern_uid, :boolean, default: true | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,17 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class IndexIdentitiesOnProvider < Gitlab::Database::Migration[2.2] | ||||||
|  |   milestone '17.0' | ||||||
|  | 
 | ||||||
|  |   disable_ddl_transaction! | ||||||
|  | 
 | ||||||
|  |   INDEX_NAME = 'index_identities_on_provider' | ||||||
|  | 
 | ||||||
|  |   def up | ||||||
|  |     add_concurrent_index :identities, :provider, name: INDEX_NAME | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def down | ||||||
|  |     remove_concurrent_index_by_name :identities, name: INDEX_NAME | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class AddProjectIdToWorkspaceVariables < Gitlab::Database::Migration[2.2] | ||||||
|  |   milestone '17.0' | ||||||
|  | 
 | ||||||
|  |   def change | ||||||
|  |     add_column :workspace_variables, :project_id, :bigint | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class IndexWorkspaceVariablesOnProjectId < Gitlab::Database::Migration[2.2] | ||||||
|  |   milestone '17.0' | ||||||
|  |   disable_ddl_transaction! | ||||||
|  | 
 | ||||||
|  |   INDEX_NAME = 'index_workspace_variables_on_project_id' | ||||||
|  | 
 | ||||||
|  |   def up | ||||||
|  |     add_concurrent_index :workspace_variables, :project_id, name: INDEX_NAME | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def down | ||||||
|  |     remove_concurrent_index_by_name :workspace_variables, INDEX_NAME | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class AddWorkspaceVariablesProjectIdFk < Gitlab::Database::Migration[2.2] | ||||||
|  |   milestone '17.0' | ||||||
|  |   disable_ddl_transaction! | ||||||
|  | 
 | ||||||
|  |   def up | ||||||
|  |     add_concurrent_foreign_key :workspace_variables, :projects, column: :project_id, on_delete: :cascade | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def down | ||||||
|  |     with_lock_retries do | ||||||
|  |       remove_foreign_key :workspace_variables, column: :project_id | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,19 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class CreateMergeRequestRequestedChanges < Gitlab::Database::Migration[2.2] | ||||||
|  |   milestone '17.0' | ||||||
|  | 
 | ||||||
|  |   def change | ||||||
|  |     create_table :merge_request_requested_changes do |t| | ||||||
|  |       t.bigint :project_id, null: false | ||||||
|  |       t.bigint :user_id, null: false | ||||||
|  |       t.bigint :merge_request_id, null: false | ||||||
|  | 
 | ||||||
|  |       t.timestamps_with_timezone null: false | ||||||
|  | 
 | ||||||
|  |       t.index :project_id | ||||||
|  |       t.index :user_id | ||||||
|  |       t.index :merge_request_id | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,25 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class AddWorkspaceVariablesProjectIdTrigger < Gitlab::Database::Migration[2.2] | ||||||
|  |   milestone '17.0' | ||||||
|  | 
 | ||||||
|  |   def up | ||||||
|  |     install_sharding_key_assignment_trigger( | ||||||
|  |       table: :workspace_variables, | ||||||
|  |       sharding_key: :project_id, | ||||||
|  |       parent_table: :workspaces, | ||||||
|  |       parent_sharding_key: :project_id, | ||||||
|  |       foreign_key: :workspace_id | ||||||
|  |     ) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def down | ||||||
|  |     remove_sharding_key_assignment_trigger( | ||||||
|  |       table: :workspace_variables, | ||||||
|  |       sharding_key: :project_id, | ||||||
|  |       parent_table: :workspaces, | ||||||
|  |       parent_sharding_key: :project_id, | ||||||
|  |       foreign_key: :workspace_id | ||||||
|  |     ) | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,40 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class QueueBackfillWorkspaceVariablesProjectId < Gitlab::Database::Migration[2.2] | ||||||
|  |   milestone '17.0' | ||||||
|  |   restrict_gitlab_migration gitlab_schema: :gitlab_main_cell | ||||||
|  | 
 | ||||||
|  |   MIGRATION = "BackfillWorkspaceVariablesProjectId" | ||||||
|  |   DELAY_INTERVAL = 2.minutes | ||||||
|  |   BATCH_SIZE = 1000 | ||||||
|  |   SUB_BATCH_SIZE = 100 | ||||||
|  | 
 | ||||||
|  |   def up | ||||||
|  |     queue_batched_background_migration( | ||||||
|  |       MIGRATION, | ||||||
|  |       :workspace_variables, | ||||||
|  |       :id, | ||||||
|  |       :project_id, | ||||||
|  |       :workspaces, | ||||||
|  |       :project_id, | ||||||
|  |       :workspace_id, | ||||||
|  |       job_interval: DELAY_INTERVAL, | ||||||
|  |       batch_size: BATCH_SIZE, | ||||||
|  |       sub_batch_size: SUB_BATCH_SIZE | ||||||
|  |     ) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def down | ||||||
|  |     delete_batched_background_migration( | ||||||
|  |       MIGRATION, | ||||||
|  |       :workspace_variables, | ||||||
|  |       :id, | ||||||
|  |       [ | ||||||
|  |         :project_id, | ||||||
|  |         :workspaces, | ||||||
|  |         :project_id, | ||||||
|  |         :workspace_id | ||||||
|  |       ] | ||||||
|  |     ) | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,17 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class SetTrustedExternUidToFalseForExistingBitbucketIdentities < Gitlab::Database::Migration[2.2] | ||||||
|  |   restrict_gitlab_migration gitlab_schema: :gitlab_main_clusterwide | ||||||
|  | 
 | ||||||
|  |   milestone '17.0' | ||||||
|  | 
 | ||||||
|  |   disable_ddl_transaction! | ||||||
|  | 
 | ||||||
|  |   BATCH_SIZE = 1000 | ||||||
|  | 
 | ||||||
|  |   def up | ||||||
|  |     define_batchable_model('identities').where(provider: 'bitbucket').each_batch(of: BATCH_SIZE) do |batch| | ||||||
|  |       batch.update_all(trusted_extern_uid: false) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 1f79208f10eac682970b91dd12159c9c7446fab637409d2f62dc91231af1dd13 | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | c84be5380fb2c1e90aabd987b8a7c020ec17405a8d0b97f0ca44e4ea724b7c6d | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 66b22a6c730d44535b321e0dd626c1b47fa3206ff811acd16007e9587a4c5d65 | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 8e74960909f458e3500f3857a4154b4b930dc21d4f5c1d7916f321f197220ba6 | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | a1f5f62a9782df2887fea2f8f1bccca6759e9da59d9a2778d6e7d09fc998d690 | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | ae763de6e4f8d746dce6d4c5d1aa68b1e756bbd0488d2ad705c016ecc7c04fcd | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 1867e85e95b2def01e9fc4ef4209e64f7afd5e71a1378a0024dadc3715cc07aa | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 0ed31058286c68932a683e6072002fd5fe6a4d785c113db22028262aafc47c86 | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 6f571972797eee34572944fb18ecf389d97c5880838b9c3c0ccf7ebbe5937f1d | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | a845ee1d6e023d976f526e76d2d690ec2a168d8975eda3edb5a1e9932d26c16c | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | cab7740141a0b515fbaf0c6e38c3d2aea4ac5ff765a2978ccd89f4274d44c1d1 | ||||||
|  | @ -695,6 +695,22 @@ BEGIN | ||||||
| END; | END; | ||||||
| $$; | $$; | ||||||
| 
 | 
 | ||||||
|  | CREATE FUNCTION trigger_56d49f4ed623() RETURNS trigger | ||||||
|  |     LANGUAGE plpgsql | ||||||
|  |     AS $$ | ||||||
|  | BEGIN | ||||||
|  | IF NEW."project_id" IS NULL THEN | ||||||
|  |   SELECT "project_id" | ||||||
|  |   INTO NEW."project_id" | ||||||
|  |   FROM "workspaces" | ||||||
|  |   WHERE "workspaces"."id" = NEW."workspace_id"; | ||||||
|  | END IF; | ||||||
|  | 
 | ||||||
|  | RETURN NEW; | ||||||
|  | 
 | ||||||
|  | END | ||||||
|  | $$; | ||||||
|  | 
 | ||||||
| CREATE FUNCTION trigger_94514aeadc50() RETURNS trigger | CREATE FUNCTION trigger_94514aeadc50() RETURNS trigger | ||||||
|     LANGUAGE plpgsql |     LANGUAGE plpgsql | ||||||
|     AS $$ |     AS $$ | ||||||
|  | @ -4319,6 +4335,7 @@ CREATE TABLE application_settings ( | ||||||
|     include_optional_metrics_in_service_ping boolean DEFAULT true NOT NULL, |     include_optional_metrics_in_service_ping boolean DEFAULT true NOT NULL, | ||||||
|     zoekt_settings jsonb DEFAULT '{}'::jsonb NOT NULL, |     zoekt_settings jsonb DEFAULT '{}'::jsonb NOT NULL, | ||||||
|     service_ping_settings jsonb DEFAULT '{}'::jsonb NOT NULL, |     service_ping_settings jsonb DEFAULT '{}'::jsonb NOT NULL, | ||||||
|  |     rate_limits_unauthenticated_git_http jsonb DEFAULT '{}'::jsonb NOT NULL, | ||||||
|     CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)), |     CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)), | ||||||
|     CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)), |     CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)), | ||||||
|     CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)), |     CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)), | ||||||
|  | @ -4371,6 +4388,7 @@ CREATE TABLE application_settings ( | ||||||
|     CONSTRAINT check_app_settings_sentry_clientside_traces_sample_rate_range CHECK (((sentry_clientside_traces_sample_rate >= (0)::double precision) AND (sentry_clientside_traces_sample_rate <= (1)::double precision))), |     CONSTRAINT check_app_settings_sentry_clientside_traces_sample_rate_range CHECK (((sentry_clientside_traces_sample_rate >= (0)::double precision) AND (sentry_clientside_traces_sample_rate <= (1)::double precision))), | ||||||
|     CONSTRAINT check_application_settings_clickhouse_is_hash CHECK ((jsonb_typeof(clickhouse) = 'object'::text)), |     CONSTRAINT check_application_settings_clickhouse_is_hash CHECK ((jsonb_typeof(clickhouse) = 'object'::text)), | ||||||
|     CONSTRAINT check_application_settings_rate_limits_is_hash CHECK ((jsonb_typeof(rate_limits) = 'object'::text)), |     CONSTRAINT check_application_settings_rate_limits_is_hash CHECK ((jsonb_typeof(rate_limits) = 'object'::text)), | ||||||
|  |     CONSTRAINT check_application_settings_rate_limits_unauth_git_http_is_hash CHECK ((jsonb_typeof(rate_limits_unauthenticated_git_http) = 'object'::text)), | ||||||
|     CONSTRAINT check_application_settings_service_ping_settings_is_hash CHECK ((jsonb_typeof(service_ping_settings) = 'object'::text)), |     CONSTRAINT check_application_settings_service_ping_settings_is_hash CHECK ((jsonb_typeof(service_ping_settings) = 'object'::text)), | ||||||
|     CONSTRAINT check_b8c74ea5b3 CHECK ((char_length(deactivation_email_additional_text) <= 1000)), |     CONSTRAINT check_b8c74ea5b3 CHECK ((char_length(deactivation_email_additional_text) <= 1000)), | ||||||
|     CONSTRAINT check_cdfbd99405 CHECK ((char_length(security_txt_content) <= 2048)), |     CONSTRAINT check_cdfbd99405 CHECK ((char_length(security_txt_content) <= 2048)), | ||||||
|  | @ -9764,7 +9782,8 @@ CREATE TABLE identities ( | ||||||
|     created_at timestamp without time zone, |     created_at timestamp without time zone, | ||||||
|     updated_at timestamp without time zone, |     updated_at timestamp without time zone, | ||||||
|     secondary_extern_uid character varying, |     secondary_extern_uid character varying, | ||||||
|     saml_provider_id integer |     saml_provider_id integer, | ||||||
|  |     trusted_extern_uid boolean DEFAULT true | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| CREATE SEQUENCE identities_id_seq | CREATE SEQUENCE identities_id_seq | ||||||
|  | @ -11250,6 +11269,24 @@ CREATE SEQUENCE merge_request_predictions_merge_request_id_seq | ||||||
| 
 | 
 | ||||||
| ALTER SEQUENCE merge_request_predictions_merge_request_id_seq OWNED BY merge_request_predictions.merge_request_id; | ALTER SEQUENCE merge_request_predictions_merge_request_id_seq OWNED BY merge_request_predictions.merge_request_id; | ||||||
| 
 | 
 | ||||||
|  | CREATE TABLE merge_request_requested_changes ( | ||||||
|  |     id bigint NOT NULL, | ||||||
|  |     project_id bigint NOT NULL, | ||||||
|  |     user_id bigint NOT NULL, | ||||||
|  |     merge_request_id bigint NOT NULL, | ||||||
|  |     created_at timestamp with time zone NOT NULL, | ||||||
|  |     updated_at timestamp with time zone NOT NULL | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | CREATE SEQUENCE merge_request_requested_changes_id_seq | ||||||
|  |     START WITH 1 | ||||||
|  |     INCREMENT BY 1 | ||||||
|  |     NO MINVALUE | ||||||
|  |     NO MAXVALUE | ||||||
|  |     CACHE 1; | ||||||
|  | 
 | ||||||
|  | ALTER SEQUENCE merge_request_requested_changes_id_seq OWNED BY merge_request_requested_changes.id; | ||||||
|  | 
 | ||||||
| CREATE TABLE merge_request_review_llm_summaries ( | CREATE TABLE merge_request_review_llm_summaries ( | ||||||
|     id bigint NOT NULL, |     id bigint NOT NULL, | ||||||
|     user_id bigint, |     user_id bigint, | ||||||
|  | @ -18123,6 +18160,7 @@ CREATE TABLE workspace_variables ( | ||||||
|     key text NOT NULL, |     key text NOT NULL, | ||||||
|     encrypted_value bytea NOT NULL, |     encrypted_value bytea NOT NULL, | ||||||
|     encrypted_value_iv bytea NOT NULL, |     encrypted_value_iv bytea NOT NULL, | ||||||
|  |     project_id bigint, | ||||||
|     CONSTRAINT check_5545042100 CHECK ((char_length(key) <= 255)) |     CONSTRAINT check_5545042100 CHECK ((char_length(key) <= 255)) | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
|  | @ -19403,6 +19441,8 @@ ALTER TABLE ONLY merge_request_metrics ALTER COLUMN id SET DEFAULT nextval('merg | ||||||
| 
 | 
 | ||||||
| ALTER TABLE ONLY merge_request_predictions ALTER COLUMN merge_request_id SET DEFAULT nextval('merge_request_predictions_merge_request_id_seq'::regclass); | ALTER TABLE ONLY merge_request_predictions ALTER COLUMN merge_request_id SET DEFAULT nextval('merge_request_predictions_merge_request_id_seq'::regclass); | ||||||
| 
 | 
 | ||||||
|  | ALTER TABLE ONLY merge_request_requested_changes ALTER COLUMN id SET DEFAULT nextval('merge_request_requested_changes_id_seq'::regclass); | ||||||
|  | 
 | ||||||
| ALTER TABLE ONLY merge_request_review_llm_summaries ALTER COLUMN id SET DEFAULT nextval('merge_request_review_llm_summaries_id_seq'::regclass); | ALTER TABLE ONLY merge_request_review_llm_summaries ALTER COLUMN id SET DEFAULT nextval('merge_request_review_llm_summaries_id_seq'::regclass); | ||||||
| 
 | 
 | ||||||
| ALTER TABLE ONLY merge_request_reviewers ALTER COLUMN id SET DEFAULT nextval('merge_request_reviewers_id_seq'::regclass); | ALTER TABLE ONLY merge_request_reviewers ALTER COLUMN id SET DEFAULT nextval('merge_request_reviewers_id_seq'::regclass); | ||||||
|  | @ -21650,6 +21690,9 @@ ALTER TABLE ONLY merge_request_metrics | ||||||
| ALTER TABLE ONLY merge_request_predictions | ALTER TABLE ONLY merge_request_predictions | ||||||
|     ADD CONSTRAINT merge_request_predictions_pkey PRIMARY KEY (merge_request_id); |     ADD CONSTRAINT merge_request_predictions_pkey PRIMARY KEY (merge_request_id); | ||||||
| 
 | 
 | ||||||
|  | ALTER TABLE ONLY merge_request_requested_changes | ||||||
|  |     ADD CONSTRAINT merge_request_requested_changes_pkey PRIMARY KEY (id); | ||||||
|  | 
 | ||||||
| ALTER TABLE ONLY merge_request_review_llm_summaries | ALTER TABLE ONLY merge_request_review_llm_summaries | ||||||
|     ADD CONSTRAINT merge_request_review_llm_summaries_pkey PRIMARY KEY (id); |     ADD CONSTRAINT merge_request_review_llm_summaries_pkey PRIMARY KEY (id); | ||||||
| 
 | 
 | ||||||
|  | @ -25656,6 +25699,8 @@ CREATE INDEX index_historical_data_on_recorded_at ON historical_data USING btree | ||||||
| 
 | 
 | ||||||
| CREATE UNIQUE INDEX index_http_integrations_on_project_and_endpoint ON alert_management_http_integrations USING btree (project_id, endpoint_identifier); | CREATE UNIQUE INDEX index_http_integrations_on_project_and_endpoint ON alert_management_http_integrations USING btree (project_id, endpoint_identifier); | ||||||
| 
 | 
 | ||||||
|  | CREATE INDEX index_identities_on_provider ON identities USING btree (provider); | ||||||
|  | 
 | ||||||
| CREATE INDEX index_identities_on_saml_provider_id ON identities USING btree (saml_provider_id) WHERE (saml_provider_id IS NOT NULL); | CREATE INDEX index_identities_on_saml_provider_id ON identities USING btree (saml_provider_id) WHERE (saml_provider_id IS NOT NULL); | ||||||
| 
 | 
 | ||||||
| CREATE INDEX index_identities_on_user_id ON identities USING btree (user_id); | CREATE INDEX index_identities_on_user_id ON identities USING btree (user_id); | ||||||
|  | @ -26068,6 +26113,12 @@ CREATE INDEX index_merge_request_metrics_on_merged_at ON merge_request_metrics U | ||||||
| 
 | 
 | ||||||
| CREATE INDEX index_merge_request_metrics_on_pipeline_id ON merge_request_metrics USING btree (pipeline_id); | CREATE INDEX index_merge_request_metrics_on_pipeline_id ON merge_request_metrics USING btree (pipeline_id); | ||||||
| 
 | 
 | ||||||
|  | CREATE INDEX index_merge_request_requested_changes_on_merge_request_id ON merge_request_requested_changes USING btree (merge_request_id); | ||||||
|  | 
 | ||||||
|  | CREATE INDEX index_merge_request_requested_changes_on_project_id ON merge_request_requested_changes USING btree (project_id); | ||||||
|  | 
 | ||||||
|  | CREATE INDEX index_merge_request_requested_changes_on_user_id ON merge_request_requested_changes USING btree (user_id); | ||||||
|  | 
 | ||||||
| CREATE INDEX index_merge_request_review_llm_summaries_on_mr_diff_id ON merge_request_review_llm_summaries USING btree (merge_request_diff_id); | CREATE INDEX index_merge_request_review_llm_summaries_on_mr_diff_id ON merge_request_review_llm_summaries USING btree (merge_request_diff_id); | ||||||
| 
 | 
 | ||||||
| CREATE INDEX index_merge_request_review_llm_summaries_on_review_id ON merge_request_review_llm_summaries USING btree (review_id); | CREATE INDEX index_merge_request_review_llm_summaries_on_review_id ON merge_request_review_llm_summaries USING btree (review_id); | ||||||
|  | @ -27838,6 +27889,8 @@ CREATE UNIQUE INDEX index_work_item_widget_definitions_on_namespace_type_and_nam | ||||||
| 
 | 
 | ||||||
| CREATE INDEX index_work_item_widget_definitions_on_work_item_type_id ON work_item_widget_definitions USING btree (work_item_type_id); | CREATE INDEX index_work_item_widget_definitions_on_work_item_type_id ON work_item_widget_definitions USING btree (work_item_type_id); | ||||||
| 
 | 
 | ||||||
|  | CREATE INDEX index_workspace_variables_on_project_id ON workspace_variables USING btree (project_id); | ||||||
|  | 
 | ||||||
| CREATE INDEX index_workspace_variables_on_workspace_id ON workspace_variables USING btree (workspace_id); | CREATE INDEX index_workspace_variables_on_workspace_id ON workspace_variables USING btree (workspace_id); | ||||||
| 
 | 
 | ||||||
| CREATE INDEX index_workspaces_on_cluster_agent_id ON workspaces USING btree (cluster_agent_id); | CREATE INDEX index_workspaces_on_cluster_agent_id ON workspaces USING btree (cluster_agent_id); | ||||||
|  | @ -29722,6 +29775,8 @@ CREATE TRIGGER trigger_3857ca5ea4af BEFORE INSERT OR UPDATE ON merge_trains FOR | ||||||
| 
 | 
 | ||||||
| CREATE TRIGGER trigger_388e93f88fdd BEFORE INSERT OR UPDATE ON packages_build_infos FOR EACH ROW EXECUTE FUNCTION trigger_388e93f88fdd(); | CREATE TRIGGER trigger_388e93f88fdd BEFORE INSERT OR UPDATE ON packages_build_infos FOR EACH ROW EXECUTE FUNCTION trigger_388e93f88fdd(); | ||||||
| 
 | 
 | ||||||
|  | CREATE TRIGGER trigger_56d49f4ed623 BEFORE INSERT OR UPDATE ON workspace_variables FOR EACH ROW EXECUTE FUNCTION trigger_56d49f4ed623(); | ||||||
|  | 
 | ||||||
| CREATE TRIGGER trigger_94514aeadc50 BEFORE INSERT OR UPDATE ON deployment_approvals FOR EACH ROW EXECUTE FUNCTION trigger_94514aeadc50(); | CREATE TRIGGER trigger_94514aeadc50 BEFORE INSERT OR UPDATE ON deployment_approvals FOR EACH ROW EXECUTE FUNCTION trigger_94514aeadc50(); | ||||||
| 
 | 
 | ||||||
| CREATE TRIGGER trigger_b2d852e1e2cb BEFORE INSERT OR UPDATE ON ci_pipelines FOR EACH ROW EXECUTE FUNCTION trigger_b2d852e1e2cb(); | CREATE TRIGGER trigger_b2d852e1e2cb BEFORE INSERT OR UPDATE ON ci_pipelines FOR EACH ROW EXECUTE FUNCTION trigger_b2d852e1e2cb(); | ||||||
|  | @ -30091,6 +30146,9 @@ ALTER TABLE ONLY todos | ||||||
| ALTER TABLE ONLY releases | ALTER TABLE ONLY releases | ||||||
|     ADD CONSTRAINT fk_47fe2a0596 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; |     ADD CONSTRAINT fk_47fe2a0596 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; | ||||||
| 
 | 
 | ||||||
|  | ALTER TABLE ONLY workspace_variables | ||||||
|  |     ADD CONSTRAINT fk_494e093520 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; | ||||||
|  | 
 | ||||||
| ALTER TABLE ONLY geo_event_log | ALTER TABLE ONLY geo_event_log | ||||||
|     ADD CONSTRAINT fk_4a99ebfd60 FOREIGN KEY (repositories_changed_event_id) REFERENCES geo_repositories_changed_events(id) ON DELETE CASCADE; |     ADD CONSTRAINT fk_4a99ebfd60 FOREIGN KEY (repositories_changed_event_id) REFERENCES geo_repositories_changed_events(id) ON DELETE CASCADE; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -177,8 +177,7 @@ WARNING: | ||||||
| In a multi-server setup you must use one of the options to | In a multi-server setup you must use one of the options to | ||||||
| [eliminate local disk usage for job logs](job_logs.md#prevent-local-disk-usage), or job logs could be lost. | [eliminate local disk usage for job logs](job_logs.md#prevent-local-disk-usage), or job logs could be lost. | ||||||
| 
 | 
 | ||||||
| In GitLab 13.2 and later, you should use the | You should use the [consolidated object storage settings](object_storage.md#configure-a-single-storage-connection-for-all-object-types-consolidated-form). | ||||||
| [consolidated object storage settings](object_storage.md#configure-a-single-storage-connection-for-all-object-types-consolidated-form). |  | ||||||
| 
 | 
 | ||||||
| ### Migrating to object storage | ### Migrating to object storage | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -23,8 +23,7 @@ reasons are: | ||||||
| - Artifact files might be left on disk and not deleted by housekeeping. Run the | - Artifact files might be left on disk and not deleted by housekeeping. Run the | ||||||
|   [Rake task for _orphaned_ artifact files](../raketasks/cleanup.md#remove-orphan-artifact-files) |   [Rake task for _orphaned_ artifact files](../raketasks/cleanup.md#remove-orphan-artifact-files) | ||||||
|   to remove these. This script should always find work to do, as it also removes empty directories (see above). |   to remove these. This script should always find work to do, as it also removes empty directories (see above). | ||||||
| - [Artifact housekeeping was changed significantly](#housekeeping-disabled-in-gitlab-146-to-152), | - [Artifact housekeeping was changed significantly](#housekeeping-disabled-in-gitlab-150-to-152), and you might need to enable a feature flag to use the updated system. | ||||||
|   and you might need to enable a feature flag to use the updated system. |  | ||||||
| - The [keep latest artifacts from most recent success jobs](../ci/jobs/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs) | - The [keep latest artifacts from most recent success jobs](../ci/jobs/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs) | ||||||
|   feature is enabled. |   feature is enabled. | ||||||
| 
 | 
 | ||||||
|  | @ -37,15 +36,11 @@ space, and in some cases, manually delete job artifacts to reclaim disk space. | ||||||
| Artifacts housekeeping is the process that identifies which artifacts are expired | Artifacts housekeeping is the process that identifies which artifacts are expired | ||||||
| and can be deleted. | and can be deleted. | ||||||
| 
 | 
 | ||||||
| #### Housekeeping disabled in GitLab 14.6 to 15.2 | #### Housekeeping disabled in GitLab 15.0 to 15.2 | ||||||
| 
 | 
 | ||||||
| Artifact housekeeping was disabled in GitLab 14.6. It was significantly improved | Artifact housekeeping was significantly improved in GitLab 15.0, introduced behind [feature flags](feature_flags.md) disabled by default. The flags were enabled by default [in GitLab 15.3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92931). | ||||||
| in GitLab 14.10, and the changes were back ported to patch versions of GitLab 14.6 and later, |  | ||||||
| introduced behind [feature flags](feature_flags.md) disabled by default. The flags were |  | ||||||
| enabled by default [in GitLab 15.3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92931). |  | ||||||
| 
 | 
 | ||||||
| If artifacts housekeeping does not seem to be working in GitLab 14.6 to GitLab 15.2, | If artifacts housekeeping does not seem to be working in GitLab 15.0 to GitLab 15.2, you should check if the feature flags are enabled. | ||||||
| you should check if the feature flags are enabled. |  | ||||||
| 
 | 
 | ||||||
| To check if the feature flags are enabled: | To check if the feature flags are enabled: | ||||||
| 
 | 
 | ||||||
|  | @ -53,21 +48,11 @@ To check if the feature flags are enabled: | ||||||
| 
 | 
 | ||||||
| 1. Check if the feature flags are enabled. | 1. Check if the feature flags are enabled. | ||||||
| 
 | 
 | ||||||
|    - GitLab 14.10 and earlier: |    ```ruby | ||||||
| 
 |    Feature.enabled?(:ci_detect_wrongly_expired_artifacts) | ||||||
|      ```ruby |    Feature.enabled?(:ci_update_unlocked_job_artifacts) | ||||||
|      Feature.enabled?(:ci_detect_wrongly_expired_artifacts, default_enabled: :yaml) |    Feature.enabled?(:ci_job_artifacts_backlog_work) | ||||||
|      Feature.enabled?(:ci_update_unlocked_job_artifacts, default_enabled: :yaml) |    ``` | ||||||
|      Feature.enabled?(:ci_job_artifacts_backlog_work, default_enabled: :yaml) |  | ||||||
|      ``` |  | ||||||
| 
 |  | ||||||
|    - GitLab 15.0 and later: |  | ||||||
| 
 |  | ||||||
|      ```ruby |  | ||||||
|      Feature.enabled?(:ci_detect_wrongly_expired_artifacts) |  | ||||||
|      Feature.enabled?(:ci_update_unlocked_job_artifacts) |  | ||||||
|      Feature.enabled?(:ci_job_artifacts_backlog_work) |  | ||||||
|      ``` |  | ||||||
| 
 | 
 | ||||||
| 1. If any of the feature flags are disabled, enable them: | 1. If any of the feature flags are disabled, enable them: | ||||||
| 
 | 
 | ||||||
|  | @ -154,23 +139,15 @@ GitLab 15.3 and later. It analyzes the artifacts returned by the above database | ||||||
| determines which should be `locked` or `unlocked`. Artifacts are then deleted | determines which should be `locked` or `unlocked`. Artifacts are then deleted | ||||||
| by that worker if needed. | by that worker if needed. | ||||||
| 
 | 
 | ||||||
| The worker can be enabled on self-managed instances running GitLab 14.10 and later: | The worker can be enabled on self-managed instances: | ||||||
| 
 | 
 | ||||||
| 1. Start a [Rails console](operations/rails_console.md#starting-a-rails-console-session). | 1. Start a [Rails console](operations/rails_console.md#starting-a-rails-console-session). | ||||||
| 
 | 
 | ||||||
| 1. Check if the feature is enabled. | 1. Check if the feature is enabled. | ||||||
| 
 |     | ||||||
|    - GitLab 14.10: |    ```ruby | ||||||
| 
 |    Feature.enabled?(:ci_job_artifacts_backlog_work) | ||||||
|      ```ruby |    ``` | ||||||
|      Feature.enabled?(:ci_job_artifacts_backlog_work, default_enabled: :yaml) |  | ||||||
|      ``` |  | ||||||
| 
 |  | ||||||
|    - GitLab 15.0 and later: |  | ||||||
| 
 |  | ||||||
|      ```ruby |  | ||||||
|      Feature.enabled?(:ci_job_artifacts_backlog_work) |  | ||||||
|      ``` |  | ||||||
| 
 | 
 | ||||||
| 1. Enable the feature, if needed: | 1. Enable the feature, if needed: | ||||||
| 
 | 
 | ||||||
|  | @ -429,8 +406,6 @@ For more information, [see the investigation details](https://gitlab.com/gitlab- | ||||||
| 
 | 
 | ||||||
| ## Usage quota shows incorrect artifact storage usage | ## Usage quota shows incorrect artifact storage usage | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/238536) in GitLab 14.10. |  | ||||||
| 
 |  | ||||||
| Sometimes the [artifacts storage usage](../user/usage_quotas.md) displays an incorrect | Sometimes the [artifacts storage usage](../user/usage_quotas.md) displays an incorrect | ||||||
| value for the total storage space used by artifacts. To recalculate the artifact | value for the total storage space used by artifacts. To recalculate the artifact | ||||||
| usage statistics for all projects in the instance, you can run this background script: | usage statistics for all projects in the instance, you can run this background script: | ||||||
|  |  | ||||||
|  | @ -119,28 +119,25 @@ If you need support for namespace in the URL path to remove the requirement for | ||||||
| 
 | 
 | ||||||
| 1. Enable the GitLab Pages flag for this feature by adding | 1. Enable the GitLab Pages flag for this feature by adding | ||||||
|    `gitlab_pages["namespace_in_path"] = true` to `/etc/gitlab/gitlab.rb`. |    `gitlab_pages["namespace_in_path"] = true` to `/etc/gitlab/gitlab.rb`. | ||||||
| 1. In your DNS provider, add entries for `example.io` and `projects.example.io`. | 1. In your DNS provider, add entries for `example.io`. | ||||||
|    In both lines, replace `example.io` with your domain name, and `192.0.0.0` with |    Replace `example.io` with your domain name, and `192.0.0.0` with | ||||||
|    the IPv4 version of your IP address. The entries look like this: |    the IPv4 version of your IP address. The entries look like this: | ||||||
| 
 | 
 | ||||||
|    ```plaintext |    ```plaintext | ||||||
|    example.io          1800 IN A    192.0.0.0 |    example.io          1800 IN A    192.0.0.0 | ||||||
|    projects.example.io 1800 IN A    192.0.0.0 |  | ||||||
|    ``` |    ``` | ||||||
| 
 | 
 | ||||||
| 1. Optional. If your GitLab instance has an IPv6 address, add entries for it. | 1. Optional. If your GitLab instance has an IPv6 address, add entries for it. | ||||||
|    In both lines, replace `example.io` with your domain name, and `2001:db8::1` with |    Replace `example.io` with your domain name, and `2001:db8::1` with | ||||||
|    the IPv6 version of your IP address. The entries look like this: |    the IPv6 version of your IP address. The entries look like this: | ||||||
| 
 | 
 | ||||||
|    ```plaintext |    ```plaintext | ||||||
|    example.io          1800 IN AAAA 2001:db8::1 |    example.io          1800 IN AAAA 2001:db8::1 | ||||||
|    projects.example.io 1800 IN AAAA 2001:db8::1 |  | ||||||
|    ``` |    ``` | ||||||
| 
 | 
 | ||||||
| This example contains the following: | This example contains the following: | ||||||
| 
 | 
 | ||||||
| - `example.io`: The domain GitLab Pages is served from. | - `example.io`: The domain GitLab Pages is served from. | ||||||
| - `projects.example.io`: An additional subdomain for GitLab Pages default authentication flow. |  | ||||||
| 
 | 
 | ||||||
| #### DNS configuration for custom domains | #### DNS configuration for custom domains | ||||||
| 
 | 
 | ||||||
|  | @ -306,8 +303,7 @@ Prerequisites: | ||||||
| - Your instance must use the Linux package installation method. | - Your instance must use the Linux package installation method. | ||||||
| - You have configured DNS setup | - You have configured DNS setup | ||||||
|   [without a wildcard](#for-namespace-in-url-path-without-wildcard-dns). |   [without a wildcard](#for-namespace-in-url-path-without-wildcard-dns). | ||||||
| - You have a single TLS certificate that covers your domain (like `example.io`) | - You have a TLS certificate that covers your domain (like `example.io`). | ||||||
|   and the `projects.*` version of your domain, like `projects.example.io`. |  | ||||||
| 
 | 
 | ||||||
| In this configuration, NGINX proxies all requests to the daemon. The GitLab Pages | In this configuration, NGINX proxies all requests to the daemon. The GitLab Pages | ||||||
| daemon doesn't listen to the outside world: | daemon doesn't listen to the outside world: | ||||||
|  | @ -337,17 +333,18 @@ daemon doesn't listen to the outside world: | ||||||
|    pages_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/pages-nginx.key" |    pages_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/pages-nginx.key" | ||||||
|    ``` |    ``` | ||||||
| 
 | 
 | ||||||
| 1. [Reconfigure GitLab](../restart_gitlab.md#reconfigure-a-linux-package-installation). | 1. If you're using [Pages Access Control](#access-control), update the redirect URI in the GitLab Pages | ||||||
|  |    [System OAuth application](../../integration/oauth_provider.md#create-an-instance-wide-application) | ||||||
|  |    to use the HTTPS protocol. | ||||||
| 
 | 
 | ||||||
|    WARNING: |    WARNING: | ||||||
|    GitLab Pages does not update the OAuth application if changes are made to the redirect URI. |    GitLab Pages does not update the OAuth application, and | ||||||
|  |    the default `auth_redirect_uri` is updated to `https://example.io/projects/auth`. | ||||||
|    Before you reconfigure, remove the `gitlab_pages` section from `/etc/gitlab/gitlab-secrets.json`, |    Before you reconfigure, remove the `gitlab_pages` section from `/etc/gitlab/gitlab-secrets.json`, | ||||||
|    then run `gitlab-ctl reconfigure`. For more information, see |    then run `gitlab-ctl reconfigure`. For more information, see | ||||||
|    [GitLab Pages does not regenerate OAuth](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3947). |    [GitLab Pages does not regenerate OAuth](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3947). | ||||||
| 
 | 
 | ||||||
| 1. If you're using [Pages Access Control](#access-control), update the redirect URI in the GitLab Pages | 1. [Reconfigure GitLab](../restart_gitlab.md#reconfigure-a-linux-package-installation). | ||||||
|    [System OAuth application](../../integration/oauth_provider.md#create-an-instance-wide-application) |  | ||||||
|    to use the HTTPS protocol. |  | ||||||
| 
 | 
 | ||||||
| NGINX uses the custom proxy header `X-Gitlab-Namespace-In-Path` | NGINX uses the custom proxy header `X-Gitlab-Namespace-In-Path` | ||||||
| to send the namespace to the GitLab Pages daemon. | to send the namespace to the GitLab Pages daemon. | ||||||
|  |  | ||||||
|  | @ -0,0 +1,41 @@ | ||||||
|  | --- | ||||||
|  | stage: Create | ||||||
|  | group: Source Code | ||||||
|  | info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments | ||||||
|  | --- | ||||||
|  | 
 | ||||||
|  | # Rate limits on Git HTTP | ||||||
|  | 
 | ||||||
|  | DETAILS: | ||||||
|  | **Tier:** Free, Premium, Ultimate | ||||||
|  | **Offering:** Self-managed, GitLab Dedicated | ||||||
|  | 
 | ||||||
|  | > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/147112) in GitLab 17.0. | ||||||
|  | 
 | ||||||
|  | If you use Git HTTP in your repository, | ||||||
|  | common Git operations can generate many Git HTTP requests. | ||||||
|  | Some of these Git HTTP requests do not contain authentication parameter and | ||||||
|  | are considered unauthenticated. You can enforce rate limits on Git HTTP requests. | ||||||
|  | This can improve the security and durability of your web application. | ||||||
|  | [General user and IP rate limits](../settings/user_and_ip_rate_limits.md) aren't applied | ||||||
|  | to Git HTTP requests. | ||||||
|  | 
 | ||||||
|  | ## Configure Git HTTP rate limits | ||||||
|  | 
 | ||||||
|  | Git HTTP rate limits are disabled by default. If enabled and configured, these limits | ||||||
|  | are applied to Git HTTP requests. | ||||||
|  | 
 | ||||||
|  | To configure Git HTTP rate limits: | ||||||
|  | 
 | ||||||
|  | 1. On the left sidebar, at the bottom, select **Admin Area**. | ||||||
|  | 1. Select **Settings > Network**. | ||||||
|  | 1. Expand **Git HTTP rate limits**. | ||||||
|  | 1. Select **Enable unauthenticated Git HTTP request rate limit**. | ||||||
|  | 1. Enter a value for **Max unauthenticated Git HTTP requests per period per user**. | ||||||
|  | 1. Enter a value for **Unauthenticated Git HTTP rate limit period in seconds**. | ||||||
|  | 1. Select **Save changes**. | ||||||
|  | 
 | ||||||
|  | ## Related topics | ||||||
|  | 
 | ||||||
|  | - [Rate limiting](../../security/rate_limits.md) | ||||||
|  | - [User and IP rate limits](../settings/user_and_ip_rate_limits.md) | ||||||
|  | @ -9,6 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w | ||||||
| You can change network settings to limit the rate of connections with your instance. | You can change network settings to limit the rate of connections with your instance. | ||||||
| 
 | 
 | ||||||
| - [Deprecated API rate limits](deprecated_api_rate_limits.md) | - [Deprecated API rate limits](deprecated_api_rate_limits.md) | ||||||
|  | - [Git HTTP](git_http_rate_limits.md) | ||||||
| - [Git LFS](git_lfs_rate_limits.md) | - [Git LFS](git_lfs_rate_limits.md) | ||||||
| - [Git SSH operations](rate_limits_on_git_ssh_operations.md) | - [Git SSH operations](rate_limits_on_git_ssh_operations.md) | ||||||
| - [Incident management](incident_management_rate_limits.md) | - [Incident management](incident_management_rate_limits.md) | ||||||
|  |  | ||||||
|  | @ -15,9 +15,6 @@ This API is in an [Experiment](../policy/experiment-beta-support.md#experiment) | ||||||
| The response payload may be subject to change or breakage | The response payload may be subject to change or breakage | ||||||
| across GitLab releases. | across GitLab releases. | ||||||
| 
 | 
 | ||||||
| > - Introduced in GitLab 12.1. |  | ||||||
| > - Pagination introduced in 14.4. |  | ||||||
| 
 |  | ||||||
| Every call to this endpoint requires authentication. To perform this call, user should be authorized to read repository. | Every call to this endpoint requires authentication. To perform this call, user should be authorized to read repository. | ||||||
| To see vulnerabilities in response, user should be authorized to read | To see vulnerabilities in response, user should be authorized to read | ||||||
| [Project Security Dashboard](../user/application_security/security_dashboard/index.md). | [Project Security Dashboard](../user/application_security/security_dashboard/index.md). | ||||||
|  |  | ||||||
|  | @ -316,9 +316,6 @@ If the artifacts were deleted successfully, a response with status `204 No Conte | ||||||
| 
 | 
 | ||||||
| ## Delete project artifacts | ## Delete project artifacts | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223793) in GitLab 14.7 [with a flag](../administration/feature_flags.md) named `bulk_expire_project_artifacts`. Enabled by default on GitLab self-managed. Enabled on GitLab.com. |  | ||||||
| > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/350609) in GitLab 14.10. |  | ||||||
| 
 |  | ||||||
| Delete artifacts eligible for deletion in a project. By default, artifacts from | Delete artifacts eligible for deletion in a project. By default, artifacts from | ||||||
| [the most recent successful pipeline of each ref](../ci/jobs/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs) | [the most recent successful pipeline of each ref](../ci/jobs/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs) | ||||||
| are not deleted. | are not deleted. | ||||||
|  |  | ||||||
|  | @ -184,9 +184,6 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git | ||||||
| 
 | 
 | ||||||
| ## The `filter` parameter | ## The `filter` parameter | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34490) in GitLab 13.2. |  | ||||||
| > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/227052) in GitLab 13.4. |  | ||||||
| 
 |  | ||||||
| When multiple variables have the same `key`, [GET](#get-a-single-variable), [PUT](#update-a-variable), | When multiple variables have the same `key`, [GET](#get-a-single-variable), [PUT](#update-a-variable), | ||||||
| or [DELETE](#delete-a-variable) requests might return: | or [DELETE](#delete-a-variable) requests might return: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -416,7 +416,6 @@ GET /projects/:id/releases/:tag_name/downloads/:direct_asset_path | ||||||
| |----------------------------| -------------- | -------- | ----------------------------------------------------------------------------------- | | |----------------------------| -------------- | -------- | ----------------------------------------------------------------------------------- | | ||||||
| | `id`                       | integer/string | yes      | The ID or [URL-encoded path of the project](../rest/index.md#namespaced-path-encoding).  | | | `id`                       | integer/string | yes      | The ID or [URL-encoded path of the project](../rest/index.md#namespaced-path-encoding).  | | ||||||
| | `tag_name`                 | string         | yes      | The Git tag the release is associated with.                                         | | | `tag_name`                 | string         | yes      | The Git tag the release is associated with.                                         | | ||||||
| | `filepath`                 | string         | yes      | Deprecated: Use `direct_asset_path` instead.                                        | |  | ||||||
| | `direct_asset_path`        | string         | yes      | Path to the release asset file as specified when [creating](links.md#create-a-release-link) or [updating](links.md#update-a-release-link) its link. | | | `direct_asset_path`        | string         | yes      | Path to the release asset file as specified when [creating](links.md#create-a-release-link) or [updating](links.md#update-a-release-link) its link. | | ||||||
| 
 | 
 | ||||||
| Example request: | Example request: | ||||||
|  | @ -476,7 +475,6 @@ POST /projects/:id/releases | ||||||
| | `assets:links`     | array of hash   | no                          | An array of assets links.                                                                                                        | | | `assets:links`     | array of hash   | no                          | An array of assets links.                                                                                                        | | ||||||
| | `assets:links:name`| string          | required by: `assets:links` | The name of the link. Link names must be unique within the release.                                                              | | | `assets:links:name`| string          | required by: `assets:links` | The name of the link. Link names must be unique within the release.                                                              | | ||||||
| | `assets:links:url` | string          | required by: `assets:links` | The URL of the link. Link URLs must be unique within the release.                                                                | | | `assets:links:url` | string          | required by: `assets:links` | The URL of the link. Link URLs must be unique within the release.                                                                | | ||||||
| | `assets:links:filepath` | string     | no | Deprecated: Use `direct_asset_path` instead. | |  | ||||||
| | `assets:links:direct_asset_path` | string     | no | Optional path for a [direct asset link](../../user/project/releases/release_fields.md#permanent-links-to-release-assets). | | | `assets:links:direct_asset_path` | string     | no | Optional path for a [direct asset link](../../user/project/releases/release_fields.md#permanent-links-to-release-assets). | | ||||||
| | `assets:links:link_type` | string     | no | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`. | | | `assets:links:link_type` | string     | no | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`. | | ||||||
| | `released_at`      | datetime        | no                          | Date and time for the release. Defaults to the current time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). Only provide this field if creating an [upcoming](../../user/project/releases/index.md#upcoming-releases) or [historical](../../user/project/releases/index.md#historical-releases) release.  | | | `released_at`      | datetime        | no                          | Date and time for the release. Defaults to the current time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). Only provide this field if creating an [upcoming](../../user/project/releases/index.md#upcoming-releases) or [historical](../../user/project/releases/index.md#historical-releases) release.  | | ||||||
|  |  | ||||||
|  | @ -100,7 +100,6 @@ POST /projects/:id/releases/:tag_name/assets/links | ||||||
| | `tag_name`           | string         | yes      | The tag associated with the Release.                                                                                      | | | `tag_name`           | string         | yes      | The tag associated with the Release.                                                                                      | | ||||||
| | `name`               | string         | yes      | The name of the link. Link names must be unique in the release.                                                           | | | `name`               | string         | yes      | The name of the link. Link names must be unique in the release.                                                           | | ||||||
| | `url`                | string         | yes      | The URL of the link. Link URLs must be unique in the release.                                                             | | | `url`                | string         | yes      | The URL of the link. Link URLs must be unique in the release.                                                             | | ||||||
| | `filepath`           | string         | no       | Deprecated: Use `direct_asset_path` instead.                                                                              | |  | ||||||
| | `direct_asset_path`  | string         | no       | Optional path for a [direct asset link](../../user/project/releases/release_fields.md#permanent-links-to-release-assets). | | | `direct_asset_path`  | string         | no       | Optional path for a [direct asset link](../../user/project/releases/release_fields.md#permanent-links-to-release-assets). | | ||||||
| | `link_type`          | string         | no       | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`.                                        | | | `link_type`          | string         | no       | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`.                                        | | ||||||
| 
 | 
 | ||||||
|  | @ -142,7 +141,6 @@ PUT /projects/:id/releases/:tag_name/assets/links/:link_id | ||||||
| | `link_id`            | integer        | yes      | The ID of the link. | | | `link_id`            | integer        | yes      | The ID of the link. | | ||||||
| | `name`               | string         | no       | The name of the link. | | | `name`               | string         | no       | The name of the link. | | ||||||
| | `url`                | string         | no       | The URL of the link. | | | `url`                | string         | no       | The URL of the link. | | ||||||
| | `filepath`           | string         | no       | Deprecated: Use `direct_asset_path` instead. | |  | ||||||
| | `direct_asset_path`  | string         | no       | Optional path for a [direct asset link](../../user/project/releases/release_fields.md#permanent-links-to-release-assets). | | | `direct_asset_path`  | string         | no       | Optional path for a [direct asset link](../../user/project/releases/release_fields.md#permanent-links-to-release-assets). | | ||||||
| | `link_type`          | string         | no       | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`. | | | `link_type`          | string         | no       | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`. | | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -10,7 +10,6 @@ DETAILS: | ||||||
| **Tier:** Free, Premium, Ultimate | **Tier:** Free, Premium, Ultimate | ||||||
| **Offering:** GitLab.com, Self-managed, GitLab Dedicated | **Offering:** GitLab.com, Self-managed, GitLab Dedicated | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78227) in GitLab 14.8 [with a flag](../administration/feature_flags.md) named `ci_secure_files`. Disabled by default. |  | ||||||
| > - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/350748) in GitLab 15.7. Feature flag `ci_secure_files` removed. | > - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/350748) in GitLab 15.7. Feature flag `ci_secure_files` removed. | ||||||
| 
 | 
 | ||||||
| This feature is part of [Mobile DevOps](../ci/mobile_devops.md) developed by [GitLab Incubation Engineering](https://handbook.gitlab.com/handbook/engineering/development/incubation/). | This feature is part of [Mobile DevOps](../ci/mobile_devops.md) developed by [GitLab Incubation Engineering](https://handbook.gitlab.com/handbook/engineering/development/incubation/). | ||||||
|  |  | ||||||
|  | @ -10,8 +10,6 @@ DETAILS: | ||||||
| **Tier:** Free, Premium, Ultimate | **Tier:** Free, Premium, Ultimate | ||||||
| **Offering:** GitLab.com, Self-managed, GitLab Dedicated | **Offering:** GitLab.com, Self-managed, GitLab Dedicated | ||||||
| 
 | 
 | ||||||
| > - `CI_JOB_JWT` variable for reading secrets from Vault [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207125) in GitLab 12.10. |  | ||||||
| > - `CI_JOB_JWT_V2` variable to support additional OIDC providers [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346737) in GitLab 14.7. |  | ||||||
| > - [ID tokens](../yaml/index.md#id_tokens) to support any OIDC provider, including HashiCorp Vault, [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/356986) in GitLab 15.7. | > - [ID tokens](../yaml/index.md#id_tokens) to support any OIDC provider, including HashiCorp Vault, [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/356986) in GitLab 15.7. | ||||||
| 
 | 
 | ||||||
| WARNING: | WARNING: | ||||||
|  | @ -24,8 +22,7 @@ Historically, teams stored secrets in projects or applied permissions on the Git | ||||||
| instance to build and deploy. OIDC capable [ID tokens](../yaml/index.md#id_tokens) are configurable | instance to build and deploy. OIDC capable [ID tokens](../yaml/index.md#id_tokens) are configurable | ||||||
| in the CI/CD job allowing you to follow a scalable and least-privilege security approach. | in the CI/CD job allowing you to follow a scalable and least-privilege security approach. | ||||||
| 
 | 
 | ||||||
| In GitLab 15.6 and earlier, you must use `CI_JOB_JWT_V2` instead of an ID token, | In GitLab 15.6 and earlier, you must use `CI_JOB_JWT_V2` instead of an ID token, but it is not customizable. | ||||||
| but it is not customizable. In GitLab 14.6 an earlier you must use the `CI_JOB_JWT`, which has limited support. |  | ||||||
| 
 | 
 | ||||||
| ## Prerequisites | ## Prerequisites | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -58,9 +58,9 @@ The following fields are included in the JWT: | ||||||
| | `ref_type`              | Always                       | Git ref type, either `branch` or `tag`                                                                                                                                                               | | | `ref_type`              | Always                       | Git ref type, either `branch` or `tag`                                                                                                                                                               | | ||||||
| | `ref_path`              | Always                       | Fully qualified ref for the job. For example, `refs/heads/main`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119075) in GitLab 16.0.                                          | | | `ref_path`              | Always                       | Fully qualified ref for the job. For example, `refs/heads/main`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119075) in GitLab 16.0.                                          | | ||||||
| | `ref_protected`         | Always                       | `true` if this Git ref is protected, `false` otherwise                                                                                                                                               | | | `ref_protected`         | Always                       | `true` if this Git ref is protected, `false` otherwise                                                                                                                                               | | ||||||
| | `environment`           | Job specifies an environment | Environment this job specifies ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294440) in GitLab 13.9)                                                                                   | | | `environment`           | Job specifies an environment | Environment this job specifies                                                                                   | | ||||||
| | `groups_direct`         | User is a direct member of 0 to 200 groups | The paths of the user's direct membership groups. Omitted if the user is a direct member of more than 200 groups. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/435848) in GitLab 16.11). | | | `groups_direct`         | User is a direct member of 0 to 200 groups | The paths of the user's direct membership groups. Omitted if the user is a direct member of more than 200 groups. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/435848) in GitLab 16.11). | | ||||||
| | `environment_protected` | Job specifies an environment | `true` if specified environment is protected, `false` otherwise ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294440) in GitLab 13.9)                                                  | | | `environment_protected` | Job specifies an environment | `true` if specified environment is protected, `false` otherwise                                                  | | ||||||
| | `deployment_tier`       | Job specifies an environment | [Deployment tier](../../environments/index.md#deployment-tier-of-environments) of environment this job specifies ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/363590) in GitLab 15.2) | | | `deployment_tier`       | Job specifies an environment | [Deployment tier](../../environments/index.md#deployment-tier-of-environments) of environment this job specifies ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/363590) in GitLab 15.2) | | ||||||
| | `environment_action`    | Job specifies an environment | [Environment action (`environment:action`)](../../environments/index.md) specified in the job. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/) in GitLab 16.5)                                   | | | `environment_action`    | Job specifies an environment | [Environment action (`environment:action`)](../../environments/index.md) specified in the job. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/) in GitLab 16.5)                                   | | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -187,10 +187,6 @@ proposes to change this behavior. | ||||||
| 
 | 
 | ||||||
| ## Limit your project's job token access (deprecated) | ## Limit your project's job token access (deprecated) | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/328553) in GitLab 14.1. [Deployed behind the `:ci_scoped_job_token` feature flag](../../user/feature_flags.md), disabled by default. |  | ||||||
| > - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/332272) in GitLab 14.4. |  | ||||||
| > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/332272) in GitLab 14.6. |  | ||||||
| 
 |  | ||||||
| NOTE: | NOTE: | ||||||
| The [**Limit access _from_ this project**](#configure-the-job-token-scope-deprecated) | The [**Limit access _from_ this project**](#configure-the-job-token-scope-deprecated) | ||||||
| setting is disabled by default for all new projects and is [scheduled for removal](https://gitlab.com/gitlab-org/gitlab/-/issues/383084) | setting is disabled by default for all new projects and is [scheduled for removal](https://gitlab.com/gitlab-org/gitlab/-/issues/383084) | ||||||
|  |  | ||||||
|  | @ -194,7 +194,6 @@ job: | ||||||
| 
 | 
 | ||||||
| ## View all job artifacts in a project | ## View all job artifacts in a project | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31271) in GitLab 12.4 [with a flag](../../administration/feature_flags.md) named `artifacts_management_page`. Disabled by default. |  | ||||||
| > - [Improved look](https://gitlab.com/gitlab-org/gitlab/-/issues/33418) in GitLab 15.6. | > - [Improved look](https://gitlab.com/gitlab-org/gitlab/-/issues/33418) in GitLab 15.6. | ||||||
| > - [Improved performance](https://gitlab.com/gitlab-org/gitlab/-/issues/387765) in GitLab 15.9. | > - [Improved performance](https://gitlab.com/gitlab-org/gitlab/-/issues/387765) in GitLab 15.9. | ||||||
| > - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/407475) in GitLab 16.0. Feature flag `artifacts_management_page` removed. | > - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/407475) in GitLab 16.0. Feature flag `artifacts_management_page` removed. | ||||||
|  | @ -362,9 +361,6 @@ With this configuration, GitLab adds **artifact 1** as a link to `file.txt` to t | ||||||
| 
 | 
 | ||||||
| ## Keep artifacts from most recent successful jobs | ## Keep artifacts from most recent successful jobs | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16267) in GitLab 13.0. |  | ||||||
| > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/229936) in GitLab 13.4. |  | ||||||
| > - [Made optional with a CI/CD setting](https://gitlab.com/gitlab-org/gitlab/-/issues/241026) in GitLab 13.8. |  | ||||||
| > - Artifacts for [blocked](https://gitlab.com/gitlab-org/gitlab/-/issues/387087) or [failed](https://gitlab.com/gitlab-org/gitlab/-/issues/266958) pipelines no longer kept indefinitely in GitLab 16.7. | > - Artifacts for [blocked](https://gitlab.com/gitlab-org/gitlab/-/issues/387087) or [failed](https://gitlab.com/gitlab-org/gitlab/-/issues/266958) pipelines no longer kept indefinitely in GitLab 16.7. | ||||||
| 
 | 
 | ||||||
| By default artifacts are always kept for successful pipelines for the most recent commit on each ref. | By default artifacts are always kept for successful pipelines for the most recent commit on each ref. | ||||||
|  |  | ||||||
|  | @ -73,8 +73,8 @@ The token also includes custom claims provided by GitLab: | ||||||
| | `ref_path`              | Always                       | Fully qualified ref for the job. For example, `refs/heads/main`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119075) in GitLab 16.0.                                                                                                                                                      | | | `ref_path`              | Always                       | Fully qualified ref for the job. For example, `refs/heads/main`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119075) in GitLab 16.0.                                                                                                                                                      | | ||||||
| | `ref_protected`         | Always                       | `true` if the Git ref is protected, `false` otherwise.                                                                                                                                                                                                                                                           | | | `ref_protected`         | Always                       | `true` if the Git ref is protected, `false` otherwise.                                                                                                                                                                                                                                                           | | ||||||
| | `groups_direct`         | User is a direct member of 0 to 200 groups | The paths of the user's direct membership groups. Omitted if the user is a direct member of more than 200 groups. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/435848) in GitLab 16.11). | | | `groups_direct`         | User is a direct member of 0 to 200 groups | The paths of the user's direct membership groups. Omitted if the user is a direct member of more than 200 groups. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/435848) in GitLab 16.11). | | ||||||
| | `environment`           | Job specifies an environment | Environment this job deploys to ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294440) in GitLab 13.9).                                                                                                                                                                                             | | | `environment`           | Job specifies an environment | Environment this job deploys to.                                                                                                                                                                                             | | ||||||
| | `environment_protected` | Job specifies an environment | `true` if deployed environment is protected, `false` otherwise ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294440) in GitLab 13.9).                                                                                                                                                              | | | `environment_protected` | Job specifies an environment | `true` if deployed environment is protected, `false` otherwise.                                                                                                                                                              | | ||||||
| | `deployment_tier`       | Job specifies an environment | [Deployment tier](../environments/index.md#deployment-tier-of-environments) of the environment the job specifies. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/363590) in GitLab 15.2.                                                                                                             | | | `deployment_tier`       | Job specifies an environment | [Deployment tier](../environments/index.md#deployment-tier-of-environments) of the environment the job specifies. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/363590) in GitLab 15.2.                                                                                                             | | ||||||
| | `environment_action`    | Job specifies an environment | [Environment action (`environment:action`)](../environments/index.md) specified in the job. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/) in GitLab 16.5)                                                                                                                                               | | | `environment_action`    | Job specifies an environment | [Environment action (`environment:action`)](../environments/index.md) specified in the job. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/) in GitLab 16.5)                                                                                                                                               | | ||||||
| | `runner_id`             | Always                       | ID of the runner executing the job. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/404722) in GitLab 16.0.                                                                                                                                                                                           | | | `runner_id`             | Always                       | ID of the runner executing the job. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/404722) in GitLab 16.0.                                                                                                                                                                                           | | ||||||
|  |  | ||||||
|  | @ -10,10 +10,6 @@ DETAILS: | ||||||
| **Tier:** Free, Premium, Ultimate | **Tier:** Free, Premium, Ultimate | ||||||
| **Offering:** GitLab.com, Self-managed, GitLab Dedicated | **Offering:** GitLab.com, Self-managed, GitLab Dedicated | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218746) in GitLab 13.4 and GitLab Runner 13.4. |  | ||||||
| > - `file` setting [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250695) in GitLab 14.1 and GitLab Runner 14.1. |  | ||||||
| > - `VAULT_NAMESPACE` setting [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255619) in GitLab 14.9 and GitLab Runner 14.9. |  | ||||||
| 
 |  | ||||||
| Secrets represent sensitive information your CI job needs to complete work. This | Secrets represent sensitive information your CI job needs to complete work. This | ||||||
| sensitive information can be items like API tokens, database credentials, or private keys. | sensitive information can be items like API tokens, database credentials, or private keys. | ||||||
| Secrets are sourced from your secrets provider. | Secrets are sourced from your secrets provider. | ||||||
|  | @ -125,8 +121,6 @@ DETAILS: | ||||||
| **Tier:** Premium, Ultimate | **Tier:** Premium, Ultimate | ||||||
| **Offering:** GitLab.com, Self-managed, GitLab Dedicated | **Offering:** GitLab.com, Self-managed, GitLab Dedicated | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/28321) in GitLab 13.4 and GitLab Runner 13.4. |  | ||||||
| 
 |  | ||||||
| After [configuring your Vault server](#configure-your-vault-server), you can use | After [configuring your Vault server](#configure-your-vault-server), you can use | ||||||
| the secrets stored in Vault by defining them with the [`vault` keyword](../yaml/index.md#secretsvault): | the secrets stored in Vault by defining them with the [`vault` keyword](../yaml/index.md#secretsvault): | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -10,7 +10,6 @@ DETAILS: | ||||||
| **Tier:** Free, Premium, Ultimate | **Tier:** Free, Premium, Ultimate | ||||||
| **Offering:** GitLab.com, Self-managed, GitLab Dedicated | **Offering:** GitLab.com, Self-managed, GitLab Dedicated | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78227) in GitLab 14.8 [with a flag](../../administration/feature_flags.md) named `ci_secure_files`. Disabled by default. |  | ||||||
| > - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/350748) in GitLab 15.7. Feature flag `ci_secure_files` removed. | > - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/350748) in GitLab 15.7. Feature flag `ci_secure_files` removed. | ||||||
| 
 | 
 | ||||||
| This feature is part of [Mobile DevOps](../mobile_devops.md) developed by [GitLab Incubation Engineering](https://handbook.gitlab.com/handbook/engineering/development/incubation/). | This feature is part of [Mobile DevOps](../mobile_devops.md) developed by [GitLab Incubation Engineering](https://handbook.gitlab.com/handbook/engineering/development/incubation/). | ||||||
|  |  | ||||||
|  | @ -201,9 +201,6 @@ DETAILS: | ||||||
| **Tier:** Free, Premium, Ultimate | **Tier:** Free, Premium, Ultimate | ||||||
| **Offering:** Self-managed, GitLab Dedicated | **Offering:** Self-managed, GitLab Dedicated | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14108) in GitLab 13.0. |  | ||||||
| > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/299879) in GitLab 13.11. |  | ||||||
| 
 |  | ||||||
| You can make a CI/CD variable available to all projects and groups in a GitLab instance. | You can make a CI/CD variable available to all projects and groups in a GitLab instance. | ||||||
| 
 | 
 | ||||||
| Prerequisites: | Prerequisites: | ||||||
|  | @ -216,9 +213,8 @@ To add an instance variable: | ||||||
| 1. Select **Settings > CI/CD** and expand the **Variables** section. | 1. Select **Settings > CI/CD** and expand the **Variables** section. | ||||||
| 1. Select **Add variable** and fill in the details: | 1. Select **Add variable** and fill in the details: | ||||||
|    - **Key**: Must be one line, with no spaces, using only letters, numbers, or `_`. |    - **Key**: Must be one line, with no spaces, using only letters, numbers, or `_`. | ||||||
|    - **Value**: In [GitLab 13.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/220028), |    - **Value**: The value is limited to 10,000 characters, but also bounded by any limits in the | ||||||
|      the value is limited to 10,000 characters, but also bounded by any limits in the |      runner's operating system. | ||||||
|      runner's operating system. In GitLab 13.0 to 13.2, the value is limited to 700 characters. |  | ||||||
|    - **Type**: `Variable` (default) or [`File`](#use-file-type-cicd-variables). |    - **Type**: `Variable` (default) or [`File`](#use-file-type-cicd-variables). | ||||||
|    - **Protect variable** Optional. If selected, the variable is only available |    - **Protect variable** Optional. If selected, the variable is only available | ||||||
|      in pipelines that run on protected branches or tags. |      in pipelines that run on protected branches or tags. | ||||||
|  | @ -267,8 +263,6 @@ valid [secrets file](../../administration/backup_restore/troubleshooting_backup_ | ||||||
| 
 | 
 | ||||||
| ### Mask a CI/CD variable | ### Mask a CI/CD variable | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330650) in GitLab 13.12, the `~` character can be used in masked variables. |  | ||||||
| 
 |  | ||||||
| WARNING: | WARNING: | ||||||
| Masking a CI/CD variable is not a guaranteed way to prevent malicious users from | Masking a CI/CD variable is not a guaranteed way to prevent malicious users from | ||||||
| accessing variable values. The masking feature is "best-effort" and there to | accessing variable values. The masking feature is "best-effort" and there to | ||||||
|  | @ -473,9 +467,6 @@ variables: | ||||||
| 
 | 
 | ||||||
| ### Pass an environment variable to another job | ### Pass an environment variable to another job | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22638) in GitLab 13.0. |  | ||||||
| > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/217834) in GitLab 13.1. |  | ||||||
| 
 |  | ||||||
| You can create a new environment variables in a job, and pass it to another job | You can create a new environment variables in a job, and pass it to another job | ||||||
| in a later stage. These variables cannot be used as CI/CD variables to configure a pipeline, | in a later stage. These variables cannot be used as CI/CD variables to configure a pipeline, | ||||||
| but they can be used in job scripts. | but they can be used in job scripts. | ||||||
|  | @ -712,8 +703,6 @@ can cause the pipeline to behave unexpectedly. | ||||||
| 
 | 
 | ||||||
| ### Restrict who can override variables | ### Restrict who can override variables | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/295234) in GitLab 13.8. |  | ||||||
| 
 |  | ||||||
| You can limit the ability to override variables to only users with the Maintainer role. | You can limit the ability to override variables to only users with the Maintainer role. | ||||||
| When other users try to run a pipeline with overridden variables, they receive the | When other users try to run a pipeline with overridden variables, they receive the | ||||||
| `Insufficient permissions to set pipeline variables` error message. | `Insufficient permissions to set pipeline variables` error message. | ||||||
|  | @ -951,9 +940,6 @@ if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then | ||||||
| 
 | 
 | ||||||
| #### Restrict access to debug logging | #### Restrict access to debug logging | ||||||
| 
 | 
 | ||||||
| > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213159) in GitLab 13.7. |  | ||||||
| > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/292661) in GitLab 13.8. |  | ||||||
| 
 |  | ||||||
| You can restrict access to debug logging. When restricted, only users with | You can restrict access to debug logging. When restricted, only users with | ||||||
| at least the Developer role | at least the Developer role | ||||||
| can view job logs when debug logging is enabled with a variable in: | can view job logs when debug logging is enabled with a variable in: | ||||||
|  |  | ||||||
|  | @ -125,7 +125,7 @@ as it can cause the pipeline to behave unexpectedly. | ||||||
| | `CI_RUNNER_EXECUTABLE_ARCH`       | Jobs only   | all    | 10.6   | The OS/architecture of the GitLab Runner executable. Might not be the same as the environment of the executor. | | | `CI_RUNNER_EXECUTABLE_ARCH`       | Jobs only   | all    | 10.6   | The OS/architecture of the GitLab Runner executable. Might not be the same as the environment of the executor. | | ||||||
| | `CI_RUNNER_ID`                    | Jobs only   | 8.10   | 0.5    | The unique ID of the runner being used. | | | `CI_RUNNER_ID`                    | Jobs only   | 8.10   | 0.5    | The unique ID of the runner being used. | | ||||||
| | `CI_RUNNER_REVISION`              | Jobs only   | all    | 10.6   | The revision of the runner running the job. | | | `CI_RUNNER_REVISION`              | Jobs only   | all    | 10.6   | The revision of the runner running the job. | | ||||||
| | `CI_RUNNER_SHORT_TOKEN`           | Jobs only   | all    | 12.3   | The runner's unique ID, used to authenticate new job requests. In [GitLab 14.9](https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/2251) and later, the token contains a prefix, and the first 17 characters are used. Prior to 14.9, the first eight characters are used. | | | `CI_RUNNER_SHORT_TOKEN`           | Jobs only   | all    | 12.3   | The runner's unique ID, used to authenticate new job requests. The token contains a prefix, and the first 17 characters are used. | | ||||||
| | `CI_RUNNER_TAGS`                  | Jobs only   | 8.10   | 0.5    | A comma-separated list of the runner tags. | | | `CI_RUNNER_TAGS`                  | Jobs only   | 8.10   | 0.5    | A comma-separated list of the runner tags. | | ||||||
| | `CI_RUNNER_VERSION`               | Jobs only   | all    | 10.6   | The version of the GitLab Runner running the job. | | | `CI_RUNNER_VERSION`               | Jobs only   | all    | 10.6   | The version of the GitLab Runner running the job. | | ||||||
| | `CI_SERVER_FQDN`                  | Pipeline    | 16.10  | all    | The fully qualified domain name (FQDN) of the instance. For example `gitlab.example.com:8080`. | | | `CI_SERVER_FQDN`                  | Pipeline    | 16.10  | all    | The fully qualified domain name (FQDN) of the instance. For example `gitlab.example.com:8080`. | | ||||||
|  |  | ||||||
|  | @ -50,7 +50,7 @@ There are two places defined variables can be used. On the: | ||||||
| | [`script`](../yaml/index.md#script)                                   | yes              | Script execution shell | The variable expansion is made by the [execution shell environment](#execution-shell-environment). | | | [`script`](../yaml/index.md#script)                                   | yes              | Script execution shell | The variable expansion is made by the [execution shell environment](#execution-shell-environment). | | ||||||
| | [`services:name`](../yaml/index.md#services)                          | yes              | Runner                 | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism). | | | [`services:name`](../yaml/index.md#services)                          | yes              | Runner                 | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism). | | ||||||
| | [`services`](../yaml/index.md#services)                               | yes              | Runner                 | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism). | | | [`services`](../yaml/index.md#services)                               | yes              | Runner                 | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism). | | ||||||
| | [`tags`](../yaml/index.md#tags)                                       | yes              | GitLab                 | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35742) in GitLab 14.1. | | | [`tags`](../yaml/index.md#tags)                                       | yes              | GitLab                 | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab.  | | ||||||
| | [`trigger` and `trigger:project`](../yaml/index.md#trigger)           | yes              | GitLab                 | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab. Variable expansion for `trigger:project` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/367660) in GitLab 15.3. | | | [`trigger` and `trigger:project`](../yaml/index.md#trigger)           | yes              | GitLab                 | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab. Variable expansion for `trigger:project` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/367660) in GitLab 15.3. | | ||||||
| | [`variables`](../yaml/index.md#variables)                             | yes              | GitLab/Runner          | The variable expansion is first made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab, and then any unrecognized or unavailable variables are expanded by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism). | | | [`variables`](../yaml/index.md#variables)                             | yes              | GitLab/Runner          | The variable expansion is first made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab, and then any unrecognized or unavailable variables are expanded by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism). | | ||||||
| | [`workflow:name`](../yaml/index.md#workflowname)                      | yes              | GitLab                 | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab.<br/><br/>Supported are all variables available in `workflow`:<br/>- Project/Group variables.<br/>- Global `variables` and `workflow:rules:variables` (when matching the rule).<br/>- Variables inherited from parent pipelines.<br/>- Variables from triggers.<br/>- Variables from pipeline schedules.<br/><br/>Not supported are variables defined in the GitLab Runner `config.toml`, variables defined in jobs, or [Persisted variables](#persisted-variables). | | | [`workflow:name`](../yaml/index.md#workflowname)                      | yes              | GitLab                 | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab.<br/><br/>Supported are all variables available in `workflow`:<br/>- Project/Group variables.<br/>- Global `variables` and `workflow:rules:variables` (when matching the rule).<br/>- Variables inherited from parent pipelines.<br/>- Variables from triggers.<br/>- Variables from pipeline schedules.<br/><br/>Not supported are variables defined in the GitLab Runner `config.toml`, variables defined in jobs, or [Persisted variables](#persisted-variables). | | ||||||
|  | @ -81,11 +81,6 @@ because the expansion is done in GitLab before any runner gets the job. | ||||||
| 
 | 
 | ||||||
| #### Nested variable expansion | #### Nested variable expansion | ||||||
| 
 | 
 | ||||||
| - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48627) in GitLab 13.10. [Deployed behind the `variable_inside_variable` feature flag](../../user/feature_flags.md), disabled by default. |  | ||||||
| - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/297382) in GitLab 14.3. |  | ||||||
| - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/297382) in GitLab 14.4. |  | ||||||
| - Feature flag `variable_inside_variable` removed in GitLab 14.5. |  | ||||||
| 
 |  | ||||||
| GitLab expands job variable values recursively before sending them to the runner. For example, in the following scenario: | GitLab expands job variable values recursively before sending them to the runner. For example, in the following scenario: | ||||||
| 
 | 
 | ||||||
| ```yaml | ```yaml | ||||||
|  |  | ||||||
|  | @ -7,17 +7,18 @@ source: /doc/user/search/exact_code_search.md | ||||||
| 
 | 
 | ||||||
| # Search tips | # Search tips | ||||||
| 
 | 
 | ||||||
| | Query                | Description                                                                           | | | Query                | Regular expression mode                               | Exact match mode               | | ||||||
| | -------------------- |-------------------------------------------------------------------------------------- | | | -------------------- | ----------------------------------------------------- | ------------------------------ | | ||||||
| | `foo`                | Returns files that contain `foo`                                                      | | | `"foo"`              | `foo`                                                 | `"foo"`                        | | ||||||
| | `"class foo"`        | Returns files that contain the exact string `class foo`                               | | | `foo file:^doc/`     | `foo` in directories that start with `/doc`           | `foo` in directories that start with `/doc` | | ||||||
| | `class foo`          | Returns files that contain both `class` and `foo`                                     | | | `"class foo"`        | `class foo`                                           | `"class foo"`                  | | ||||||
| | `foo or bar`         | Returns files that contain either `foo` or `bar`                                      | | | `class foo`          | `class` and `foo`                                     | `class foo`                    | | ||||||
| | `class Foo`          | Returns files that contain `class` (case insensitive) and `Foo` (case sensitive)      | | | `foo or bar`         | `foo` or `bar`                                        | `foo or bar`                   | | ||||||
| | `class Foo case:yes` | Returns files that contain `class` and `Foo` (both case sensitive)                    | | | `class Foo`          | `class` (case insensitive) and `Foo` (case sensitive) | `class Foo` (case insensitive) | | ||||||
| | `foo -bar`           | Returns files that contain `foo` but not `bar`                                        | | | `class Foo case:yes` | `class` and `Foo` (both case sensitive)               | `class Foo` (case sensitive)   | | ||||||
| | `foo file:js`        | Searches for `foo` in files with names that contain `js`                              | | | `foo -bar`           | `foo` but not `bar`                                   | `foo -bar`                     | | ||||||
| | `foo -file:test`     | Searches for `foo` in files with names that do not contain `test`                     | | | `foo file:js`        | `foo` in files with names that contain `js`           | `foo` in files with names that contain `js` | | ||||||
| | `foo lang:ruby`      | Searches for `foo` in Ruby source code                                                | | | `foo -file:test`     | `foo` in files with names that do not contain `test`  | `foo` in files with names that do not contain `test` | | ||||||
| | `foo f:\.js$`        | Searches for `foo` in files with names that end with `.js`                            | | | `foo lang:ruby`      | `foo` in Ruby source code                             | `foo` in Ruby source code      | | ||||||
| | `foo.*bar`           | Searches for strings that match the regular expression `foo.*bar`                     | | | `foo file:\.js$`     | `foo` in files with names that end with `.js`         | `foo` in files with names that end with `.js` | | ||||||
|  | | `foo.*bar`           | `foo.*bar` (regular expression)                       | None                           | | ||||||
|  |  | ||||||
|  | @ -325,6 +325,24 @@ This change is a breaking change. You should [create a runner in the UI](https:/ | ||||||
| 
 | 
 | ||||||
| <div class="deprecation breaking-change" data-milestone="18.0"> | <div class="deprecation breaking-change" data-milestone="18.0"> | ||||||
| 
 | 
 | ||||||
|  | ### Runner `active` GraphQL fields replaced by `paused` | ||||||
|  | 
 | ||||||
|  | <div class="deprecation-notes"> | ||||||
|  | - Announced in GitLab <span class="milestone">14.8</span> | ||||||
|  | - Removal in GitLab <span class="milestone">18.0</span> ([breaking change](https://docs.gitlab.com/ee/update/terminology.html#breaking-change)) | ||||||
|  | - To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/351109). | ||||||
|  | </div> | ||||||
|  | 
 | ||||||
|  | Occurrences of the `active` identifier in the GitLab GraphQL API endpoints will be renamed to `paused` in GitLab 18.0: | ||||||
|  | 
 | ||||||
|  | - The `CiRunner` property. | ||||||
|  | - The `RunnerUpdateInput` input type for the `runnerUpdate` mutation. | ||||||
|  | - The `runners`, `Group.runners`, and `Project.runners` queries. | ||||||
|  | 
 | ||||||
|  | </div> | ||||||
|  | 
 | ||||||
|  | <div class="deprecation breaking-change" data-milestone="18.0"> | ||||||
|  | 
 | ||||||
| ### Running a single database is deprecated | ### Running a single database is deprecated | ||||||
| 
 | 
 | ||||||
| <div class="deprecation-notes"> | <div class="deprecation-notes"> | ||||||
|  |  | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue