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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.checksum6
-rw-r--r--Gemfile.lock8
-rw-r--r--app/controllers/admin/topics_controller.rb2
-rw-r--r--app/controllers/registrations/welcome_controller.rb41
-rw-r--r--config/initializers_before_autoloader/003_gc_compact.rb21
-rw-r--r--config/puma.example.development.rb7
-rw-r--r--config/puma.rb.example7
-rw-r--r--db/15_11_migration_fixes.txt299
-rw-r--r--db/post_migrate/20230522220709_ensure_incident_work_item_type_backfill_is_finished.rb37
-rw-r--r--db/post_migrate/20230522225610_remove_tmp_index_issues_on_issue_type_and_id_only_incidents.rb16
-rw-r--r--db/schema_migrations/202305222207091
-rw-r--r--db/schema_migrations/202305222256101
-rw-r--r--db/structure.sql2
-rw-r--r--doc/api/environments.md84
-rw-r--r--doc/tutorials/hugo/index.md169
-rw-r--r--doc/user/clusters/agent/gitops/flux.md61
-rw-r--r--lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml13
-rw-r--r--lib/tasks/gitlab/db/migration_fix_15_11.rake30
-rw-r--r--locale/gitlab.pot8
-rw-r--r--spec/controllers/admin/topics_controller_spec.rb6
-rw-r--r--spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb2
-rw-r--r--spec/migrations/20230522220709_ensure_incident_work_item_type_backfill_is_finished_spec.rb105
-rw-r--r--spec/support/shared_examples/features/work_items_shared_examples.rb2
-rw-r--r--spec/tasks/gitlab/db/migration_fix_15_11_rake_spec.rb66
25 files changed, 838 insertions, 160 deletions
diff --git a/Gemfile b/Gemfile
index 256121cda0a..bbe364f75bf 100644
--- a/Gemfile
+++ b/Gemfile
@@ -172,7 +172,7 @@ gem 'seed-fu', '~> 2.3.7'
gem 'elasticsearch-model', '~> 7.2'
gem 'elasticsearch-rails', '~> 7.2', require: 'elasticsearch/rails/instrumentation'
gem 'elasticsearch-api', '7.13.3'
-gem 'aws-sdk-core', '~> 3.173.0'
+gem 'aws-sdk-core', '~> 3.173.1'
gem 'aws-sdk-cloudformation', '~> 1'
gem 'aws-sdk-s3', '~> 1.122.0'
gem 'faraday_middleware-aws-sigv4', '~>0.3.0'
@@ -210,7 +210,7 @@ gem 'rack', '~> 2.2.7'
gem 'rack-timeout', '~> 0.6.3', require: 'rack/timeout/base'
group :puma do
- gem 'puma', '~> 5.6.5', require: false
+ gem 'puma', '~> 6.2', require: false
gem 'sd_notify', '~> 0.1.0', require: false
end
diff --git a/Gemfile.checksum b/Gemfile.checksum
index 71ed6d7124d..4fdcc2cff6f 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -37,7 +37,7 @@
{"name":"aws-eventstream","version":"1.2.0","platform":"ruby","checksum":"ffa53482c92880b001ff2fb06919b9bb82fd847cbb0fa244985d2ebb6dd0d1df"},
{"name":"aws-partitions","version":"1.761.0","platform":"ruby","checksum":"291e444e1edfc92c5521a6dbdd1236ccc3f122b3520163b2be6ec5b6ef350ef2"},
{"name":"aws-sdk-cloudformation","version":"1.41.0","platform":"ruby","checksum":"31e47539719734413671edf9b1a31f8673fbf9688549f50c41affabbcb1c6b26"},
-{"name":"aws-sdk-core","version":"3.173.0","platform":"ruby","checksum":"e704c18580e64dcb1db3bb9757e2d609fa044f723077a4665783a749fe7ab281"},
+{"name":"aws-sdk-core","version":"3.173.1","platform":"ruby","checksum":"692acfcf95bce8cbbde97a9db077d219cf72ccd1b76afa354bcaf21eebb1d9f6"},
{"name":"aws-sdk-kms","version":"1.64.0","platform":"ruby","checksum":"40de596c95047bfc6e1aacea24f3df6241aa716b6f7ce08ac4c5f7e3120395ad"},
{"name":"aws-sdk-s3","version":"1.122.0","platform":"ruby","checksum":"3d1fb6d0a6c55cf568ff66d657b4a6e7eaa718675f1f3156d7b44e3791f39905"},
{"name":"aws-sigv4","version":"1.5.1","platform":"ruby","checksum":"d68c87fff4ee843b4b92b23c7f31f957f254ec6eb064181f7119124aab8b8bb4"},
@@ -463,8 +463,8 @@
{"name":"pry-rails","version":"0.3.9","platform":"ruby","checksum":"468662575abb6b67f4a9831219f99290d5eae7bf186e64dd810d0a3e4a8cc4b1"},
{"name":"pry-shell","version":"0.6.1","platform":"ruby","checksum":"a99a6b3dffe4df274ea1751866816906861a23851f13346e10a8e8f61b53360c"},
{"name":"public_suffix","version":"5.0.0","platform":"ruby","checksum":"26ee4fbce33ada25eb117ac71f2c24bf4d8b3414ab6b34f05b4708a3e90f1c6b"},
-{"name":"puma","version":"5.6.5","platform":"java","checksum":"29d78fc2bc070b9db285a3334a890c3e0ece9bb369388065f0f340ccb1e57faf"},
-{"name":"puma","version":"5.6.5","platform":"ruby","checksum":"661029d15a115e9f6c0641a69c830ffd9f1b9ac63fcd0791d94ccd900e03f863"},
+{"name":"puma","version":"6.2.2","platform":"java","checksum":"979623e8072876a1d44092f91dfaddf337be103323b321fe779adc92def7106a"},
+{"name":"puma","version":"6.2.2","platform":"ruby","checksum":"4503e79d1d9f13985a30928c72cd1518cebf1da5fcf720efd1aa21ef6795c479"},
{"name":"pyu-ruby-sasl","version":"0.0.3.3","platform":"ruby","checksum":"5683a6bc5738db5a1bf5ceddeaf545405fb241b4184dd4f2587e679a7e9497e5"},
{"name":"raabro","version":"1.4.0","platform":"ruby","checksum":"d4fa9ff5172391edb92b242eed8be802d1934b1464061ae5e70d80962c5da882"},
{"name":"racc","version":"1.6.2","platform":"java","checksum":"0880781e7dfde09e665d0b6160b583e01ed52fcc2955d7891447d33c2d1d2cf1"},
diff --git a/Gemfile.lock b/Gemfile.lock
index 9fa33aa29e8..a1043e141cf 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -203,7 +203,7 @@ GEM
aws-sdk-cloudformation (1.41.0)
aws-sdk-core (~> 3, >= 3.99.0)
aws-sigv4 (~> 1.1)
- aws-sdk-core (3.173.0)
+ aws-sdk-core (3.173.1)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5)
@@ -1160,7 +1160,7 @@ GEM
tty-markdown
tty-prompt
public_suffix (5.0.0)
- puma (5.6.5)
+ puma (6.2.2)
nio4r (~> 2.0)
pyu-ruby-sasl (0.0.3.3)
raabro (1.4.0)
@@ -1669,7 +1669,7 @@ DEPENDENCIES
autoprefixer-rails (= 10.2.5.1)
awesome_print
aws-sdk-cloudformation (~> 1)
- aws-sdk-core (~> 3.173.0)
+ aws-sdk-core (~> 3.173.1)
aws-sdk-s3 (~> 1.122.0)
axe-core-rspec
babosa (~> 2.0)
@@ -1863,7 +1863,7 @@ DEPENDENCIES
pry-byebug
pry-rails (~> 0.3.9)
pry-shell (~> 0.6.1)
- puma (~> 5.6.5)
+ puma (~> 6.2)
rack (~> 2.2.7)
rack-attack (~> 6.6.1)
rack-cors (~> 1.1.1)
diff --git a/app/controllers/admin/topics_controller.rb b/app/controllers/admin/topics_controller.rb
index 1f0664362a0..c4de600dd1d 100644
--- a/app/controllers/admin/topics_controller.rb
+++ b/app/controllers/admin/topics_controller.rb
@@ -27,7 +27,7 @@ class Admin::TopicsController < Admin::ApplicationController
@topic = Projects::Topic.new(topic_params)
if @topic.save
- redirect_to edit_admin_topic_path(@topic), notice: format(_('Topic %{topic_name} was successfully created.'), topic_name: @topic.name)
+ redirect_to admin_topics_path, notice: format(_('Topic %{topic_name} was successfully created.'), topic_name: @topic.name)
else
render "new"
end
diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb
index 1fbec8f9e73..76aa4afbe80 100644
--- a/app/controllers/registrations/welcome_controller.rb
+++ b/app/controllers/registrations/welcome_controller.rb
@@ -4,6 +4,7 @@ module Registrations
class WelcomeController < ApplicationController
include OneTrustCSP
include GoogleAnalyticsCSP
+ include ::Gitlab::Utils::StrongMemoize
layout 'minimal'
skip_before_action :authenticate_user!, :required_signup_info, :check_two_factor_requirement, only: [:show, :update]
@@ -24,6 +25,7 @@ module Registrations
if result.success?
track_event('successfully_submitted_form')
+ finish_onboarding_on_welcome_page unless complete_signup_onboarding?
redirect_to update_success_path
else
@@ -34,6 +36,8 @@ module Registrations
private
def registering_from_invite?(members)
+ # If there are more than one member it will mean we have been invited to multiple projects/groups and
+ # are not able to distinguish which one we should putting the user in after registration
members.count == 1 && members.last.source.present?
end
@@ -61,31 +65,37 @@ module Registrations
end
# overridden in EE
- def redirect_to_signup_onboarding?
+ def complete_signup_onboarding?
false
end
- def redirect_for_tasks_to_be_done?
- MemberTask.for_members(current_user.members).exists?
+ def invites_with_tasks_to_be_done?
+ MemberTask.for_members(user_members).exists?
end
def update_success_path
- return issues_dashboard_path(assignee_username: current_user.username) if redirect_for_tasks_to_be_done?
-
- return signup_onboarding_path if redirect_to_signup_onboarding?
-
- members = current_user.members
-
- if registering_from_invite?(members)
- flash[:notice] = helpers.invite_accepted_notice(members.last)
- members_activity_path(members)
+ if invites_with_tasks_to_be_done?
+ issues_dashboard_path(assignee_username: current_user.username)
+ elsif complete_signup_onboarding? # trials/regular registration on .com
+ signup_onboarding_path
+ elsif registering_from_invite?(user_members) # invites w/o tasks due to order
+ flash[:notice] = helpers.invite_accepted_notice(user_members.last)
+ members_activity_path(user_members)
else
- # subscription registrations goes through here as well
- finish_onboarding_if_in_subscription_flow
+ # Subscription registrations goes through here as well.
+ # Invites will come here too if there is more than 1.
path_for_signed_in_user(current_user)
end
end
+ def user_members
+ current_user.members
+ end
+ strong_memoize_attr :user_members
+
+ # overridden in EE
+ def finish_onboarding_on_welcome_page; end
+
# overridden in EE
def signup_onboarding_path; end
@@ -96,9 +106,6 @@ module Registrations
def welcome_update_params
{}
end
-
- # overridden in EE
- def finish_onboarding_if_in_subscription_flow; end
end
end
diff --git a/config/initializers_before_autoloader/003_gc_compact.rb b/config/initializers_before_autoloader/003_gc_compact.rb
deleted file mode 100644
index 6b5d49d79ab..00000000000
--- a/config/initializers_before_autoloader/003_gc_compact.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-# Be sure to restart your server when you modify this file.
-#
-# Disables `GC.compact` method via monkey-patching.
-# This is temporary measure to deal with reguarly appearing compacting issues (resulting in segfaults) in external gems.
-# Having this patch allow using `nakayoshi_fork` in `config/puma.rb`,
-# only without `GC.compact` (still invoking 4 GC cycles).
-# Refer to for details: https://github.com/puma/puma/blob/80274413b04fae77cac7a7fecab7d6e89204343b/lib/puma/util.rb#L27
-
-# rubocop:disable Rails/Output
-module NakayoshiForkCompacting
- module MonkeyPatch
- def compact
- puts 'Note: GC compacting is currently disabled.'\
- ' Refer to `config/initializers_before_autoloader/003_gc_compact.rb` for details.'
- end
- end
-end
-
-GC.singleton_class.prepend NakayoshiForkCompacting::MonkeyPatch
diff --git a/config/puma.example.development.rb b/config/puma.example.development.rb
index 1183e3d75cf..e7dacc70c2e 100644
--- a/config/puma.example.development.rb
+++ b/config/puma.example.development.rb
@@ -84,13 +84,6 @@ worker_timeout 60
# https://github.com/puma/puma/blob/master/5.0-Upgrade.md#lower-latency-better-throughput
wait_for_less_busy_worker ENV.fetch('PUMA_WAIT_FOR_LESS_BUSY_WORKER', 0.001).to_f
-# nakayoshi_fork was removed in Puma 6.0: https://github.com/puma/puma/issues/2258
-# https://github.com/puma/puma/blob/master/5.0-Upgrade.md#nakayoshi_fork
-if Gem::Version.new(Puma::Const::PUMA_VERSION).canonical_segments.first == 5 &&
- ENV['DISABLE_PUMA_NAKAYOSHI_FORK'] != 'true'
- nakayoshi_fork
-end
-
# Use json formatter
require_relative "/home/git/gitlab/lib/gitlab/puma_logging/json_formatter"
diff --git a/config/puma.rb.example b/config/puma.rb.example
index ac3adc1eeec..07a6f6a2501 100644
--- a/config/puma.rb.example
+++ b/config/puma.rb.example
@@ -73,13 +73,6 @@ worker_timeout 60
# https://github.com/puma/puma/blob/master/5.0-Upgrade.md#lower-latency-better-throughput
wait_for_less_busy_worker ENV.fetch('PUMA_WAIT_FOR_LESS_BUSY_WORKER', 0.001).to_f
-# nakayoshi_fork was removed in Puma 6.0: https://github.com/puma/puma/issues/2258
-# https://github.com/puma/puma/blob/master/5.0-Upgrade.md#nakayoshi_fork
-if Gem::Version.new(Puma::Const::PUMA_VERSION).canonical_segments.first == 5 &&
- ENV['DISABLE_PUMA_NAKAYOSHI_FORK'] != 'true'
- nakayoshi_fork
-end
-
# Use json formatter
require_relative "/home/git/gitlab/lib/gitlab/puma_logging/json_formatter"
diff --git a/db/15_11_migration_fixes.txt b/db/15_11_migration_fixes.txt
new file mode 100644
index 00000000000..7fa291f7b29
--- /dev/null
+++ b/db/15_11_migration_fixes.txt
@@ -0,0 +1,299 @@
+20211202041233
+20211202094944
+20211202135508
+20211202145237
+20211203091642
+20211203160952
+20211203161149
+20211203161840
+20211203161942
+20211204010826
+20211206073851
+20211206074547
+20211206161271
+20211207081708
+20211207090503
+20211207125331
+20211207135331
+20211207154413
+20211207154414
+20211207165508
+20211207173510
+20211207173511
+20211208111425
+20211208122200
+20211208122201
+20211208171402
+20211209093636
+20211209093828
+20211209093923
+20211209094222
+20211209103048
+20211209203820
+20211209203821
+20211209230042
+20211210025754
+20211210031721
+20211210140000
+20211210140629
+20211210173137
+20211213064821
+20211213102111
+20211213130324
+20211213142344
+20211213154259
+20211213154704
+20211214012507
+20211214110307
+20211215090620
+20211215182006
+20211216133107
+20211216134134
+20211216135651
+20211216220939
+20211217050753
+20211217120000
+20211217145923
+20211217174331
+20211220064757
+20211220120402
+20211220123956
+20211220174504
+20211223125921
+20211224112937
+20211224114539
+20211229023654
+20211230112517
+20211230113031
+20220104060049
+20220104174445
+20220105020514
+20220105082217
+20220105121325
+20220105152547
+20220105153149
+20220106111958
+20220106112043
+20220106112085
+20220106141756
+20220106163326
+20220106185033
+20220106230629
+20220106230712
+20220106231518
+20220106233459
+20220106235626
+20220107064845
+20220107091629
+20220107165036
+20220109133006
+20220109134455
+20220110170953
+20220110171049
+20220110224913
+20220110231420
+20220110233155
+20220111002756
+20220111023852
+20220111093534
+20220111095006
+20220111095007
+20220111101421
+20220111102314
+20220111154950
+20220111154951
+20220111200254
+20220111221516
+20220112015940
+20220112090556
+20220112115413
+20220112205111
+20220112230642
+20220112232037
+20220112232605
+20220112232723
+20220113013319
+20220113014438
+20220113015830
+20220113035519
+20220113040447
+20220113111440
+20220113125401
+20220113135449
+20220113135924
+20220113164801
+20220113164901
+20220114105525
+20220114131950
+20220116175851
+20220117034056
+20220117082611
+20220117225936
+20220118015633
+20220118020026
+20220118141950
+20220118155846
+20220118155847
+20220118155848
+20220118204039
+20220119094023
+20220119094503
+20220119141407
+20220119141736
+20220119143130
+20220119144253
+20220119144458
+20220119151221
+20220119153706
+20220119154442
+20220119170426
+20220119193130
+20220119201340
+20220119203119
+20220119220620
+20220120033115
+20220120085655
+20220120094340
+20220120123700
+20220120123800
+20220120160625
+20220120211831
+20220120211832
+20220121214752
+20220121214753
+20220121221651
+20220124130028
+20220124145019
+20220124151456
+20220124151949
+20220124152824
+20220124153233
+20220124153234
+20220124180704
+20220124180705
+20220124184338
+20220124200927
+20220124204046
+20220124214131
+20220124215857
+20220124221521
+20220125083520
+20220125084127
+20220125084348
+20220125122228
+20220125122640
+20220125122725
+20220125230538
+20220126191624
+20220126201752
+20220126202654
+20220126203421
+20220126210021
+20220126210022
+20220126210657
+20220127112243
+20220127112412
+20220127132200
+20220127132201
+20220128093756
+20220128103042
+20220128155251
+20220128155814
+20220128194722
+20220131000000
+20220131000001
+20220131135725
+20220131192643
+20220201034731
+20220201141705
+20220201173212
+20220201193033
+20220201205300
+20220202034409
+20220202105733
+20220202115350
+20220203074916
+20220203091304
+20220203123333
+20220203133652
+20220203134942
+20220204053655
+20220204093120
+20220204095121
+20220204110725
+20220204154220
+20220204193000
+20220204194347
+20220207080758
+20220207083129
+20220208080921
+20220208115439
+20220208170445
+20220208171826
+20220209111007
+20220211090920
+20220211125954
+20220211214605
+20220212120735
+20220213100000
+20220213103859
+20220213104531
+20220215164709
+20220215190020
+20220216110023
+20220216201949
+20220217100008
+20220217113058
+20220217135229
+20220221102333
+20220221214928
+20220222072536
+20220222191845
+20220222192524
+20220222192525
+20220223112304
+20220223124428
+20220224000000
+20220224204415
+20220225133705
+20220301002101
+20220301003502
+20220301091503
+20220301093434
+20220301175104
+20220301175426
+20220302110724
+20220302114046
+20220302203410
+20220303190555
+20220303191047
+20220304052335
+20220304061631
+20220304062107
+20220304152729
+20220304165107
+20220304201847
+20220305223212
+20220307192534
+20220307192610
+20220307192645
+20220307192725
+20220307203458
+20220307203459
+20220308000205
+20220308115219
+20220308115502
+20220309084838
+20220309084954
+20220309100648
+20220309154855
+20220310011530
+20220310011613
+20220310095341
+20220310101118
+20220310134207
+20220310141349
+20220311010352
+20220314094841
+20220314154235
+20220314162342 \ No newline at end of file
diff --git a/db/post_migrate/20230522220709_ensure_incident_work_item_type_backfill_is_finished.rb b/db/post_migrate/20230522220709_ensure_incident_work_item_type_backfill_is_finished.rb
new file mode 100644
index 00000000000..a93f5417dd0
--- /dev/null
+++ b/db/post_migrate/20230522220709_ensure_incident_work_item_type_backfill_is_finished.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class EnsureIncidentWorkItemTypeBackfillIsFinished < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ MIGRATION = 'BackfillWorkItemTypeIdForIssues'
+ INCIDENT_ENUM_TYPE = 1
+
+ class MigrationWorkItemType < MigrationRecord
+ self.table_name = 'work_item_types'
+ end
+
+ def up
+ incident_work_item_type = MigrationWorkItemType.find_by(namespace_id: nil, base_type: INCIDENT_ENUM_TYPE)
+
+ if incident_work_item_type.blank?
+ say(
+ 'Incident work item type not found. Make sure the work_item_types table is populated' \
+ 'before running this migration'
+ )
+ return
+ end
+
+ ensure_batched_background_migration_is_finished(
+ job_class_name: MIGRATION,
+ table_name: :issues,
+ column_name: :id,
+ job_arguments: [INCIDENT_ENUM_TYPE, incident_work_item_type.id]
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20230522225610_remove_tmp_index_issues_on_issue_type_and_id_only_incidents.rb b/db/post_migrate/20230522225610_remove_tmp_index_issues_on_issue_type_and_id_only_incidents.rb
new file mode 100644
index 00000000000..f6cbff24755
--- /dev/null
+++ b/db/post_migrate/20230522225610_remove_tmp_index_issues_on_issue_type_and_id_only_incidents.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class RemoveTmpIndexIssuesOnIssueTypeAndIdOnlyIncidents < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'tmp_index_issues_on_issue_type_and_id_only_incidents'
+ INCIDENT_ENUM_VALUE = 1
+
+ def up
+ remove_concurrent_index_by_name :issues, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :issues, [:issue_type, :id], name: INDEX_NAME, where: "issue_type = #{INCIDENT_ENUM_VALUE}"
+ end
+end
diff --git a/db/schema_migrations/20230522220709 b/db/schema_migrations/20230522220709
new file mode 100644
index 00000000000..aadbdc7f2cf
--- /dev/null
+++ b/db/schema_migrations/20230522220709
@@ -0,0 +1 @@
+ef28d42bc0e59c42c6764f0859d36307bf4c6594d109fcfaabbb8ae5392ed563 \ No newline at end of file
diff --git a/db/schema_migrations/20230522225610 b/db/schema_migrations/20230522225610
new file mode 100644
index 00000000000..d9e737d11de
--- /dev/null
+++ b/db/schema_migrations/20230522225610
@@ -0,0 +1 @@
+efa846e74dcc14732fe78f8458e1d44bb12f3b97282c14e4a33c87eac561e032 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 7a04e1af4cf..99a76247e01 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -33183,8 +33183,6 @@ CREATE INDEX tmp_index_for_null_member_namespace_id ON members USING btree (memb
CREATE INDEX tmp_index_for_project_namespace_id_migration_on_routes ON routes USING btree (id) WHERE ((namespace_id IS NULL) AND ((source_type)::text = 'Project'::text));
-CREATE INDEX tmp_index_issues_on_issue_type_and_id_only_incidents ON issues USING btree (issue_type, id) WHERE (issue_type = 1);
-
CREATE INDEX tmp_index_members_on_state ON members USING btree (state) WHERE (state = 2);
CREATE INDEX tmp_index_migrated_container_registries ON container_repositories USING btree (project_id) WHERE ((migration_state = 'import_done'::text) OR (created_at >= '2022-01-23 00:00:00'::timestamp without time zone));
diff --git a/doc/api/environments.md b/doc/api/environments.md
index 501fec70dd6..d2335149301 100644
--- a/doc/api/environments.md
+++ b/doc/api/environments.md
@@ -40,89 +40,7 @@ Example response:
"created_at": "2019-05-25T18:55:13.252Z",
"updated_at": "2019-05-27T18:55:13.252Z",
"enable_advanced_logs_querying": false,
- "logs_api_path": "/project/-/logs/k8s.json?environment_name=review%2Ffix-foo",
- "last_deployment": {
- "id": 100,
- "iid": 34,
- "ref": "fdroid",
- "sha": "416d8ea11849050d3d1f5104cf8cf51053e790ab",
- "created_at": "2019-03-25T18:55:13.252Z",
- "status": "success",
- "user": {
- "id": 1,
- "name": "Administrator",
- "state": "active",
- "username": "root",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://localhost:3000/root"
- },
- "deployable": {
- "id": 710,
- "status": "success",
- "stage": "deploy",
- "name": "staging",
- "ref": "fdroid",
- "tag": false,
- "coverage": null,
- "created_at": "2019-03-25T18:55:13.215Z",
- "started_at": "2019-03-25T12:54:50.082Z",
- "finished_at": "2019-03-25T18:55:13.216Z",
- "duration": 21623.13423,
- "project": {
- "ci_job_token_scope_enabled": false
- },
- "user": {
- "id": 1,
- "name": "Administrator",
- "username": "root",
- "state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://gitlab.dev/root",
- "created_at": "2015-12-21T13:14:24.077Z",
- "bio": null,
- "location": null,
- "public_email": "",
- "skype": "",
- "linkedin": "",
- "twitter": "",
- "website_url": "",
- "organization": null
- },
- "commit": {
- "id": "416d8ea11849050d3d1f5104cf8cf51053e790ab",
- "short_id": "416d8ea1",
- "created_at": "2016-01-02T15:39:18.000Z",
- "parent_ids": [
- "e9a4449c95c64358840902508fc827f1a2eab7df"
- ],
- "title": "Removed fabric to fix #40",
- "message": "Removed fabric to fix #40\n",
- "author_name": "Administrator",
- "author_email": "admin@example.com",
- "authored_date": "2016-01-02T15:39:18.000Z",
- "committer_name": "Administrator",
- "committer_email": "admin@example.com",
- "committed_date": "2016-01-02T15:39:18.000Z"
- },
- "pipeline": {
- "id": 34,
- "sha": "416d8ea11849050d3d1f5104cf8cf51053e790ab",
- "ref": "fdroid",
- "status": "success",
- "web_url": "http://localhost:3000/Commit451/lab-coat/pipelines/34"
- },
- "web_url": "http://localhost:3000/Commit451/lab-coat/-/jobs/710",
- "artifacts": [
- {
- "file_type": "trace",
- "size": 1305,
- "filename": "job.log",
- "file_format": null
- }
- ],
- "runner": null,
- "artifacts_expire_at": null
- }
+ "logs_api_path": "/project/-/logs/k8s.json?environment_name=review%2Ffix-foo"
}
]
```
diff --git a/doc/tutorials/hugo/index.md b/doc/tutorials/hugo/index.md
new file mode 100644
index 00000000000..22d512080c7
--- /dev/null
+++ b/doc/tutorials/hugo/index.md
@@ -0,0 +1,169 @@
+---
+stage: Plan
+group: Knowledge
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Tutorial: Build, test, and deploy your Hugo site with GitLab
+
+<!-- vale gitlab.FutureTense = NO -->
+
+This tutorial walks you through creating a CI/CD pipeline to build, test, and deploy a Hugo site.
+
+By the end of the tutorial, you'll have a working pipeline and a Hugo site deployed on GitLab Pages.
+
+Here's an overview of what you're going to do:
+
+1. Prepare your Hugo site.
+1. Create a GitLab project.
+1. Push your Hugo site to GitLab.
+1. Build your Hugo site with a CI/CD pipeline.
+1. Deploy and view your Hugo site with GitLab Pages.
+
+## Prerequisites
+
+- An account on GitLab.com.
+- Familiarity with Git.
+- A Hugo site (if you don't already have one, you can follow the [Hugo Quick Start](https://gohugo.io/getting-started/quick-start/)).
+
+## Prepare your Hugo site
+
+First, make sure your Hugo site is ready to push to GitLab. You need to have your content, a theme, and a configuration file.
+
+Don't *build* your site, as GitLab does that for you. In fact, it's important to **not** upload your `public` folder, as this can cause conflicts later on.
+
+The easiest way to exclude your `public` folder is by creating a `.gitignore` file and adding your `public` folder to it.
+
+You can do this with the following command at the top level of your Hugo project:
+
+```shell
+echo "/public/" >> .gitignore
+```
+
+This either adds `/public/` to a new `.gitignore` file or appends it to an existing file.
+
+OK, your Hugo site is ready to push, after you create a GitLab project.
+
+## Create a GitLab project
+
+If you haven't done so already, create a blank GitLab project for your Hugo site.
+
+To create a blank project, in GitLab:
+
+1. On the top bar, select **Main menu > Projects > View all projects**.
+1. On the right of the page, select **New project**.
+1. Select **Create blank project**.
+1. Enter the project details:
+ - In the **Project name** field, enter the name of your project. The name must start with a lowercase or uppercase letter (`a-zA-Z`), digit (`0-9`), emoji, or underscore (`_`). It can also contain dots (`.`), pluses (`+`), dashes (`-`), or spaces.
+ - In the **Project slug** field, enter the path to your project. The GitLab instance uses the slug as the URL path to the project. To change the slug, first enter the project name, then change the slug.
+ - The **Visibility Level** can be either Private or Public. If you choose Private, your website is still publicly available, but your code remains private.
+ - Because you're pushing an existing repository, clear the box to **Initialize repository with a README**.
+1. When you're ready, select **Create project**.
+1. You should see instructions for pushing your code to this new project. You'll need those instructions in the next step.
+
+You now have a home for your Hugo site!
+
+## Push your Hugo site to GitLab
+
+Next you need to push your local Hugo site to your remote GitLab project.
+
+If you created a new GitLab project in the previous step, you'll see the instructions for initializing your repository, then committing and pushing your files.
+
+Otherwise, make sure the remote origin for your local Git repository matches your GitLab project.
+
+Assuming your default branch is `main`, you can push your Hugo site with the following command:
+
+```shell
+git push origin main
+```
+
+After you've pushed your site, you should see all the content except the `public` folder. The `public` folder was excluded by the `.gitignore` file.
+
+In the next step, you'll use a CI/CD pipeline to build your site and recreate that `public` folder.
+
+## Build your Hugo site
+
+To build a Hugo site with GitLab, you first need to create a `.gitlab-ci.yml` file to specify instructions for the CI/CD pipeline. If you've not done this before, it might sound daunting. However, GitLab provides everything you need.
+
+### Add your configuration options
+
+You specify your configuration options in a special file called `.gitlab-ci.yml`. To create a `.gitlab-ci.yml` file:
+
+1. On the left sidebar, select **Repository > Files**.
+1. Above the file list, select the plus icon ( + ), then select **New file** from the dropdown list.
+1. For the filename, enter `.gitlab-ci.yml`. Don't omit the period at the beginning.
+1. Select the **Apply a template** dropdown list, then enter "Hugo" in the filter box.
+1. Select the result **Hugo**, and your file is populated with all the code you need to build your Hugo site using CI/CD.
+
+Let's take a closer look at what's happening in this `.gitlab-ci.yml` file.
+
+```yaml
+default:
+ image: "${CI_TEMPLATE_REGISTRY_HOST}/pages/hugo:latest"
+
+variables:
+ GIT_SUBMODULE_STRATEGY: recursive
+
+test: # builds and tests your site
+ script:
+ - hugo
+ rules:
+ - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
+
+pages: # a predefined job that builds your pages and saves them to the specified path.
+ script:
+ - hugo
+ artifacts:
+ paths:
+ - public
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ environment: production
+```
+
+- `image` specifies an image from the GitLab Registry that contains Hugo. This image is used to create the environment where your site is built.
+- The `GIT_SUBMODULE_STRATEGY` variable ensures GitLab also looks at your Git submodules, which are sometimes used for Hugo themes.
+- `test` is a job where you can run tests on your Hugo site before it's deployed. The test job runs in all cases, *except* if you're committing a change to your default branch. You place any commands under `script`. The command in this job - `hugo`- builds your site so it can be tested.
+- `pages` is a predefined job for creating pages from Static Site Generators. Again, this job runs the `hugo` command to build your site. Then `artifacts` specifies that those resulting pages are added to a directory called `public`. With `rules`, you're checking that this commit was made on the default branch. Typically, you wouldn't want to build and deploy the live site from a feature branch.
+
+You don't need to add anything else to this file. When you're ready, select **Commit changes** at the bottom of the page.
+
+You've just triggered a pipeline to build your Hugo site!
+
+## Deploy and view your Hugo site
+
+If you're quick, you can see GitLab build and deploy your site.
+
+From the left-hand navigation, select **Build > Pipelines**.
+
+You'll see that GitLab has run your `test` and `pages` jobs.
+
+To view your site, on the left-hand navigation, select **Settings > Pages**
+
+The `pages` job in your pipeline has deployed the contents of your `public` directory to GitLab Pages. Under **Access pages**, you should see the link in the format: `https://<your-namespace>.gitlab.io/<project-name>`.
+
+You won't see this link if you haven't yet run your pipeline.
+
+Select the displayed link to view your site.
+
+When you first view your Hugo site, the stylesheet won't work. Don't worry, you need to make a small change in your Hugo configuration file. Hugo needs to know the URL of your GitLab Pages site so it can build relative links to stylesheets and other assets:
+
+1. In your local Hugo site, open your `config.yaml` or `config.toml` file.
+1. Change the value of the `BaseURL` parameter to match the URL that appears in your GitLab Pages settings.
+1. Push your changed file to GitLab, and your pipeline is triggered again.
+
+When the pipeline has finished, your site should be working at the URL you just specified.
+
+If your Hugo site is stored in a private repository, you'll need to change your permissions so the Pages site is visible. Otherwise, it's visible only to authorized users. To change your permissions:
+
+1. Go to **Settings > General > Visibility, project features, permissions**.
+1. Scroll down to the **Pages** section and select **Everyone** from the dropdown list.
+1. Select **Save changes**.
+
+Now everyone can see it.
+
+You've built, tested, and deployed your Hugo site with GitLab. Great work!
+
+Every time you change your site and push it to GitLab, your site is built, tested, and deployed automatically.
+
+To learn more about CI/CD pipelines, try [this tutorial on how to create a complex pipeline](../../ci/quick_start/tutorial.md). You can also learn more about the [different types of testing available](../../ci/testing/index.md).
diff --git a/doc/user/clusters/agent/gitops/flux.md b/doc/user/clusters/agent/gitops/flux.md
index 98840080716..db2cab23b4a 100644
--- a/doc/user/clusters/agent/gitops/flux.md
+++ b/doc/user/clusters/agent/gitops/flux.md
@@ -13,6 +13,10 @@ You can use Flux to:
- Reconcile code changes with your deployments.
- Manage your Flux installation itself with a bootstrap.
+You can use the agent for Kubernetes with Flux to:
+
+- Trigger immediate Git repository reconciliation.
+
To get started, see the [Flux installation documentation](https://fluxcd.io/flux/installation).
Support for Flux is in [Beta](../../../../policy/alpha-beta-support.md#beta).
@@ -34,3 +38,60 @@ write access to the source repositories.
## GitOps repository structure
You should organize your repositories to meet the needs of your team. For detailed recommendations, see the Flux [repository structure documentation](https://fluxcd.io/flux/guides/repository-structure/).
+
+## Immediate Git repository reconciliation
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/392852) in GitLab 16.1.
+
+Usually, the Flux source controller reconciles Git repositories at configured intervals.
+This can cause delays between a `git push` and the reconciliation of the cluster state, and results in
+unnecessary pulls from GitLab.
+
+The agent for Kubernetes automatically detects Flux `GitRepository` objects that
+reference GitLab projects in the instance the agent is connected to,
+and configures a [`Receiver`](https://fluxcd.io/flux/components/notification/receiver/) for the instance.
+When the agent for Kubernetes detects a `git push`, the `Receiver` is triggered
+and Flux reconciles the cluster with any changes to the repository.
+
+To use immediate Git repository reconciliation, you must have a Kubernetes cluster that runs:
+
+- The agent for Kubernetes.
+- Flux `source-controller` and `notification-controller`.
+
+Immediate Git repository reconciliation can reduce the time between a push and reconciliation,
+but it doesn't guarantee that every `git push` event is received. You should still set
+[`GitRepository.spec.interval`](https://fluxcd.io/flux/components/source/gitrepositories/#interval)
+to an acceptable duration.
+
+### Custom webhook endpoints
+
+When the agent for Kubernetes calls the `Receiver` webhook,
+the agent defaults to `http://webhook-receiver.flux-system.svc.cluster.local`,
+which is also the default set by a Flux bootstrap installation. To configure a custom
+endpoint, set `flux.webhook_receiver_url` to a URL that the agent can resolve. For example:
+
+```yaml
+flux:
+ webhook_receiver_url: http://webhook-receiver.another-flux-namespace.svc.cluster.local
+```
+
+There is special handing for
+[service proxy URIs](https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster-services/) configured
+in this format: `/api/v1/namespaces/[^/]+/services/[^/]+/proxy`. For example:
+
+```yaml
+flux:
+ webhook_receiver_url: /api/v1/namespaces/flux-system/services/http:webhook-receiver:80/proxy
+```
+
+In these cases, the agent for Kubernetes uses the available Kubernetes configuration
+and context to connect to the API endpoint.
+You can use this if you run an agent outside a cluster
+and you haven't [configured an `Ingress`](https://fluxcd.io/flux/guides/webhook-receivers/#expose-the-webhook-receiver)
+for the Flux notification controller.
+
+WARNING:
+You should configure only trusted service proxy URIs.
+When the agent for Kubernetes provides a service proxy URI,
+it sends typical Kubernetes API requests which include
+the credentials necessary to authenticate with the API service.
diff --git a/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
index d6f6e94526e..6a364959db2 100644
--- a/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
@@ -6,7 +6,8 @@
---
# All available Hugo versions are listed here:
# https://gitlab.com/pages/hugo/container_registry
-image: "${CI_TEMPLATE_REGISTRY_HOST}/pages/hugo:latest"
+default:
+ image: "${CI_TEMPLATE_REGISTRY_HOST}/pages/hugo:latest"
variables:
GIT_SUBMODULE_STRATEGY: recursive
@@ -14,9 +15,8 @@ variables:
test:
script:
- hugo
- except:
- variables:
- - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ rules:
+ - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
pages:
script:
@@ -24,7 +24,6 @@ pages:
artifacts:
paths:
- public
- only:
- variables:
- - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
environment: production
diff --git a/lib/tasks/gitlab/db/migration_fix_15_11.rake b/lib/tasks/gitlab/db/migration_fix_15_11.rake
new file mode 100644
index 00000000000..fbfee856abb
--- /dev/null
+++ b/lib/tasks/gitlab/db/migration_fix_15_11.rake
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+desc 'db | migration_fix_15_11'
+task migration_fix_15_11: [:environment] do
+ next if Gitlab.com?
+
+ only_on = %i[main ci].select { |db| Gitlab::Database.has_database?(db) }
+ Gitlab::Database::EachDatabase.each_database_connection(only: only_on) do |conn, database|
+ begin
+ first_migration = conn.execute('SELECT * FROM schema_migrations ORDER BY version ASC LIMIT 1')
+ rescue ActiveRecord::StatementInvalid
+ # Uninitialized DB, skip
+ next
+ end
+ next if first_migration.none? # No migrations have been run yet
+ # If we are affected, the first migration in the schema_migrations table
+ # will be 20220314184009
+ next unless first_migration.first['version'] == '20220314184009'
+
+ puts "Running 15.11 migration fix for #{database}"
+ fixes = File.readlines(Rails.root.join('db/15_11_migration_fixes.txt')).map(&:chomp)
+ conn.transaction do
+ fixes.each do |version|
+ conn.execute("INSERT INTO schema_migrations (version) VALUES ('#{version}')")
+ end
+ end
+ end
+end
+
+Rake::Task['db:migrate'].enhance(['migration_fix_15_11'])
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 3b50a0f0d30..b40f3a090b6 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1862,6 +1862,9 @@ msgstr ""
msgid "AI actions"
msgstr ""
+msgid "AI-generated summary"
+msgstr ""
+
msgid "AI-generated test file"
msgstr ""
@@ -1871,7 +1874,7 @@ msgstr ""
msgid "AISummary|Generates a summary of all comments"
msgstr ""
-msgid "AISummary|See summary"
+msgid "AISummary|View summary"
msgstr ""
msgid "AI| %{link_start}How is my data used?%{link_end}"
@@ -1925,9 +1928,6 @@ msgstr ""
msgid "AI|Something went wrong. Please try again later"
msgstr ""
-msgid "AI|Text generated by AI"
-msgstr ""
-
msgid "AI|The container element wasn't found, stopping AI Genie."
msgstr ""
diff --git a/spec/controllers/admin/topics_controller_spec.rb b/spec/controllers/admin/topics_controller_spec.rb
index e640f8bb7ec..fbac9de584b 100644
--- a/spec/controllers/admin/topics_controller_spec.rb
+++ b/spec/controllers/admin/topics_controller_spec.rb
@@ -102,6 +102,12 @@ RSpec.describe Admin::TopicsController do
expect(errors).to contain_exactly(errors.full_message(:title, I18n.t('errors.messages.blank')))
end
+ it 'redirects to the topics list' do
+ post :create, params: { projects_topic: { name: 'test-redirect', title: "Test redirect" } }
+
+ expect(response).to redirect_to(admin_topics_path)
+ end
+
context 'as a normal user' do
before do
sign_in(user)
diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
index 576ce23b058..e42e4735ee2 100644
--- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
+++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
@@ -182,7 +182,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js, featur
visit project_merge_request_path(project, merge_request)
end
- it 'allows to cancel the automatic merge' do
+ it 'allows to cancel the automatic merge', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/412416' do
click_button "Cancel auto-merge"
expect(page).to have_button "Merge when pipeline succeeds"
diff --git a/spec/migrations/20230522220709_ensure_incident_work_item_type_backfill_is_finished_spec.rb b/spec/migrations/20230522220709_ensure_incident_work_item_type_backfill_is_finished_spec.rb
new file mode 100644
index 00000000000..9699e2df877
--- /dev/null
+++ b/spec/migrations/20230522220709_ensure_incident_work_item_type_backfill_is_finished_spec.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe EnsureIncidentWorkItemTypeBackfillIsFinished, :migration, feature_category: :team_planning do
+ include MigrationHelpers::WorkItemTypesHelper
+
+ let(:batched_migrations) { table(:batched_background_migrations) }
+ let(:work_item_types) { table(:work_item_types) }
+ let(:batch_failed_status) { 2 }
+
+ let!(:migration_class) { described_class::MIGRATION }
+
+ describe '#up', :redis do
+ it "doesn't fail if work item types don't exist on the DB" do
+ table(:work_item_types).delete_all
+
+ migrate!
+
+ # Since migration specs run outside of a transaction, we need to make
+ # sure we recreate default types since this spec deletes them all
+ reset_work_item_types
+ end
+
+ context 'when migration is missing' do
+ before do
+ batched_migrations.where(job_class_name: migration_class).delete_all
+ end
+
+ it 'warns migration not found' do
+ expect(Gitlab::AppLogger)
+ .to receive(:warn).with(/Could not find batched background migration for the given configuration:/)
+ .once
+
+ migrate!
+ end
+ end
+
+ context 'with migration present' do
+ let!(:backfill_migration) do
+ type_id = work_item_types.find_by!(namespace_id: nil, base_type: described_class::INCIDENT_ENUM_TYPE).id
+
+ create_migration_with(status, described_class::INCIDENT_ENUM_TYPE, type_id)
+ end
+
+ context 'when migrations have finished' do
+ let(:status) { 3 } # finished enum value
+
+ it 'does not raise an error' do
+ expect { migrate! }.not_to raise_error
+ end
+ end
+
+ context 'with different migration statuses' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:status, :description) do
+ 0 | 'paused'
+ 1 | 'active'
+ 4 | 'failed'
+ 5 | 'finalizing'
+ end
+
+ with_them do
+ it 'finalizes the migration' do
+ expect do
+ migrate!
+
+ backfill_migration.reload
+ end.to change { backfill_migration.status }.from(status).to(3)
+ end
+ end
+ end
+ end
+ end
+
+ def create_migration_with(status, base_type, type_id)
+ migration = batched_migrations.create!(
+ job_class_name: migration_class,
+ table_name: :issues,
+ column_name: :id,
+ job_arguments: [base_type, type_id],
+ interval: 2.minutes,
+ min_value: 1,
+ max_value: 2,
+ batch_size: 1000,
+ sub_batch_size: 200,
+ gitlab_schema: :gitlab_main,
+ status: status
+ )
+
+ table(:batched_background_migration_jobs).create!(
+ batched_background_migration_id: migration.id,
+ status: batch_failed_status,
+ min_value: 1,
+ max_value: 10,
+ attempts: 2,
+ batch_size: 100,
+ sub_batch_size: 10
+ )
+
+ migration
+ end
+end
diff --git a/spec/support/shared_examples/features/work_items_shared_examples.rb b/spec/support/shared_examples/features/work_items_shared_examples.rb
index 46c8ebc01be..32611621bce 100644
--- a/spec/support/shared_examples/features/work_items_shared_examples.rb
+++ b/spec/support/shared_examples/features/work_items_shared_examples.rb
@@ -148,7 +148,7 @@ RSpec.shared_examples 'work items assignees' do
find("body").click
wait_for_requests
- expect(work_item.assignees).to include(user)
+ expect(work_item.reload.assignees).to include(user)
end
end
diff --git a/spec/tasks/gitlab/db/migration_fix_15_11_rake_spec.rb b/spec/tasks/gitlab/db/migration_fix_15_11_rake_spec.rb
new file mode 100644
index 00000000000..3ff07698ad4
--- /dev/null
+++ b/spec/tasks/gitlab/db/migration_fix_15_11_rake_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'rake_helper'
+
+RSpec.describe 'migration_fix_15_11', :reestablished_active_record_base, feature_category: :database do
+ let(:db) { ApplicationRecord.connection }
+ let(:target_init_schema) { '20220314184009' }
+ let(:earlier_init_schema) { '20210101010101' }
+
+ before :all do
+ Rake.application.rake_require 'active_record/railties/databases'
+ Rake.application.rake_require 'tasks/gitlab/db/migration_fix_15_11'
+
+ Rake::Task.define_task :environment
+ end
+
+ describe 'migration_fix_15_11' do
+ context 'when fix is needed' do
+ it 'patches init_schema' do
+ db.execute('DELETE FROM schema_migrations')
+ db.execute("INSERT INTO schema_migrations (version) VALUES ('#{target_init_schema}')")
+ run_rake_task(:migration_fix_15_11)
+ result = db.execute('SELECT * FROM schema_migrations')
+ expect(result.count).to eq(300)
+ end
+ end
+
+ context 'when fix is not needed because no migrations have been run' do
+ it 'does nothing' do
+ db.execute('DELETE FROM schema_migrations')
+ run_rake_task(:migration_fix_15_11)
+ result = db.execute('SELECT * FROM schema_migrations')
+ expect(result.count).to eq(0)
+ end
+ end
+
+ context 'when fix is not needed because DB has not been initialized' do
+ it 'does nothing' do
+ db.execute('DROP TABLE schema_migrations')
+ expect { run_rake_task(:migration_fix_15_11) }.not_to raise_error
+ end
+ end
+
+ context 'when fix is not needed because there is an earlier init_schema' do
+ it 'does nothing' do
+ db.execute('DELETE FROM schema_migrations')
+ db.execute("INSERT INTO schema_migrations (version) VALUES ('#{earlier_init_schema}')")
+ run_rake_task(:migration_fix_15_11)
+ result = db.execute('SELECT * FROM schema_migrations')
+ expect(result.pluck('version')).to match_array [earlier_init_schema]
+ end
+ end
+
+ context 'when fix is not needed because the fix has been run already' do
+ it 'does not affect the schema_migrations table' do
+ db.execute('DELETE FROM schema_migrations')
+ db.execute("INSERT INTO schema_migrations (version) VALUES ('#{target_init_schema}')")
+ run_rake_task(:migration_fix_15_11)
+ fixed_table = db.execute('SELECT version FROM schema_migrations').pluck('version')
+ run_rake_task(:migration_fix_15_11)
+ test_fixed_table = db.execute('SELECT version FROM schema_migrations').pluck('version')
+ expect(fixed_table).to match_array test_fixed_table
+ end
+ end
+ end
+end