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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2024-01-17 15:09:14 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2024-01-17 15:09:14 +0300
commit14c3ebc6364f7d5eb31cbf2e66a79ec574e88b70 (patch)
treeb05db97dc0a40721e3f99b70454d309197615428
parentdb1b40c0ae61a0b647c114b22c990419de05de7a (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/test-on-gdk/main.gitlab-ci.yml5
-rw-r--r--CHANGELOG.md484
-rw-r--r--app/assets/javascripts/ml/model_registry/components/model_row.vue2
-rw-r--r--app/assets/javascripts/observability/client.js2
-rw-r--r--app/assets/javascripts/organizations/groups_and_projects/components/app.vue28
-rw-r--r--app/assets/javascripts/organizations/groups_and_projects/constants.js2
-rw-r--r--app/assets/javascripts/releases/components/releases_sort.vue26
-rw-r--r--app/assets/javascripts/releases/constants.js8
-rw-r--r--app/assets/javascripts/work_items/components/shared/work_item_sidebar_dropdown_widget_with_edit.vue8
-rw-r--r--app/assets/javascripts/work_items/components/work_item_milestone_with_edit.vue2
-rw-r--r--app/controllers/import/bulk_imports_controller.rb5
-rw-r--r--app/controllers/import/gitea_controller.rb5
-rw-r--r--app/controllers/invites_controller.rb2
-rw-r--r--app/finders/ci/runners_finder.rb11
-rw-r--r--app/finders/personal_access_tokens_finder.rb1
-rw-r--r--app/graphql/resolvers/ci/runners_resolver.rb6
-rw-r--r--app/models/concerns/has_user_type.rb4
-rw-r--r--app/models/group.rb6
-rw-r--r--app/models/member.rb2
-rw-r--r--app/models/namespaces/user_namespace.rb2
-rw-r--r--app/models/project_authorization.rb2
-rw-r--r--app/models/project_team.rb2
-rw-r--r--app/models/route.rb38
-rw-r--r--app/services/groups/transfer_service.rb2
-rw-r--r--app/services/projects/import_service.rb5
-rw-r--r--app/services/projects/update_remote_mirror_service.rb6
-rw-r--r--app/validators/addressable_url_validator.rb12
-rw-r--r--app/views/devise/shared/_footer.html.haml2
-rw-r--r--app/views/groups/group_members/index.html.haml1
-rw-r--r--app/views/shared/integrations/gitlab_slack_application/_slack_integration_form.html.haml2
-rw-r--r--app/workers/bulk_imports/pipeline_worker.rb4
-rw-r--r--app/workers/integrations/irker_worker.rb5
-rw-r--r--config/feature_flags/development/bulk_import_limit_concurrent_batches.yml8
-rw-r--r--config/feature_flags/development/compare_project_authorization_linear_cte.yml8
-rw-r--r--config/feature_flags/development/linear_project_authorization.yml8
-rw-r--r--config/feature_flags/gitlab_com_derisk/batch_route_updates.yml9
-rw-r--r--db/docs/container_expiration_policies.yml2
-rw-r--r--db/docs/container_registry_data_repair_details.yml10
-rw-r--r--db/docs/container_registry_protection_rules.yml10
-rw-r--r--db/docs/container_repositories.yml13
-rw-r--r--doc/administration/geo/disaster_recovery/background_verification.md5
-rw-r--r--doc/administration/gitaly/index.md2
-rw-r--r--doc/administration/gitaly/praefect.md6
-rw-r--r--doc/administration/gitaly/troubleshooting.md361
-rw-r--r--doc/administration/gitaly/troubleshooting_gitaly_cluster.md312
-rw-r--r--doc/administration/server_hooks.md2
-rw-r--r--doc/api/graphql/reference/index.md3
-rw-r--r--doc/architecture/blueprints/google_artifact_registry_integration/backend.md10
-rw-r--r--doc/security/unlock_user.md2
-rw-r--r--doc/update/versions/gitlab_15_changes.md2
-rw-r--r--doc/user/project/integrations/gitlab_slack_app_troubleshooting.md4
-rw-r--r--doc/user/project/integrations/gitlab_slack_application.md133
-rw-r--r--doc/user/project/integrations/slack_slash_commands.md2
-rw-r--r--lib/gitlab/cleanup/personal_access_tokens.rb15
-rw-r--r--lib/gitlab/hook_data/project_builder.rb4
-rw-r--r--lib/gitlab/project_authorizations.rb68
-rw-r--r--lib/tasks/gitlab/seed/group_seed.rake2
-rw-r--r--locale/gitlab.pot16
-rw-r--r--qa/qa/page/merge_request/show.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb2
-rw-r--r--spec/controllers/groups/group_members_controller_spec.rb10
-rw-r--r--spec/controllers/import/gitea_controller_spec.rb4
-rw-r--r--spec/features/groups/members/leave_group_spec.rb8
-rw-r--r--spec/features/groups/members/manage_members_spec.rb2
-rw-r--r--spec/features/invites_spec.rb4
-rw-r--r--spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb2
-rw-r--r--spec/features/projects/releases/user_views_releases_spec.rb4
-rw-r--r--spec/finders/ci/runners_finder_spec.rb20
-rw-r--r--spec/frontend/ml/model_registry/components/model_row_spec.js2
-rw-r--r--spec/frontend/observability/client_spec.js7
-rw-r--r--spec/frontend/organizations/groups_and_projects/components/app_spec.js20
-rw-r--r--spec/frontend/releases/components/releases_sort_spec.js58
-rw-r--r--spec/frontend/work_items/components/work_item_milestone_with_edit_spec.js16
-rw-r--r--spec/graphql/resolvers/ci/runners_resolver_spec.rb2
-rw-r--r--spec/lib/gitlab/project_authorizations_spec.rb599
-rw-r--r--spec/models/ci/runner_spec.rb17
-rw-r--r--spec/models/group_spec.rb11
-rw-r--r--spec/models/project_team_spec.rb3
-rw-r--r--spec/models/route_spec.rb16
-rw-r--r--spec/services/groups/participants_service_spec.rb3
-rw-r--r--spec/services/groups/transfer_service_spec.rb8
-rw-r--r--spec/services/projects/import_service_spec.rb25
-rw-r--r--spec/services/projects/participants_service_spec.rb2
-rw-r--r--spec/services/projects/update_remote_mirror_service_spec.rb2
-rw-r--r--spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb8
-rw-r--r--spec/validators/addressable_url_validator_spec.rb4
-rw-r--r--spec/workers/bulk_imports/pipeline_worker_spec.rb37
-rw-r--r--vendor/project_templates/typo3_distribution.tar.gzbin77413 -> 79645 bytes
89 files changed, 1486 insertions, 1123 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d2f1fc8c2ff..4da524df878 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -183,7 +183,7 @@ variables:
CI_FETCH_REPO_GIT_STRATEGY: "none"
DEBIAN_VERSION: "bullseye"
UBI_VERSION: "8.6"
- CHROME_VERSION: "119"
+ CHROME_VERSION: "120"
DOCKER_VERSION: "24.0.5"
RUBYGEMS_VERSION: "3.4"
BUNDLER_VERSION: "2.5"
diff --git a/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml b/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml
index 5efe66d9b47..58f34b77d0c 100644
--- a/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml
+++ b/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml
@@ -206,6 +206,11 @@ gdk-qa-non-blocking:
QA_RUN_TYPE: gdk-qa-non-blocking
parallel: 5
allow_failure: true
+ artifacts:
+ paths:
+ - log
+ reports:
+ dotenv: ""
rules:
# run tests on master pipelines to collect metrics and move tests to `blocking` job until `non-blocking` job
# is removed entirely
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e2a525edbdb..8a38565bf25 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,490 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 16.8.0 (2024-01-17)
+
+### Added (113 changes)
+
+- [Enable security_policies_policy_scope by default](gitlab-org/gitlab@f79b154180c1e5fdb240e02f3b593b4865b42d4e) ([merge request](gitlab-org/gitlab!141766)) **GitLab Enterprise Edition**
+- [Enable compliance framework report by default](gitlab-org/gitlab@60e01b758a57e44ab89c9ae37f71e6da2ee6bd72) ([merge request](gitlab-org/gitlab!140825)) **GitLab Enterprise Edition**
+- [Improve issue weight system notes](gitlab-org/gitlab@dc18d16118f5a617e7af004f49d7de9393016dfc) ([merge request](gitlab-org/gitlab!141479)) **GitLab Enterprise Edition**
+- [Release the Maven dependency proxy](gitlab-org/gitlab@aa18d864fb03734eb8de24c0b259b2b7d4da7015) ([merge request](gitlab-org/gitlab!141600))
+- [Make delete members API rate limit configurable](gitlab-org/gitlab@18f63149c87f8dac86369a4d8abb60eda0f60eec) ([merge request](gitlab-org/gitlab!140633))
+- [Adds support for mlflow experiment search](gitlab-org/gitlab@f4b5d7db108885885752afc84d8356c0c5e106b7) ([merge request](gitlab-org/gitlab!141428))
+- [Adds ML Agent and AgentVersion models](gitlab-org/gitlab@6e27278848405306d1d1ec597c5fbe6312144442) ([merge request](gitlab-org/gitlab!141356)) **GitLab Enterprise Edition**
+- [Add code suggestions available to user graphql type](gitlab-org/gitlab@71a210d879da13472050cacdc2b4ef1b46123a6f) ([merge request](gitlab-org/gitlab!141617)) **GitLab Enterprise Edition**
+- [API option for returning top level namespaces only](gitlab-org/gitlab@7cb19c35853e4ba599d9abcfb3702e167a307697) ([merge request](gitlab-org/gitlab!141311))
+- [Protected packages: Display busy table with loading icon](gitlab-org/gitlab@4fd0e5a3885bb6f830fa70cef02cc72776c48d89) by @gerardo-navarro ([merge request](gitlab-org/gitlab!141370))
+- [Add sorting to member roles GraphQL query](gitlab-org/gitlab@d3cc881499dcc51f9be3b9a16c8c34e59830774e) ([merge request](gitlab-org/gitlab!141405)) **GitLab Enterprise Edition**
+- [Log audit events when updating and deleting member roles](gitlab-org/gitlab@5eb6f94b8282c9511533532ef3b236365ee2cb26) ([merge request](gitlab-org/gitlab!141630)) **GitLab Enterprise Edition**
+- [Add partition_id to Ci::PipelineConfig](gitlab-org/gitlab@f2ddcb34d0a18a9e6969e824eaeed259ac2c5da0) ([merge request](gitlab-org/gitlab!141461))
+- [Add Duo Chat access check to GraphQL API](gitlab-org/gitlab@57aac43b27baf1824787dbf38fa6d76040633328) ([merge request](gitlab-org/gitlab!141389))
+- [Backfill zoekt_enabled_namespaces and zoekt_indices](gitlab-org/gitlab@d4a7c607cf66ecd6940a2998965e1b472a2fe573) ([merge request](gitlab-org/gitlab!140252)) **GitLab Enterprise Edition**
+- [Add description field for Ci::InstanceVariable and InheritedCiVariable](gitlab-org/gitlab@37cbc8035c56a9927ca69137ee332d2071110db8) ([merge request](gitlab-org/gitlab!140549))
+- [Add partition_id to Ci::PipelineArtifact](gitlab-org/gitlab@c3ac0da2088f5e2a5b459ae7aa62375329ea3041) ([merge request](gitlab-org/gitlab!141345))
+- [Add partition_id to Ci::PipelineMetadata](gitlab-org/gitlab@171b7fa93f8403e93ba6c669bd903eba959edb14) ([merge request](gitlab-org/gitlab!141078))
+- [Remove manage_project_access_tokens FF](gitlab-org/gitlab@96c3aaf636c187f6b3999ece8693c0fefadf3180) ([merge request](gitlab-org/gitlab!141294)) **GitLab Enterprise Edition**
+- [Ensure backfill of default branch protection setting](gitlab-org/gitlab@d01dfa4a3b40dcf3fe1f2dbc6f33b81e3716d008) ([merge request](gitlab-org/gitlab!141012))
+- [Group by OWASP Top 10](gitlab-org/gitlab@54e2dfdc35b77c7ec501ad3ebcaa8ac13aff3b98) ([merge request](gitlab-org/gitlab!141149)) **GitLab Enterprise Edition**
+- [Allow User to be specified for a CI Image or Service](gitlab-org/gitlab@f3ec5bf2329d02f526dfdfa5460b0bb093a29b6a) by @ar-mali ([merge request](gitlab-org/gitlab!137907))
+- [Add index project_id, component_version_id and id](gitlab-org/gitlab@fdad489b0991b72f19206abc7b0768337add2b58) ([merge request](gitlab-org/gitlab!141400)) **GitLab Enterprise Edition**
+- [Add support for inapplicable task items in RTE](gitlab-org/gitlab@fbd1f1fa6aa1f568c6a11f569b86bee8ab7466b1) ([merge request](gitlab-org/gitlab!141303))
+- [Remove ff cache_control_headers_for_openid_jwks](gitlab-org/gitlab@3365b71f0e3b3a391d133639c057414187e6c7ab) ([merge request](gitlab-org/gitlab!141305))
+- [Added gitlab_tags helper to MLflow API](gitlab-org/gitlab@d4fa6558fbd0e72bfd309442598df38682e6f682) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139706))
+- [Add GCP Secret Manager CI integration](gitlab-org/gitlab@0daa46523566d2ee20dac7d76a46a611ad546697) ([merge request](gitlab-org/gitlab!141460)) **GitLab Enterprise Edition**
+- [Added tests to guardrail missing scopes](gitlab-org/gitlab@99e9e272b682303605c51960a82535096bac45a9) ([merge request](gitlab-org/gitlab!138307))
+- [Release Pipeline execution polices as an experiment](gitlab-org/gitlab@f3e708bb3d6f7b9f796e9a89b61622518699051a) ([merge request](gitlab-org/gitlab!139771)) **GitLab Enterprise Edition**
+- [Add ability to admin_terraform_state to custom roles](gitlab-org/gitlab@52ebf3e509c9ef139df04caeabaae1f551da71c2) ([merge request](gitlab-org/gitlab!140759)) **GitLab Enterprise Edition**
+- [Add support for rich text editor in comment templates](gitlab-org/gitlab@5dfc400951b6449e1116188459a397da78eb16e3) ([merge request](gitlab-org/gitlab!141316))
+- [Add rich text editor in iterations](gitlab-org/gitlab@b6bf098d4eb307e1679a475e9318cb69af9bf8df) ([merge request](gitlab-org/gitlab!141314)) **GitLab Enterprise Edition**
+- [Add owasp_top_10 filter to VulnerabilitySeverityCount GraphQL API](gitlab-org/gitlab@bc1ad3a30a970932243ebac8472bd7b481c9e8cc) ([merge request](gitlab-org/gitlab!140205)) **GitLab Enterprise Edition**
+- [Add pages project settings API](gitlab-org/gitlab@52b254913a45fece3d21db2ff3078d2aaa8685cd) ([merge request](gitlab-org/gitlab!140895))
+- [Add mutation to update color](gitlab-org/gitlab@0039d6d6ea9156d9c55690b2d5277fa500b7b9ce) ([merge request](gitlab-org/gitlab!140847)) **GitLab Enterprise Edition**
+- [Expose epic-issue permissions in GraphQL](gitlab-org/gitlab@a69106709f6a2dd5be958f9574b1323d7bfe9d73) ([merge request](gitlab-org/gitlab!141351))
+- [Add support for table alignment in RTE](gitlab-org/gitlab@11e4f7b7d05886dfe35e738963a7a4b0b0d86192) ([merge request](gitlab-org/gitlab!141249))
+- [Add Your resources tab to CI/CD Catalog](gitlab-org/gitlab@c508c9beb2d9aa9475806fa96823edfc727d0b63) ([merge request](gitlab-org/gitlab!138388))
+- [Wrap the serched text with double quotes when exact_search is passed](gitlab-org/gitlab@16d0c0814d3a115085bdd8aed38843f0cde99829) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/140346)) **GitLab Enterprise Edition**
+- [Add documentation for migration helpers](gitlab-org/gitlab@27d11987825fc84582d038b4ed0f7356e51134d0) ([merge request](gitlab-org/gitlab!140046)) **GitLab Enterprise Edition**
+- [Enable ci_data_ingestion_to_click_house by default](gitlab-org/gitlab@c981c43c2b37b961abc3e6cb3d3bd31c488d5e45) ([merge request](gitlab-org/gitlab!141238)) **GitLab Enterprise Edition**
+- [Added initial Diffblue Cover integration](gitlab-org/gitlab@a925c2f291507c63f4e5f1fccb02159dca1bc219) by @roxspring ([merge request](gitlab-org/gitlab!134437))
+- [Redefine referenced FK ci_job_artifacts for self managed](gitlab-org/gitlab@c28a2116fa9641811ef451396efe021f8c70f63f) ([merge request](gitlab-org/gitlab!141218))
+- [Send Arkose Data Exchange payload on signup challenge initialization](gitlab-org/gitlab@f80056ff1e087f6ef35bc78f279a3594dabf7c70) ([merge request](gitlab-org/gitlab!139070)) **GitLab Enterprise Edition**
+- [Add system_id param to GET runners/:id/jobs endpoint](gitlab-org/gitlab@75b287e451aaea061369c283d1d38d552363431b) ([merge request](gitlab-org/gitlab!140667))
+- [Use new GraphQL client to paginate deploy keys](gitlab-org/gitlab@5965d1b71386079b74d98bb3d4dbf0b0ce1cf842) ([merge request](gitlab-org/gitlab!139569))
+- [feat: Protected packages: Project settings ui package protection rules](gitlab-org/gitlab@66e0f67ca56ca216600e82df57d03e793013a391) by @gerardo-navarro ([merge request](gitlab-org/gitlab!140008))
+- [Replace clickhouse_ci_analytics FF with database config check](gitlab-org/gitlab@687352cfddf8df959efe6e8c1814df5ecc4b4636) ([merge request](gitlab-org/gitlab!140890))
+- [Create namespace descendants table](gitlab-org/gitlab@352f692cad7fe8c59409a8fcdc4756589722d847) ([merge request](gitlab-org/gitlab!140735))
+- [Add support for global HTTP TLS client cert](gitlab-org/gitlab@5ae8a6f85ea92fff615a34d0cbdeaad72fd60a59) ([merge request](gitlab-org/gitlab!140263))
+- [Migrate config_version for non-terminated workspaces](gitlab-org/gitlab@fe4f885edbf3e3a10923d643ace462a87da737ae) ([merge request](gitlab-org/gitlab!140972)) **GitLab Enterprise Edition**
+- [Hard limit daily phone verification transactions](gitlab-org/gitlab@770104162f8f537fa3e69529a380eeeb65573ce2) ([merge request](gitlab-org/gitlab!138627)) **GitLab Enterprise Edition**
+- [Add Experiment badge and popover](gitlab-org/gitlab@35b94980292f18d666e16e01d8e938258ce7bfee) ([merge request](gitlab-org/gitlab!139702)) **GitLab Enterprise Edition**
+- [Add WorkItems Rolledup Dates widget](gitlab-org/gitlab@734dde3e9155a01a360ef27fb1c9b547174e0092) ([merge request](gitlab-org/gitlab!139418))
+- [Finalize BackfillPartitionIdCiPipelineChatData](gitlab-org/gitlab@a1ddb08e29b56086b91a91c711f7dc1ea8812ded) ([merge request](gitlab-org/gitlab!140969))
+- [Validate referenced FK constraints ci_job_artifacts](gitlab-org/gitlab@6f8ef3d6453167bb2226da62abee9bb46934b9b0) ([merge request](gitlab-org/gitlab!140960))
+- [Add source_xid attribute to the ErrorTracking](gitlab-org/gitlab@2e850910c7be1f4c206115e8c23c61c6b976189b) ([merge request](gitlab-org/gitlab!140948)) **GitLab Enterprise Edition**
+- [Add ci_restrict_pipeline_cancellation_role to update project api](gitlab-org/gitlab@790d9aa2bb5873e0d7276ecdcb4d9e2f24a1d858) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139585)) **GitLab Enterprise Edition**
+- [Support fetching versioned readme from GQL ciCatalogResource endpoint](gitlab-org/gitlab@a5d9abf2459146b59a043b553dfb008f6e41236d) ([merge request](gitlab-org/gitlab!139983))
+- [workhorse: Support generating configuration via external command](gitlab-org/gitlab@4b5d67a17a1f1ab33b671df7314b90dfa73aa398) ([merge request](gitlab-org/gitlab!140898))
+- [Add setting to enforce 2FA for admins](gitlab-org/gitlab@e7ba0f66ad5c735ed50129ad8ccf9c7127825023) ([merge request](gitlab-org/gitlab!137911))
+- [Add color widget to work items](gitlab-org/gitlab@93abac0543222f84661517739005bb130d6c2cbb) ([merge request](gitlab-org/gitlab!140331)) **GitLab Enterprise Edition**
+- [Add GraphQL to list all organizations in an instance for admin area](gitlab-org/gitlab@1e008496d283b7018beb482f8f270a62c3ecb8b0) ([merge request](gitlab-org/gitlab!140552))
+- [Cleanup truncate_ci_merge_request_description FF](gitlab-org/gitlab@6c27289930abca271769eccb934416c8450a28b9) ([merge request](gitlab-org/gitlab!140201))
+- [Add migration to add_work_item_type_id to issues index](gitlab-org/gitlab@f3196690034c1c7ba6247e1b2560c9d2aff31772) ([merge request](gitlab-org/gitlab!139079)) **GitLab Enterprise Edition**
+- [Add support for updating member_role permissions](gitlab-org/gitlab@d6d9cd97d229cc02c52ad7f799ef06eb0bed6692) ([merge request](gitlab-org/gitlab!140581)) **GitLab Enterprise Edition**
+- [Change data source for project level dependencies](gitlab-org/gitlab@51f4f2a88fd44defc3f6b3ce635c25a356201f05) ([merge request](gitlab-org/gitlab!139686)) **GitLab Enterprise Edition**
+- [Remove slash_commands_file_content flag](gitlab-org/gitlab@88991216f124dd45457a04b7e7f1836d83cdcc76) ([merge request](gitlab-org/gitlab!140795)) **GitLab Enterprise Edition**
+- [Enable SAML group sync for customizable roles](gitlab-org/gitlab@aedd8807232aec9fc5fac16dd196a1af11502b10) ([merge request](gitlab-org/gitlab!140573)) **GitLab Enterprise Edition**
+- [Add migration to add_work_item_type_id to issues index](gitlab-org/gitlab@372567f1e63f6ffcb1cc3161a4400aa2c458bf70) ([merge request](gitlab-org/gitlab!138299)) **GitLab Enterprise Edition**
+- [Add Harbor to integrations docs](gitlab-org/gitlab@531dd3932911b89baee622620c56ada62f3a7f61) ([merge request](gitlab-org/gitlab!140672))
+- [Schedule removal of invalid Vulnerabilities](gitlab-org/gitlab@575d9b0d51850bd33b55b36afc59a73679bbc568) ([merge request](gitlab-org/gitlab!140532))
+- [Add online and offline dashboard panels](gitlab-org/gitlab@017a8535bb16dbeea00b6fca239b90d26836ed55) ([merge request](gitlab-org/gitlab!140138)) **GitLab Enterprise Edition**
+- [Add CI/CD Catalog alert to releases page](gitlab-org/gitlab@a3c5948b5d1f34fa09a2f5092ac7e77ad0841d63) ([merge request](gitlab-org/gitlab!140691))
+- [Add pagination to compliance framework report](gitlab-org/gitlab@1353ce1731cda01cae0d003d5f5fda3f37f99b10) ([merge request](gitlab-org/gitlab!139743)) **GitLab Enterprise Edition**
+- [Adding Model Version Metadata to MLflow](gitlab-org/gitlab@05da217c7adbf9edd75dba2a7d94f5ef5bda5556) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139975))
+- [Add Manage group access tokens custom permission](gitlab-org/gitlab@093b552432fa5e49fdee828f6ac8d182a14e7ce4) ([merge request](gitlab-org/gitlab!140115)) **GitLab Enterprise Edition**
+- [Add graphql query to list policies for compliance framework](gitlab-org/gitlab@19bc5025f775bf689cbd3294b6f32fca8ab9dca6) ([merge request](gitlab-org/gitlab!136641)) **GitLab Enterprise Edition**
+- [Add Google Play to integrations docs](gitlab-org/gitlab@ada2421849b8779ebae353c78342d7a6f9532819) ([merge request](gitlab-org/gitlab!140563))
+- [Add support for cancelling drag on `Esc`](gitlab-org/gitlab@f74a573db7a7ecc382203ef38ee82db8ae8e07eb) ([merge request](gitlab-org/gitlab!140619))
+- [Add organization specification for group creation](gitlab-org/gitlab@6f9b46a9a4ee7878da91ef9c4235234f95d7a400) ([merge request](gitlab-org/gitlab!140472))
+- [Add a setting to allow/disallow duplicate Terraform modules](gitlab-org/gitlab@c09fadea25f918fb52b98921835415c21f18a897) ([merge request](gitlab-org/gitlab!139161))
+- [Add referrers to container repository tags in GraphQL API](gitlab-org/gitlab@befbd09add9b4a2e9071b9c92f79403f0e9e090e) ([merge request](gitlab-org/gitlab!138588))
+- [Emit event when a release is published](gitlab-org/gitlab@853af39e669370e90c86b30857fbc3e0aa144acf) by @oelmekki ([merge request](gitlab-org/gitlab!137253))
+- [Expose instance level custom roles](gitlab-org/gitlab@915153bbfd9fb930012dd34d2d4db127a639651c) ([merge request](gitlab-org/gitlab!137708)) **GitLab Enterprise Edition**
+- [Add new fields to GroupType](gitlab-org/gitlab@01d12e94d14646115826a84c8a4f4081e42d020b) ([merge request](gitlab-org/gitlab!139966))
+- [Add delete button to edit compliance framework page](gitlab-org/gitlab@68adf479f5393148689bbdb96d00a400c5468598) ([merge request](gitlab-org/gitlab!139723)) **GitLab Enterprise Edition**
+- [Add zoekt enabled namespace and indices](gitlab-org/gitlab@4d8fc7524be6ead4c2189f44d2c7d13ca70224df) ([merge request](gitlab-org/gitlab!138992)) **GitLab Enterprise Edition**
+- [Cache users from Bitbucket Server](gitlab-org/gitlab@4bc85597fcaf09ac5a4ff57a15b6e4e872632e1e) ([merge request](gitlab-org/gitlab!139221))
+- [Clean up BE for SecurityConfigurationController](gitlab-org/gitlab@9db7c4babceebbb98f8eb5e5d37ec6aaa002eb73) ([merge request](gitlab-org/gitlab!140325)) **GitLab Enterprise Edition**
+- [Add name and path as fields for version type](gitlab-org/gitlab@9427249a83b380bb536fb02078a6f7ea3682ac5f) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139772))
+- [Add feature toggle for security policies policy scope](gitlab-org/gitlab@88088a44b11ba88a81451254fd1c73444ff7bc6a) ([merge request](gitlab-org/gitlab!139959)) **GitLab Enterprise Edition**
+- [Cache users from Bitbucket Server](gitlab-org/gitlab@de92ed8f3f5a619f00303850b33e51a843b65af9) ([merge request](gitlab-org/gitlab!139775))
+- [Add discussion locked property to work item notes widget](gitlab-org/gitlab@5c133ecb10cba7c51421a161576bcb1f6ea1f02f) ([merge request](gitlab-org/gitlab!138793))
+- [Redefine referenced FK ci_job_artifacts](gitlab-org/gitlab@bb5473249fd61c8323018a1b6b1fcd6f035d006c) ([merge request](gitlab-org/gitlab!140187))
+- [Add partition_id to Ci::PipelineChatData](gitlab-org/gitlab@7d1890a9576715e7e22cd08b68543589b2f24395) ([merge request](gitlab-org/gitlab!139515))
+- [Add props field to SBOM component parser](gitlab-org/gitlab@c75baaf98ccaea7f04b24d886c01620186584864) ([merge request](gitlab-org/gitlab!140042))
+- [Add migration to add_work_item_type_id to issues index](gitlab-org/gitlab@c07001d1f32037ca3dcff1dfa6180a4273d0e965) ([merge request](gitlab-org/gitlab!138298)) **GitLab Enterprise Edition**
+- [Add organization specification for group creation](gitlab-org/gitlab@a95f2491015e7cded109decd17c5515bd1b62d19) ([merge request](gitlab-org/gitlab!139842))
+- [Add API for SBOM occurrences related-vulnerabilities](gitlab-org/gitlab@7cb132d498df2a56bade8c97716199e8e21f5f4a) ([merge request](gitlab-org/gitlab!137889)) **GitLab Enterprise Edition**
+- [Add feature toggle for security policies policy scope](gitlab-org/gitlab@6a95e2faa09c756f99117f442d1d1b67ef93b60f) ([merge request](gitlab-org/gitlab!139911)) **GitLab Enterprise Edition**
+- [Add Delete Project custom permission](gitlab-org/gitlab@3fb60c17be5d184e8fa97925edb0fc2f08d42de8) ([merge request](gitlab-org/gitlab!139696)) **GitLab Enterprise Edition**
+- [Adds CI minutes usage CSV export button](gitlab-org/gitlab@03d1edafcf3b5e44d0286c27825f9c3e94684ac5) ([merge request](gitlab-org/gitlab!139548)) **GitLab Enterprise Edition**
+- [Enhance Security configuration response with features](gitlab-org/gitlab@c5ad0b4a43e854669c0177c1ce51f1e8e50c7ff4) ([merge request](gitlab-org/gitlab!140183))
+- [Introduce verified_ca commit signature verification status](gitlab-org/gitlab@824e2e12e97469ccf998eca82825792c26eb262e) ([merge request](gitlab-org/gitlab!140082)) **GitLab Enterprise Edition**
+- [Add GraphQL fields to check if MR allows mutliple assignees/reviewers](gitlab-org/gitlab@1553ae8cf998561720a30030deae53e43b5623e8) ([merge request](gitlab-org/gitlab!139887))
+- [Add index to ci_job_artifacts referenced FK](gitlab-org/gitlab@19dc7b834802e40b5bfa8f05ddb978ccc33723d6) ([merge request](gitlab-org/gitlab!140045))
+- [Add issue_id to epics](gitlab-org/gitlab@441b41e533930f154b1735c16629cdf6f4d34ead) ([merge request](gitlab-org/gitlab!139788))
+- [Add support to search by work item links in token input](gitlab-org/gitlab@ba461a7c905caf6d97af21ed797541163673a2c5) ([merge request](gitlab-org/gitlab!135751))
+- [Adding new scope for_container_path for container protection rule](gitlab-org/gitlab@83035e5012e367388677ca7e2135b5b2b3fa3819) by @gerardo-navarro ([merge request](gitlab-org/gitlab!135969))
+- [Reference Terraform modules from a project](gitlab-org/gitlab@7d77be6ccc2eb0c890c14645961789493f033845) ([merge request](gitlab-org/gitlab!137809))
+- [Clear work item types reactive cache when importing restrictions](gitlab-org/gitlab@25fb92513d20f14c4a21a4773cb1c0bbe97b396c) ([merge request](gitlab-org/gitlab!138961))
+- [Add diff_by_file_hash merge request action](gitlab-org/gitlab@0dcbc736ab94a48cad482702f56a19c7bdb9b207) ([merge request](gitlab-org/gitlab!138712))
+
+### Fixed (103 changes)
+
+- [Fix migration error in sent_notifications migration](gitlab-org/gitlab@0b6c09587e64212c38d9dbdfcf40fb2a61f541ce) ([merge request](gitlab-org/gitlab!141783))
+- [Validate import collaborator scope](gitlab-org/gitlab@de8534e3edd463a84aa574800eb19f6a1c51c01f) ([merge request](gitlab-org/gitlab!141510))
+- [Fix display of selected timezone for cities with duplicated identifiers](gitlab-org/gitlab@8b8344972fde4c9202f1939d5f2882d8935e09e3) ([merge request](gitlab-org/gitlab!141522))
+- [Fix unresolved OpenApi references](gitlab-org/gitlab@04429efc5e3c33ec77f7d893a8edb7cf905fe17a) ([merge request](gitlab-org/gitlab!138922))
+- [Make chat_names table migration idempotent](gitlab-org/gitlab@53269865a2fe3d59de1b8eb6dde0cb57e7858b45) ([merge request](gitlab-org/gitlab!141703))
+- [Add conditional chaining for systemNoteMetadata](gitlab-org/gitlab@2f632f0a9f7dd286ea95912d34de4a3d5ebc92ed) ([merge request](gitlab-org/gitlab!140943))
+- [Truncate source_title & source_url when creating `BulkImports::Failure`](gitlab-org/gitlab@f36bf0d797ad3147bb7e77c8e9c6be4060b7ed28) ([merge request](gitlab-org/gitlab!141655))
+- [Fix error when security policy CI contains no jobs](gitlab-org/gitlab@92811c5415807b713c5f1c18c3f4dc762928d841) ([merge request](gitlab-org/gitlab!141520)) **GitLab Enterprise Edition**
+- [Fetch tag notes on release refresh](gitlab-org/gitlab@399c09b411bd962d6ecc4d2e776335db11d9385a) ([merge request](gitlab-org/gitlab!141260))
+- [Work items lists: Fix focus ring overflow issue](gitlab-org/gitlab@0216b3343533daee19ce7762e7f1df5e0cbdc2e1) ([merge request](gitlab-org/gitlab!141587))
+- [Return error message when there is unlinked security policy project](gitlab-org/gitlab@6d546f7c91b0e1aa354a6695140233d791de0351) ([merge request](gitlab-org/gitlab!140584)) **GitLab Enterprise Edition**
+- [Fix group milestone deletion](gitlab-org/gitlab@3424738891272dc5e42d39467fe675473359b30c) by @Taucher2003 ([merge request](gitlab-org/gitlab!141298))
+- [Remove next badge from logged out header](gitlab-org/gitlab@c7e201ef2ca82c6bb4dc30ff1bc0e0448ed8b0e6) ([merge request](gitlab-org/gitlab!141435))
+- [Update Flux sync status for bad config](gitlab-org/gitlab@0e7dc69ad34bba2a320f9daf8570898ea6465b88) ([merge request](gitlab-org/gitlab!141424))
+- [Package Metadata DB with v prefix](gitlab-org/gitlab@d3bda5635600e676a3492c19dede3f25f787db62) ([merge request](gitlab-org/gitlab!140435)) **GitLab Enterprise Edition**
+- [Fix preview button for instance templates](gitlab-org/gitlab@c201deda13b6d678694b1f9e1bb1eb949695d250) ([merge request](gitlab-org/gitlab!140788)) **GitLab Enterprise Edition**
+- [Fix broken state when undoing after uploading](gitlab-org/gitlab@73a7e1d73cbbafe9d84e3916cc5f792a7b71dc42) ([merge request](gitlab-org/gitlab!139021))
+- [Fix alignment issue with scan summary](gitlab-org/gitlab@98f5a8f357a8669c63e88402ece69586855b57e0) ([merge request](gitlab-org/gitlab!141234)) **GitLab Enterprise Edition**
+- [Fix broken source maps after quick actions](gitlab-org/gitlab@e0a1f24d7d814766211f2cf254d16d795920a4d4) ([merge request](gitlab-org/gitlab!141263))
+- [Align icon with text in Code Quality widget](gitlab-org/gitlab@231d0ba733c4b42f97955cf28bedd52c671d1a0e) ([merge request](gitlab-org/gitlab!141490))
+- [Fix wiki menus background color in darkmode](gitlab-org/gitlab@785715dc26f1d5a38f1c15e9fb23d605a0898ca0) by @lvckyapi ([merge request](gitlab-org/gitlab!141312))
+- [Breadcrumb: Remove extra whitespace when avatar is used](gitlab-org/gitlab@02ea34020f9b9955746df93b7216087c10a1ca6b) ([merge request](gitlab-org/gitlab!141387))
+- [Fix date for state change in vulnerability discussions](gitlab-org/gitlab@30be6cb56e9433eab2c6b1d4f82057b20b7e2f65) ([merge request](gitlab-org/gitlab!141454)) **GitLab Enterprise Edition**
+- [Show unsupported message for doc tool SM](gitlab-org/gitlab@dd303e52dfe3efda0f5bbebcf95f506eb3a7db91) ([merge request](gitlab-org/gitlab!141227)) **GitLab Enterprise Edition**
+- [Implement GCP/AWS orphan artifacts clean up task](gitlab-org/gitlab@41c8fa7f1e4de850346d212c5167295204796c77) ([merge request](gitlab-org/gitlab!139892))
+- [Show merge help text for failed pipelines](gitlab-org/gitlab@2229b93bca785bfe7e7e00aaafa2adbb795f4eca) ([merge request](gitlab-org/gitlab!141396))
+- [Fix Markdown not rendering in CI/CD catalog](gitlab-org/gitlab@3f1af81670bb2a15f81548797b3bc17a33eb20c8) ([merge request](gitlab-org/gitlab!141388))
+- [Fix "error on credentials page for PATs with deleted group/project"](gitlab-org/gitlab@c08db8d049355bd140beb30388593834c1a3a43e) ([merge request](gitlab-org/gitlab!140873)) **GitLab Enterprise Edition**
+- [Fix duplicated policy approval rules in rule details](gitlab-org/gitlab@59f781c1b605c0c197abfafb698a7f4aa8ef9cc7) ([merge request](gitlab-org/gitlab!141021)) **GitLab Enterprise Edition**
+- [Fix `Group#owned_by?` and `#has_user?` methods to handle nil](gitlab-org/gitlab@b824e61c9ff25f68aae479992df30140910a47f9) ([merge request](gitlab-org/gitlab!141276))
+- [Ignore pending access requests when calculating the highest group role](gitlab-org/gitlab@c25c7b794ca269a715b1a9b65269c1471d2e876d) ([merge request](gitlab-org/gitlab!141364))
+- [Update file size validation](gitlab-org/gitlab@56f4f58e6b4de301a4e12329852b359d0c8dbb91) ([merge request](gitlab-org/gitlab!140237))
+- [Fix error creating pipeline with external policy CI](gitlab-org/gitlab@351e41dce18ccef5a09e265344133541a3b3a225) ([merge request](gitlab-org/gitlab!141362)) **GitLab Enterprise Edition**
+- [Add uniqueness validation to topic](gitlab-org/gitlab@87aa5cd96466f80f3888f9767194d5d49a31d56b) ([merge request](gitlab-org/gitlab!141357))
+- [Add estimate system note on issuable creation](gitlab-org/gitlab@61a5a0bbf3e019ad74c0120f617bbc95a8640eb5) ([merge request](gitlab-org/gitlab!141192))
+- [Fix getting single custom role through graphQL](gitlab-org/gitlab@78cd832cdb13afd3d9ac56aa97683255b81c3b2e) ([merge request](gitlab-org/gitlab!140981)) **GitLab Enterprise Edition**
+- [Fix locations count](gitlab-org/gitlab@43c21ba9e03c42008de8d6757193d753e463aa7f) ([merge request](gitlab-org/gitlab!140727)) **GitLab Enterprise Edition**
+- [Open file link for new modal in new tab](gitlab-org/gitlab@3c6db267cb8c6464344957f08ca8e56159bffaf9) ([merge request](gitlab-org/gitlab!140546)) **GitLab Enterprise Edition**
+- [GraphQL doc update](gitlab-org/gitlab@8d3f18191e65cd564e491d11da0bea5f9a8606b2) ([merge request](gitlab-org/gitlab!141170)) **GitLab Enterprise Edition**
+- [Display error message when an existing stage name is used](gitlab-org/gitlab@abaf24a26c8bb542e93acb3389dbcf53f03eba3c) ([merge request](gitlab-org/gitlab!141062)) **GitLab Enterprise Edition**
+- [Sec Finding details: Fix double-hash for file loc](gitlab-org/gitlab@657cbe8195dde489b36d66bca025eec678889638) ([merge request](gitlab-org/gitlab!140975)) **GitLab Enterprise Edition**
+- [Fix path generation error for #switch](gitlab-org/gitlab@cedb9f2a0db5b77f1d0bc8b633dacb7588875cb5) ([merge request](gitlab-org/gitlab!141232))
+- [Pipline Mini Graph: Fix max length for item](gitlab-org/gitlab@452feb0ed2e0e7d79f1377c2f70e47e7bf993d35) ([merge request](gitlab-org/gitlab!141099))
+- [Issues list: Don't render empty closed badge](gitlab-org/gitlab@2688f2ad74d631544d1fd9150304313e3b4f1382) ([merge request](gitlab-org/gitlab!140320))
+- [Show inherited security policies when user has access to project only](gitlab-org/gitlab@a403c095bc4960b98056cce146f29753e435c224) ([merge request](gitlab-org/gitlab!140530)) **GitLab Enterprise Edition**
+- [Remove relative_url from markdown preview in RTE](gitlab-org/gitlab@5f655a0a7405f8ba296f225bfa048bf0aec5df78) ([merge request](gitlab-org/gitlab!141070))
+- [Make bundler-checksum work with Bundler v2.5.0 (part 2)](gitlab-org/gitlab@79a61126ea888cba87f44ca66c9ba5e57cdd822b) ([merge request](gitlab-org/gitlab!141069))
+- [Add spacing between account providers](gitlab-org/gitlab@0d18d66f90a2ecafb9df2a25b1c236745fa7c092) ([merge request](gitlab-org/gitlab!141038))
+- [Fix long session expiry for some requests](gitlab-org/gitlab@8c85364205ccb1f4602ab3543d10ff55295bd6cc) ([merge request](gitlab-org/gitlab!141020))
+- [Prevent unnecessary sessions in API requests](gitlab-org/gitlab@f9e48ac93c9e062382d9f61771ce26dcb0926b8c) ([merge request](gitlab-org/gitlab!141010))
+- [Provide `ref` to BlameData query](gitlab-org/gitlab@688953fcd90c1038d7266b7b6bf2a45e4fb4457f) ([merge request](gitlab-org/gitlab!140800))
+- [Fix the vulnerability statistic calculation logic](gitlab-org/gitlab@51417a5f0ec74bcd27c4943b8f1bd0ed5571ea3c) ([merge request](gitlab-org/gitlab!140711)) **GitLab Enterprise Edition**
+- [Show top-bar full width when right-sidebar is present](gitlab-org/gitlab@b413baa08ac6e0758d4d2cb1769e5b019279c961) ([merge request](gitlab-org/gitlab!140304))
+- [Right sidebar gutter toggle fix position](gitlab-org/gitlab@07cf17543225757a02a51e96826b801c5c919818) ([merge request](gitlab-org/gitlab!140308))
+- [Fix: Remember me cookie not set when bypassing](gitlab-org/gitlab@dbbe753ca506576f50a5d0382b333ba510022c03) by @gerardo-navarro ([merge request](gitlab-org/gitlab!138545))
+- [Fix TypeError for invalid package.json dependencies](gitlab-org/gitlab@934a3d69249620a2cfc3a4a7cce7efdb3144d4aa) ([merge request](gitlab-org/gitlab!140791))
+- [Fix NoMethodError for track event method](gitlab-org/gitlab@78af4ed67a519ddbc46c8ac049bfcac216bf5f42) ([merge request](gitlab-org/gitlab!140783))
+- [Clear runner heartbeat when the last manager is removed](gitlab-org/gitlab@554daf6a8f6833a1e38de6f1a58961057d62536c) ([merge request](gitlab-org/gitlab!140572))
+- [Fix file browser drag handle height](gitlab-org/gitlab@df24dd390c8ea32abbc95f2bb0b0a29f7057cafe) ([merge request](gitlab-org/gitlab!140732))
+- [Fix 500 error when anonymous user visits explore/catalog](gitlab-org/gitlab@ac40978f9e5e74086b48de885145bfdd89ecae06) ([merge request](gitlab-org/gitlab!140724))
+- [Add missing ci_sources_pipelines indexes for self-host](gitlab-org/gitlab@08f84359979e7dd60c05f598db0d34163ba8a05a) ([merge request](gitlab-org/gitlab!140697))
+- [Add the missing definition for Discord integration](gitlab-org/gitlab@c50d88bda1b5c3da516f62e4c3100f006fd8cda4) ([merge request](gitlab-org/gitlab!140671))
+- [Allow auditors to view job history of a runner](gitlab-org/gitlab@d2ea5e66dcf373c026fc086039242aad15d6d016) ([merge request](gitlab-org/gitlab!140618)) **GitLab Enterprise Edition**
+- [Make bundler-checksum work with bundler v2.5.0+](gitlab-org/gitlab@dc85634db01ce452a82f277895abdb3d17f844df) ([merge request](gitlab-org/gitlab!140599))
+- [Add sorting for the name column of the policies table](gitlab-org/gitlab@cf97cae9d5d88dad27532b7ca74979318921280e) by @vinod.kumar827 ([merge request](gitlab-org/gitlab!139341)) **GitLab Enterprise Edition**
+- [Use toast for preferences saved notification](gitlab-org/gitlab@27b30ee1a7f283b824276c0f58b100a995cabd69) ([merge request](gitlab-org/gitlab!139587))
+- [Fixed clicking global Duo Chat button after dismissed callout](gitlab-org/gitlab@936cc4a681c543e0915331bb786e149fbb7a532f) ([merge request](gitlab-org/gitlab!140551)) **GitLab Enterprise Edition**
+- [Add scheduled DAST scans to be executed by security policy bot](gitlab-org/gitlab@40b2acb9a01c7167771c70c318f5d94794709bc0) ([merge request](gitlab-org/gitlab!140525)) **GitLab Enterprise Edition**
+- [Fix Gradle publish failure in FIPS mode](gitlab-org/gitlab@6b09e9cee231e63705f46661587b9cc14a6da963) ([merge request](gitlab-org/gitlab!140499))
+- [Exclude artifact & package sizes when calculating project export limit](gitlab-org/gitlab@b800df7ebdd31ca964e51a433b3b851b6deb3866) ([merge request](gitlab-org/gitlab!140227))
+- [Add infinite scrolling to projects_dropdown](gitlab-org/gitlab@6981f5a459bbf2e74381ef4991369ab3de1cecf0) ([merge request](gitlab-org/gitlab!140185))
+- [Pipeline Sec: remove ext-link icons from alerts](gitlab-org/gitlab@aa0c97c7f7e0ae0b8e1d19f16c4c9416f1b7a165) ([merge request](gitlab-org/gitlab!140360)) **GitLab Enterprise Edition**
+- [Fixes VSA dropdowns when editing an existing stage](gitlab-org/gitlab@656078c2293b63636c1648752866fc930801e854) ([merge request](gitlab-org/gitlab!140171)) **GitLab Enterprise Edition**
+- [Update issuable assignment change email copy](gitlab-org/gitlab@6267be767bade5c09cec5effa231389e0568ff11) ([merge request](gitlab-org/gitlab!139296))
+- [Fix 500 error when not signed in](gitlab-org/gitlab@2efd4e1830eb8a2049e7ce2cf22c0fdbc110c6c9) ([merge request](gitlab-org/gitlab!140445)) **GitLab Enterprise Edition**
+- [Fix change_column_type_concurrently for migration v2](gitlab-org/gitlab@938723f349eacf9d6d343424e242b2ee905fff7d) ([merge request](gitlab-org/gitlab!139337))
+- [Avoid mapping by connected GitHub accounts during gitea import](gitlab-org/gitlab@a4f062774859bdf780c5be3c42f22efc5f93f7d9) ([merge request](gitlab-org/gitlab!140439))
+- [Fix missing page_bundles CSS for Jira issues](gitlab-org/gitlab@2f0c8e5c573940d2c3ea0874e7c9762ed0f3b4ce) ([merge request](gitlab-org/gitlab!140425)) **GitLab Enterprise Edition**
+- [Fix commit references being rendered inadvertently](gitlab-org/gitlab@f6b70ed4d5ce53d73b17e5ebfb8ae7a774d9a94a) ([merge request](gitlab-org/gitlab!140424))
+- [Fix conflicting MR link when MR created from fork](gitlab-org/gitlab@301445583852f2951eafee41795884d3fb690a76) by @zzaakiirr ([merge request](gitlab-org/gitlab!139789))
+- [Fix GitHub Import worker spread calculation](gitlab-org/gitlab@f3f3831aabc205fa971685e6995e491004b5d8f4) ([merge request](gitlab-org/gitlab!140283))
+- [Fix Zero shot prompt validation error](gitlab-org/gitlab@ba3d8abebbb33a3dd12adaf11cbb2f52a05a2935) ([merge request](gitlab-org/gitlab!140297)) **GitLab Enterprise Edition**
+- [Add label-for attributes](gitlab-org/gitlab@f4c68eafc6a277f50f7a484bdbf0e12e68743402) ([merge request](gitlab-org/gitlab!140338)) **GitLab Enterprise Edition**
+- [Escape unicode null characters before parsing the security report](gitlab-org/gitlab@2e61a808814c11810052a0bfbb07ea5a20822fa2) ([merge request](gitlab-org/gitlab!140103)) **GitLab Enterprise Edition**
+- [Fix browser navigation for vulnerability tabs](gitlab-org/gitlab@b225987832f4551c05f5ac88cabfed9e444fdeb8) ([merge request](gitlab-org/gitlab!139776)) **GitLab Enterprise Edition**
+- [Check if owner account exists](gitlab-org/gitlab@985d121b0f0fc1ed8742ac8a943b474f9a2144c4) ([merge request](gitlab-org/gitlab!140274))
+- [Fixed an incorrect parameter for deleting draft notes in the API](gitlab-org/gitlab@157cd395c6347ef2a3a32b897c92d5f02bca701a) ([merge request](gitlab-org/gitlab!140129))
+- [Do not run ElasticCommitIndexerWorker on secondary geo nodes](gitlab-org/gitlab@ab66b87d5e93674fc0b13431308ecf822d562b30) by @zzaakiirr ([merge request](gitlab-org/gitlab!139843)) **GitLab Enterprise Edition**
+- [Exclude archived projects from group project templates list](gitlab-org/gitlab@a1500d7cbd525ca1c6746704a16cb586c8524007) ([merge request](gitlab-org/gitlab!140084)) **GitLab Enterprise Edition**
+- [Ensure timestamps are set for manually created vulnerabilities](gitlab-org/gitlab@a722ac5b91d66a10d22100dd5ee6b90f5497bde5) ([merge request](gitlab-org/gitlab!140223)) **GitLab Enterprise Edition**
+- [Project overview mirrored message improvements](gitlab-org/gitlab@2615502e1e5d857663c8f5982b60ce2cdaa66eec) ([merge request](gitlab-org/gitlab!140207)) **GitLab Enterprise Edition**
+- [Use VulnerabilityReadsFinder for InstanceSecurityDashboard counts](gitlab-org/gitlab@abae6252d5dc31713eab92c15afe13fb97f35fb4) ([merge request](gitlab-org/gitlab!140099)) **GitLab Enterprise Edition**
+- [Project overivew: Add permission check for edit button](gitlab-org/gitlab@729c6dbc0973f82ddff3cf2b1fda4b99f7248962) ([merge request](gitlab-org/gitlab!139375))
+- [Ingest owasp_top_10 for multiple identifiers finding map](gitlab-org/gitlab@63e9a1df3b45ac9a6c0953481eae3b035584861b) ([merge request](gitlab-org/gitlab!140067)) **GitLab Enterprise Edition**
+- [Fix more badge in issuables lists](gitlab-org/gitlab@b217a98722baf6ef351c92aeb5a3ff2367ceff9e) ([merge request](gitlab-org/gitlab!140125))
+- [Fix alignment of buttons on readme only preference](gitlab-org/gitlab@76954164859b098bb922dae4479fc63a99936a5d) ([merge request](gitlab-org/gitlab!140112))
+- [Fix issues with Member Roles API](gitlab-org/gitlab@813f153c3186788cbcdf9ca357a16cd49dfc305f) ([merge request](gitlab-org/gitlab!140088)) **GitLab Enterprise Edition**
+- [Fix cluster reindexing document_count](gitlab-org/gitlab@6bfb959abbe88f574820d01f1bb546c596ed5777) ([merge request](gitlab-org/gitlab!140085)) **GitLab Enterprise Edition**
+- [Fix Advanced search dropdowns](gitlab-org/gitlab@fffa1320efdfdfef34a0ff8a5e7991539873ea46) ([merge request](gitlab-org/gitlab!139945))
+- [Skip calculating signature fingerprint for certificates](gitlab-org/gitlab@9df61a46a92a8216a5b811241a2401b9ce04aed9) ([merge request](gitlab-org/gitlab!139926))
+- [Ensure the approvals can not be changed after merge](gitlab-org/gitlab@f2edd555da6c5d874c62d33ec92454fbfaa883d6) ([merge request](gitlab-org/gitlab!138925))
+- [Allow assigning of guests to confidential issues](gitlab-org/gitlab@e89eb0ce6d6989ac12ac4778f856fbd6bc1bf7df) ([merge request](gitlab-org/gitlab!139500))
+- [Remove refresh_statistics_on_unlink_fork feature flag](gitlab-org/gitlab@19209f25c981274f14752c560118c603ffd932f8) ([merge request](gitlab-org/gitlab!139451))
+
+### Changed (128 changes)
+
+- [Refactor start_and_due_date to use callbacks](gitlab-org/gitlab@27705ad65570fdbb159fbdceaf51fd1d0f1ba475) by @imskr ([merge request](gitlab-org/gitlab!141727))
+- [Replace autodevops illustrations with devops-sm](gitlab-org/gitlab@b446879ac8c17253372cb9ed596bfeb77bc1aee7) ([merge request](gitlab-org/gitlab!141707))
+- [Show assignee and label shortcuts in tooltip](gitlab-org/gitlab@b5aa4ee1376e311ab199aad30b7caa44cdc4b3c2) ([merge request](gitlab-org/gitlab!141154))
+- [Migrate deprecated sorting-item vue component](gitlab-org/gitlab@e9ffaa6ba61fa381d5a21f5bfc8b75e07e708a93) ([merge request](gitlab-org/gitlab!141530)) **GitLab Enterprise Edition**
+- [Default enable group_analytics_dashboards feature flag](gitlab-org/gitlab@c8754fbb6a85ae7828d97cdf387c6d130eb80cdb) ([merge request](gitlab-org/gitlab!141453)) **GitLab Enterprise Edition**
+- [Enable security_policies_unenforceable_rules_notification by default](gitlab-org/gitlab@ab28e627af2282889ab14fa5ff7355c67d6364eb) ([merge request](gitlab-org/gitlab!141619)) **GitLab Enterprise Edition**
+- [Add `Cookie Preferences` button in the footer](gitlab-org/gitlab@11a0f85640244b1850780921987bfc92d4e07431) ([merge request](gitlab-org/gitlab!141475))
+- [Migrate deprecated sorting-item vue component](gitlab-org/gitlab@bc9343fb70cf54a3a6b2ce96988ac56d821ff598) ([merge request](gitlab-org/gitlab!141480)) **GitLab Enterprise Edition**
+- [Enable ff_require_saml_auth_to_approve by default](gitlab-org/gitlab@7bc47ba47391e56ea644fa64ea6edd3319859c9a) ([merge request](gitlab-org/gitlab!141594)) **GitLab Enterprise Edition**
+- [Add flag and disable Container Scanning CVS](gitlab-org/gitlab@71568a85541e27421aac8d019af2821b0b07833b) ([merge request](gitlab-org/gitlab!141023))
+- [Show edit issuable and wiki shortcut in tooltip](gitlab-org/gitlab@e09af9f3c383446d9501ca29199bd894f4b2d3e5) ([merge request](gitlab-org/gitlab!141526)) **GitLab Enterprise Edition**
+- [Scope epics internal_ids generation to `issues` usage](gitlab-org/gitlab@c2f0d3833ca3e53ffcaf94fb2743d6c4e3b0322e) ([merge request](gitlab-org/gitlab!139367))
+- [Add sbom_occurrence_properties table](gitlab-org/gitlab@97c28ade67ae982f83a2dea431500bee1f378eaa) ([merge request](gitlab-org/gitlab!140539))
+- [Add feedback banner to product analytics dashboards](gitlab-org/gitlab@f458bdbad83600803663d39e17047ac6ed86205e) ([merge request](gitlab-org/gitlab!140790)) **GitLab Enterprise Edition**
+- [System note tweaks](gitlab-org/gitlab@41addf4becfbdbcaf659ded8610b7d69b81aa866) ([merge request](gitlab-org/gitlab!141543))
+- [Update dependency auto-deploy-image to v2.76.1](gitlab-org/gitlab@4a4cb563c24893af2f5a7074572170e4cd6f7fa2) ([merge request](gitlab-org/gitlab!141541))
+- [Change order within admin appearance settings page by using the ABC](gitlab-org/gitlab@32134880df0e27b6b78fb40e3a9c4a429adb4519) by @bufferoverflow ([merge request](gitlab-org/gitlab!139049))
+- [Add keyboard shortcut to Web IDE dropdown option](gitlab-org/gitlab@9542966fa3a08e2c8549d588695488c35f8a14b8) ([merge request](gitlab-org/gitlab!140965))
+- [Store full include path for CI components](gitlab-org/gitlab@e997b1974fb0d77e192e5a0514a911966bbe101f) ([merge request](gitlab-org/gitlab!139122))
+- [Fix 500 error when Jira host is unreachable](gitlab-org/gitlab@17c14c23d1c2818ade6de35a4bb811a8b3604e7d) ([merge request](gitlab-org/gitlab!141363))
+- [This MR adds popover to experiment feature](gitlab-org/gitlab@2cb19343ff329894b408bbb7fe8d81639cd1f418) ([merge request](gitlab-org/gitlab!141268)) **GitLab Enterprise Edition**
+- [Change variable modal action button to save](gitlab-org/gitlab@f3bae78cf14524c1c97a706571ce1090ad1f7ed5) ([merge request](gitlab-org/gitlab!141290))
+- [Replace deprecated dropdown on new project page](gitlab-org/gitlab@6c605a9f53c15d72a5337421c594154916e9ab7b) by @daniel_magnus.bader ([merge request](gitlab-org/gitlab!139521))
+- [This MR fixes usage of reserved names](gitlab-org/gitlab@2b48daea9bd140c2b74a5a57160f760409874018) ([merge request](gitlab-org/gitlab!141439)) **GitLab Enterprise Edition**
+- [Enabling sast_reports_in_inline_diff flag by default in 16.8](gitlab-org/gitlab@51306b39bf2fed93f2f750f6007d19c19a297dcc) ([merge request](gitlab-org/gitlab!141247)) **GitLab Enterprise Edition**
+- [Change button alignment on variable drawer](gitlab-org/gitlab@1d92cc26c2eb0cc29af2efcce80e055845c55254) ([merge request](gitlab-org/gitlab!141455))
+- [Stop deleting merged MRs approval rules](gitlab-org/gitlab@c86ff3a48657b50f01874629ff8665710895cf5a) ([merge request](gitlab-org/gitlab!141036))
+- [Enabling audit_events_streaming_namespace_filter by default](gitlab-org/gitlab@2b3a1b85622f97644d2ccb4282f57178bd0e5eb9) ([merge request](gitlab-org/gitlab!141445)) **GitLab Enterprise Edition**
+- [Enable issues_completed_analytics_feature_flag feature flag by default](gitlab-org/gitlab@f39a3bc5bc2a8794acae788d44849feb10085603) ([merge request](gitlab-org/gitlab!141278)) **GitLab Enterprise Edition**
+- [Add waiting time between phone verification code sends](gitlab-org/gitlab@3f81ac7a2c37db2154685353b77591aea4eee125) ([merge request](gitlab-org/gitlab!137850)) **GitLab Enterprise Edition**
+- [Update GITLAB_PAGES_VERSION](gitlab-org/gitlab@83aba1d21593d77da3df93e8124e763055e8cfab) ([merge request](gitlab-org/gitlab!141384))
+- [Code suggestions: Update condition to check cut-off date](gitlab-org/gitlab@ac0aa97ef5c334fc4f84c4cabc1e2bf4ac964cda) ([merge request](gitlab-org/gitlab!138334))
+- [Standardize customizable permission type](gitlab-org/gitlab@f807189110630504c0121d874ee95c2d8546fac3) ([merge request](gitlab-org/gitlab!141296)) **GitLab Enterprise Edition**
+- [Add warning to group creation page to avoid using dot](gitlab-org/gitlab@32976c09262145059e3ec7723c0837931f8ad7ce) ([merge request](gitlab-org/gitlab!141243))
+- [Refactor description widget to use callbacks](gitlab-org/gitlab@de18913fb7f3274b5dcd4440ce3f47f121fb9e36) by @imskr ([merge request](gitlab-org/gitlab!140577))
+- [Show copy source branch shortcut in tooltip](gitlab-org/gitlab@29a85cd791182a13cce199219f1ff2eb5c3015fc) ([merge request](gitlab-org/gitlab!141119))
+- [Ensure dashboards change to 1 column mode at small sizes](gitlab-org/gitlab@b4284b232a522fc683b3fd5db46d98bc869ee5c0) ([merge request](gitlab-org/gitlab!141306)) **GitLab Enterprise Edition**
+- [Filter out banned users in Contribution Analytics](gitlab-org/gitlab@78fc222156a6f07356714ae3f2db369419f43071) ([merge request](gitlab-org/gitlab!140987)) **GitLab Enterprise Edition**
+- [Remove the commit count button](gitlab-org/gitlab@3cc3d014f867894a10abcbb8f0895678baf22233) ([merge request](gitlab-org/gitlab!140780))
+- [Move Cloud Seed files to cloud_seed namespace](gitlab-org/gitlab@2fbd205f31ff270e2021c56ffc393ae4a8fa7a31) ([merge request](gitlab-org/gitlab!141262))
+- [Update nio4r gem to v2.7.0](gitlab-org/gitlab@08a8a27d3ad35de716e33e0765e35dc74303a6e8) ([merge request](gitlab-org/gitlab!141219))
+- [This MR fixes component registration in tests](gitlab-org/gitlab@b4d93fa964fac4d87017afa85a0216cf65a64ed2) ([merge request](gitlab-org/gitlab!140930)) **GitLab Enterprise Edition**
+- [Improve tests for filtering admin runners by creator](gitlab-org/gitlab@3f43aba8e5cb70c6dbcd1d11c9e31bb7a360d6a1) by @zzaakiirr ([merge request](gitlab-org/gitlab!139361))
+- [Switch Zero Shot agent request traffic to AI Gateway](gitlab-org/gitlab@4844605bc6dafae1bc0d432106b1e51cda8a8c64) ([merge request](gitlab-org/gitlab!141209)) **GitLab Enterprise Edition**
+- [Make review emails easier to view on mobile](gitlab-org/gitlab@b951683c533bd3c53d278c4986cf88ca41a60fa4) ([merge request](gitlab-org/gitlab!141187))
+- [Current user todos widget service to use callbacks](gitlab-org/gitlab@a3e41129eac9c2e8c313252a23e271d2f945964a) by @imskr ([merge request](gitlab-org/gitlab!141186))
+- [Drop dependency on nokogiri for GitLab gems](gitlab-org/gitlab@89bbe66a18eb982cb281fd854cb98242940dccd8) ([merge request](gitlab-org/gitlab!141182))
+- [Use (merge) base pipelines as SRP comparison pipelines](gitlab-org/gitlab@ea7953ad62f1d21ca58111684f9daf30b4587e49) ([merge request](gitlab-org/gitlab!140348)) **GitLab Enterprise Edition**
+- [Remove pending_status_check_responses ff](gitlab-org/gitlab@e0a3e2ba01917aeb11a7a844ecf924d232cfbf9a) ([merge request](gitlab-org/gitlab!141159)) **GitLab Enterprise Edition**
+- [Remove timeout_status_check_responses ff](gitlab-org/gitlab@17424cdb025df0bcd7de3d839dd070a5a734b835) ([merge request](gitlab-org/gitlab!141152)) **GitLab Enterprise Edition**
+- [Increase the height of square and landscape logos](gitlab-org/gitlab@efe69349df66b21035d74df9c158df975da829c0) ([merge request](gitlab-org/gitlab!141137))
+- [This MR fixes component registration in tests](gitlab-org/gitlab@3cbf1092f733cc20208e6f470bc08f4c9b635f16) ([merge request](gitlab-org/gitlab!141009)) **GitLab Enterprise Edition**
+- [Project overview: Reorder more dropdown items](gitlab-org/gitlab@45273b598f69ae879b61b661034df51d74c76a04) ([merge request](gitlab-org/gitlab!140050))
+- [Remove extra space around preferences link in shortcuts modal](gitlab-org/gitlab@6c870e656a82eec43fc236548fc49e18ae899567) ([merge request](gitlab-org/gitlab!141084))
+- [Add migration to drop documents with old schema version](gitlab-org/gitlab@927c04c19fe4e60c505fe01618694345bebe3d27) ([merge request](gitlab-org/gitlab!140867)) **GitLab Enterprise Edition**
+- [Adds tooltip to clarify container image storage](gitlab-org/gitlab@9ea67aa74dfed6796e3c00767d49d973b662aca4) ([merge request](gitlab-org/gitlab!140643))
+- [Update uri gem to v0.13.0](gitlab-org/gitlab@915331b2e4db93b993cd3f83ee68052c57883b50) ([merge request](gitlab-org/gitlab!141053))
+- [This MR fixes component registration in tests](gitlab-org/gitlab@eb4f32270d307e99d754f94e5ca0dd1a842f00bc) ([merge request](gitlab-org/gitlab!140994)) **GitLab Enterprise Edition**
+- [This MR fixes component registration in tests](gitlab-org/gitlab@49e76eff1bc2d9de3e012aae52ab7a6d79a69889) ([merge request](gitlab-org/gitlab!141007)) **GitLab Enterprise Edition**
+- [Add `Dismissal Reason` to the vulnerability csv report](gitlab-org/gitlab@4034e2f3934868c072bde90874eab7216046d342) ([merge request](gitlab-org/gitlab!140664)) **GitLab Enterprise Edition**
+- [Improve accessibility in the two factor page](gitlab-org/gitlab@cfc72d2bb38b200ab6de9b35b5eae208136af21f) ([merge request](gitlab-org/gitlab!141029))
+- [Add icon to branch and tag](gitlab-org/gitlab@7786e42e315b714914bbe12289c9e8b329d16435) ([merge request](gitlab-org/gitlab!140217))
+- [Default ci_finished_builds timestamps to zero](gitlab-org/gitlab@5e854c80cbcd6e7f64d0c81f3c96246ec712ea85) ([merge request](gitlab-org/gitlab!140804))
+- [Remove feature flag package_metadata_advisory_sync](gitlab-org/gitlab@d7bd2ff95e7c4486f6ecbd45eec9dd157289e6dc) ([merge request](gitlab-org/gitlab!140166)) **GitLab Enterprise Edition**
+- [This MR adds pagination for toggle list](gitlab-org/gitlab@c384d2071120f62f7d37da189588d56b103fbe61) ([merge request](gitlab-org/gitlab!140485)) **GitLab Enterprise Edition**
+- [Remove validation of title_html and description_html](gitlab-org/gitlab@6e9270d90d0a670e988fc3ca42503202dd8360e6) ([merge request](gitlab-org/gitlab!140857)) **GitLab Enterprise Edition**
+- [Remove scan_result_policy_license_scanning_merge_base_pipeline flag](gitlab-org/gitlab@06fe12971fe808b162f508e58d7a9b518fdc7662) ([merge request](gitlab-org/gitlab!140854)) **GitLab Enterprise Edition**
+- [Add possibility to add new branch rules](gitlab-org/gitlab@3c1cee4dc72687f18e964456eef6f1f2b2506b41) ([merge request](gitlab-org/gitlab!140319))
+- [Add order and bump migration version](gitlab-org/gitlab@219c2b83829863b3a6d0afae429da1995d216ccb) ([merge request](gitlab-org/gitlab!140863)) **GitLab Enterprise Edition**
+- [Make value field resizable in CI Variables form](gitlab-org/gitlab@5ddf345cfb06fcff26b638431e67b419b9f9a6b0) ([merge request](gitlab-org/gitlab!140837))
+- [Replace epics issue_id foreign key to nullify on delete](gitlab-org/gitlab@137fbdfd58b2ff00ed8790bca126d7c57a912c56) ([merge request](gitlab-org/gitlab!140666))
+- [Add validations for bucket name for AWS](gitlab-org/gitlab@cacd199e632e6d16625732d21c93abbeb744c676) ([merge request](gitlab-org/gitlab!140779)) **GitLab Enterprise Edition**
+- [Synchronously validate `finding_id` FK on vulnerabilities](gitlab-org/gitlab@4b83fe02c431bd91a7d9618032264404f9cb5f4b) ([merge request](gitlab-org/gitlab!140775)) **GitLab Enterprise Edition**
+- [Return 401 token invalid form graphql](gitlab-org/gitlab@ccd8ba2f02ed931eeb5fb2750fc5c7fdbd937421) ([merge request](gitlab-org/gitlab!140761))
+- [Update dependency auto-deploy-image to v2.76.0](gitlab-org/gitlab@0c4bd26f836d3e99511e59817e825eca4d43d010) ([merge request](gitlab-org/gitlab!140744))
+- [Allow personal namespaces to use aggregated VSA](gitlab-org/gitlab@d6bcbdbc8cb31c854de132243976a4d0c275e774) ([merge request](gitlab-org/gitlab!138731)) **GitLab Enterprise Edition**
+- [Asynchronously validate `finding_id` foreign key on vulnerabilities](gitlab-org/gitlab@c42dbc0eda145d8f2c049ec4f9ef276cdde0b972) ([merge request](gitlab-org/gitlab!131979)) **GitLab Enterprise Edition**
+- [Add a prefix to CI Build tokens behind a feature flag](gitlab-org/gitlab@6100ae4f8947221438de3f668587841c2115437b) ([merge request](gitlab-org/gitlab!140159))
+- [Changed milestone burn chart to use segmented control](gitlab-org/gitlab@9a9c97d3074f36f2c37b8ed3ae205c2464a8b889) by @zillemarco ([merge request](gitlab-org/gitlab!139641))
+- [Add tooltip to move card button in boards](gitlab-org/gitlab@1ddb86df6f607824ef755c63b87758884f79c89e) ([merge request](gitlab-org/gitlab!140389))
+- [Remove `rules` from target branch rules name](gitlab-org/gitlab@08cc21206f6a29fcb200be9b130beec4090223e8) ([merge request](gitlab-org/gitlab!139738)) **GitLab Enterprise Edition**
+- [Add CI runner managers finder](gitlab-org/gitlab@955abe4b7ee5b8121dc4bf347c265aa5a0423f98) by @zzaakiirr ([merge request](gitlab-org/gitlab!137888))
+- [api: Expose `archived` field for CI jobs](gitlab-org/gitlab@5e374cdfebd99ab12d99464d6a40ddea400e3206) ([merge request](gitlab-org/gitlab!140285))
+- [Relocate admin mode switch from command palette to user menu](gitlab-org/gitlab@520287a553bd4997043e96f985516f60f89dd7c5) ([merge request](gitlab-org/gitlab!140254))
+- [Add published_at to ContainerRegistry::Tag](gitlab-org/gitlab@75b29e5338016f8f66c0201f032b963922e0bfe2) ([merge request](gitlab-org/gitlab!140188))
+- [Remove custom styling of tab elements](gitlab-org/gitlab@cf37a92c56efe306ff627e9b9185b72a5970dfeb) ([merge request](gitlab-org/gitlab!139956))
+- [Added control to limit users to create group/project](gitlab-org/gitlab@3652d4ad72f8308baaff757ec936404ec8c40ec8) ([merge request](gitlab-org/gitlab!134630))
+- [Remove btn-group class from all listbox helper](gitlab-org/gitlab@a1fd8d48e212951a631a61b9498eeda708ae7b2f) ([merge request](gitlab-org/gitlab!138575))
+- [Remove final instances of `group_icon`](gitlab-org/gitlab@3ddb701d3d0808abca3fc4d5771176320dccc0a3) by @yonghyun.jin13 ([merge request](gitlab-org/gitlab!139205))
+- [Move organization_users to gitlab_main_cell](gitlab-org/gitlab@733516319d7a599f491a816b53ff5d013540565c) ([merge request](gitlab-org/gitlab!140343))
+- [Add frontend for standards adherence export](gitlab-org/gitlab@efa504209dcde9f33db643d2c2a084d4dc07f0c0) ([merge request](gitlab-org/gitlab!138807)) **GitLab Enterprise Edition**
+- [This MR adds policy scope to a drawer](gitlab-org/gitlab@5a1b75b63de01ebb710ff1c3146646035fa94682) ([merge request](gitlab-org/gitlab!138720)) **GitLab Enterprise Edition**
+- [Save external_identifiers on ImportFailure for file import relations](gitlab-org/gitlab@82b0d0b5dc2fcf2585b05bf58a072455eb6e103e) ([merge request](gitlab-org/gitlab!139653))
+- [Add slug to topics](gitlab-org/gitlab@bce941042ea8d4cc5d0c33b4b645c158bb2dcb6e) by @zzaakiirr ([merge request](gitlab-org/gitlab!139269))
+- [Reset repository checksum before publishing an updated event](gitlab-org/gitlab@a891f53fbf2d527f2fa36c356d6664a037905e31) ([merge request](gitlab-org/gitlab!139282)) **GitLab Enterprise Edition**
+- [Added modifier for wild card count link](gitlab-org/gitlab@2b5951ac91756e751ceed6e47c7fa167187608c4) ([merge request](gitlab-org/gitlab!138302))
+- [Fixing jest spec violations for Vue.js v3 Migration](gitlab-org/gitlab@f3c02a09465d3717cf537f25133a1d10249d1421) ([merge request](gitlab-org/gitlab!135610))
+- [Use specific FullPathResolver descriptions](gitlab-org/gitlab@b4ae53260d798973ca189be99fb35f514663b8ff) by @ayushya0612 ([merge request](gitlab-org/gitlab!140120))
+- [Update description in CI/CD Variables settings](gitlab-org/gitlab@012757050062d3145c5e3773b53c2d0b21fe465f) ([merge request](gitlab-org/gitlab!140461))
+- [Send GitLab version and hostname during instance activation](gitlab-org/gitlab@89c7375ed69803cb09d8a12fd2bca95f51616090) ([merge request](gitlab-org/gitlab!140104)) **GitLab Enterprise Edition**
+- [Save phone verification record when the number relates to a banned user](gitlab-org/gitlab@9254c01f8ce4b4de3f6525add38da334bddae7e8) ([merge request](gitlab-org/gitlab!139083)) **GitLab Enterprise Edition**
+- [Add index for events to efficiently query user contributions](gitlab-org/gitlab@1f2a60c7420cf4a0d844d4d56dedf082bc094bcc) by @zzaakiirr ([merge request](gitlab-org/gitlab!139928))
+- [Set default vuln report filter to 'Still Detected'](gitlab-org/gitlab@c70d04a0eb355da494ffc64ba1dff34987d9cd37) ([merge request](gitlab-org/gitlab!137186)) **GitLab Enterprise Edition**
+- [Update dependency auto-deploy-image to v2.72.0](gitlab-org/gitlab@496da637158b7a9bdc088bbd265aad176e15f887) ([merge request](gitlab-org/gitlab!140351))
+- [Change i_code_review_create_mr metric to total counts](gitlab-org/gitlab@7fd2d70f1c98571e0243c130216e2877df3ca998) ([merge request](gitlab-org/gitlab!138030))
+- [Add a prefix to SCIM tokens behind a feature flag](gitlab-org/gitlab@f09de3db0ed92ce55c39a50dabf2125b9d0daa1f) ([merge request](gitlab-org/gitlab!139737)) **GitLab Enterprise Edition**
+- [Change telesign_intelligence feature flag type to ops](gitlab-org/gitlab@ee5cd032bc2ba7cfcfd291d71aec5f6b14e2de6c) ([merge request](gitlab-org/gitlab!140309)) **GitLab Enterprise Edition**
+- [Notes: Refactor CSS](gitlab-org/gitlab@33210e27caebe57bad3ecdde8caaa613581c4fda) ([merge request](gitlab-org/gitlab!140089))
+- [Analytics dashboards UI polish](gitlab-org/gitlab@55a73762fed682a3af8166c366c8e68d84af1303) ([merge request](gitlab-org/gitlab!139565)) **GitLab Enterprise Edition**
+- [Fix images not pasting in RTE](gitlab-org/gitlab@7f28622a4d3e40097aa37f32060056d5b9f80ec5) ([merge request](gitlab-org/gitlab!140298))
+- [Remove in_product_marketing_emails model and table](gitlab-org/gitlab@8bb4c2eb71afa0f18dc2dfe9f5d125bdf25d5e91) ([merge request](gitlab-org/gitlab!138835))
+- [Use plural form for packages & registries settings alerts](gitlab-org/gitlab@087137e6df2fd5573309b8c2d382ca8d830eb589) by @zzaakiirr ([merge request](gitlab-org/gitlab!139407))
+- [This MR updated yaml preview](gitlab-org/gitlab@c0e1070545824b07938318fee03fe0a4da62215f) ([merge request](gitlab-org/gitlab!140269)) **GitLab Enterprise Edition**
+- [Compare most recent SBOM pipeline for license approval policies](gitlab-org/gitlab@40ef1bbc8af023680ef10e6b0c07643c38e8eba7) ([merge request](gitlab-org/gitlab!136695)) **GitLab Enterprise Edition**
+- [Improve info on Free Public Namespaces](gitlab-org/gitlab@ebdd0bec38ccce203571f6d0145d19d7aad12713) ([merge request](gitlab-org/gitlab!138802)) **GitLab Enterprise Edition**
+- [Center the content of the login page](gitlab-org/gitlab@c7ff768cf2c2d2f0090dd8ce7baa47c025967ed0) ([merge request](gitlab-org/gitlab!140116))
+- [Add params and sorting to group users API](gitlab-org/gitlab@97bac7482e9781e81b7325bedc97dfd53c6864e9) ([merge request](gitlab-org/gitlab!140241)) **GitLab Enterprise Edition**
+- [Refactor code_suggestions_ga_non_owner_alert feature spec](gitlab-org/gitlab@df62b7db33c94573ee51f4ab44debc1a67dd50ae) ([merge request](gitlab-org/gitlab!140225)) **GitLab Enterprise Edition**
+- [Remove restyle_login_page feature flag](gitlab-org/gitlab@6c00fd1a3f62a73642be3564fa44ebbad9b62daa) ([merge request](gitlab-org/gitlab!139677))
+- [Remove feature flag ci_job_token_scope](gitlab-org/gitlab@4b5d3693307298f2491be4cc406313ce9540469a) ([merge request](gitlab-org/gitlab!139862))
+- [MR code button: Migrate to GlButton](gitlab-org/gitlab@c83969dfdcb3ce0238a97c05a1b38a534fb911a0) ([merge request](gitlab-org/gitlab!140181))
+- [Use /react as the primary command](gitlab-org/gitlab@58104079d6a45408e2e90cbfd083752de72782be) ([merge request](gitlab-org/gitlab!139504))
+- [Introduce a timeout when finding or creating a container repository](gitlab-org/gitlab@578edaa657a7f34a76254f1cc5ab01b58afcf57d) ([merge request](gitlab-org/gitlab!138616))
+- [Update dependency auto-deploy-image to v2.71.1](gitlab-org/gitlab@2fdaa3f040a7fd189957545e23e12458d6cf4f21) ([merge request](gitlab-org/gitlab!140157))
+- [Update users stats tables to use full width](gitlab-org/gitlab@1ee53cfaa78b078041048380c8d8b6ed0bccd0fc) ([merge request](gitlab-org/gitlab!139786))
+- [Refactor notifications service](gitlab-org/gitlab@5b7549464cf33a2608ef79eedff6bbe8c38bcaa2) by @imskr ([merge request](gitlab-org/gitlab!140004))
+- [Update feedback banner](gitlab-org/gitlab@5b8f24f8c25611090ceb6e62cfcd55394938e5b0) by @davidwatts111 ([merge request](gitlab-org/gitlab!139879))
+- [Updating policy ui](gitlab-org/gitlab@6e182015b42a8b8ff98d74e980aed1c21ee43280) by @davidwatts111 ([merge request](gitlab-org/gitlab!139489)) **GitLab Enterprise Edition**
+
+### Removed (43 changes)
+
+- [Delete skip_refresh_project_policies feature flag](gitlab-org/gitlab@8bb6972a230d407e8c56d7862aa50c97d6f34351) ([merge request](gitlab-org/gitlab!141653)) **GitLab Enterprise Edition**
+- [Remove convert_user_to_group_managed_accounts, remove_non_gma_memberships FFs and related code](gitlab-org/gitlab@e6fb44c93ed7e64af9e1eac30478fa2116b201ca) ([merge request](gitlab-org/gitlab!127388)) **GitLab Enterprise Edition**
+- [Remove code_suggestions_used_by_default flag](gitlab-org/gitlab@02f38cf96461b0e14b7295bd7ea64b4b0656ba98) ([merge request](gitlab-org/gitlab!141080)) **GitLab Enterprise Edition**
+- [Clean up environment alert experiment](gitlab-org/gitlab@bd6af624e172b99873f73a06c4bda5e0a2f5c201) ([merge request](gitlab-org/gitlab!141032))
+- [Remove namespace CI Catalog](gitlab-org/gitlab@30b4ffbe6a1bc64ad17ee73d8c08cbc4732f8435) ([merge request](gitlab-org/gitlab!140725)) **GitLab Enterprise Edition**
+- [Remove geo_repository_replicator_legacy_behaviour feature flag](gitlab-org/gitlab@602a08d4eb60b9b48e3c00d6d409f5d4c0d12ab4) ([merge request](gitlab-org/gitlab!141304)) **GitLab Enterprise Edition**
+- [Remove unused tag_name and tag_path from VersionType](gitlab-org/gitlab@23be76995d5c46f0c7ccd2b24e21fa0649511838) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/140970))
+- [Drop `epic_id` Column From Vulnerabilities](gitlab-org/gitlab@3f4b140f41baf8b11a804c7a3d3aad6b5b6e3685) ([merge request](gitlab-org/gitlab!138263))
+- [Drop `milestone_id` Column From Vulnerabilities](gitlab-org/gitlab@fdf2fc2a01dc987d8059e279274913b989335786) ([merge request](gitlab-org/gitlab!138262))
+- [Remove browrsersdk_tracking feature flag](gitlab-org/gitlab@05d169c14ca34509403e74ff3ce3203c9e20e80f) ([merge request](gitlab-org/gitlab!141212))
+- [Remove CA page size feature flag](gitlab-org/gitlab@af3285110ac658ae8bb48c6c46cf7d08d0d267b9) ([merge request](gitlab-org/gitlab!141075)) **GitLab Enterprise Edition**
+- [Drop `start_date` Column From Vulnerabilities](gitlab-org/gitlab@ff11c881b59b389770f5c23b9390e4d68c2d1827) ([merge request](gitlab-org/gitlab!138268))
+- [Remove individual permissions from MemberRole API](gitlab-org/gitlab@3e6d4b371b5d7fcac369552f36071fa1ef99df03) ([merge request](gitlab-org/gitlab!140715)) **GitLab Enterprise Edition**
+- [Drop `updated_by_id` Column From Vulnerabilities](gitlab-org/gitlab@9d0996611446b55114b3d9e33e7efba14c7a1251) ([merge request](gitlab-org/gitlab!138264))
+- [Drop `last_edited_by_id` Column From Vulnerabilities](gitlab-org/gitlab@7de5f7ce28c4ed4fad5a6e9bbb8bcb752a1372aa) ([merge request](gitlab-org/gitlab!138266))
+- [Drop `last_edited_at` Column From Vulnerabilities](gitlab-org/gitlab@367f6734775ad55cc6cc250578c5feae6b4a026a) ([merge request](gitlab-org/gitlab!138269))
+- [Removes sidebar_build_class method](gitlab-org/gitlab@7cf6e05f127dd68969ada0dd73c5feeaba95ef19) by @tedtran2019 ([merge request](gitlab-org/gitlab!140508))
+- [Removes `format_project_count` method](gitlab-org/gitlab@5b01f2c09c7593ee18a90e4a4a836bc032e6f194) by @tedtran2019 ([merge request](gitlab-org/gitlab!140593)) **GitLab Enterprise Edition**
+- [Cleanup the feature flag inherit_higher_access_levels_no_cross_join](gitlab-org/gitlab@03d1c3af044a6ce0123a66aa49865641a7a84be8) ([merge request](gitlab-org/gitlab!140703))
+- [Remove `delayed_project_removal_help_text`](gitlab-org/gitlab@6b7f9723f22ec0ea894331d92c8e34bc03f5d92d) by @tedtran2019 ([merge request](gitlab-org/gitlab!140405)) **GitLab Enterprise Edition**
+- [Removes ci_status_for_statuseable method](gitlab-org/gitlab@80e3a3772dbbe40054665ed79cf4e6bbfb2f6d1b) by @tedtran2019 ([merge request](gitlab-org/gitlab!140644))
+- [Drop `due_date` Column From Vulnerabilities](gitlab-org/gitlab@2f8e48e4b2a4edc50423b95c93e2be3c5d660526) ([merge request](gitlab-org/gitlab!138267))
+- [Removes ci_variable_masked? method](gitlab-org/gitlab@30ce11cfcf0594e28a5292f11979c67cf1183254) by @tedtran2019 ([merge request](gitlab-org/gitlab!140512))
+- [Removes root_ancestor_namespace method](gitlab-org/gitlab@c01bbb5dbbc2fea2f67e77ff904d4cff587d26bd) by @tedtran2019 ([merge request](gitlab-org/gitlab!140589)) **GitLab Enterprise Edition**
+- [Remove temp index from members table](gitlab-org/gitlab@fdbabef67d74b19c8a47c739b40ec0408e834a7f) ([merge request](gitlab-org/gitlab!140559))
+- [Removes environment_for_build method](gitlab-org/gitlab@ab2d8d46bac02b5cbc5f252b85ed4f2c81e7e3c8) by @tedtran2019 ([merge request](gitlab-org/gitlab!140515))
+- [Removes ci_variable_type_options method](gitlab-org/gitlab@05382c6b9e260b4124c151cf6346f67f1b7da0c3) by @tedtran2019 ([merge request](gitlab-org/gitlab!140513))
+- [Removes pipeline_status_cache_key method](gitlab-org/gitlab@16c4fbe629c9a27acb55320ea5458a5944f216bc) by @tedtran2019 ([merge request](gitlab-org/gitlab!140510))
+- [Removes omnibus_protected_paths_throttle? method](gitlab-org/gitlab@7cf34c768c8353e6fcbaaeb2faef91e6cc9450a3) by @tedtran2019 ([merge request](gitlab-org/gitlab!140507))
+- [Removes vulnerability_data_with_category method](gitlab-org/gitlab@35afb89a619cc234cf6f92b69fe72059f7658f57) by @tedtran2019 ([merge request](gitlab-org/gitlab!140506)) **GitLab Enterprise Edition**
+- [Removes show_trial_namespace_select? method](gitlab-org/gitlab@6ad837b06b1d48c99d4b9526edb5a36c09bb4700) by @tedtran2019 ([merge request](gitlab-org/gitlab!140505)) **GitLab Enterprise Edition**
+- [Removes any_project_not_in_hashed_storage? method](gitlab-org/gitlab@4392dda2c5a4ec25ef3ed0b14cb1b6f6e13ba1d5) by @tedtran2019 ([merge request](gitlab-org/gitlab!140504)) **GitLab Enterprise Edition**
+- [Removes show_profile_token_expiry_notification?](gitlab-org/gitlab@1af369c180eb09045fd2ac4b8a65707a78fdfe5e) by @tedtran2019 ([merge request](gitlab-org/gitlab!140502)) **GitLab Enterprise Edition**
+- [Removes sort_title_project_name method](gitlab-org/gitlab@ff1cc0833da137d4262eb98eec77463640cd8fe5) by @tedtran2019 ([merge request](gitlab-org/gitlab!140408)) **GitLab Enterprise Edition**
+- [Removes methods from sorting_titles_values_helper](gitlab-org/gitlab@bbc2f63b51b8a30fdbbe66acff2976aab735c439) by @tedtran2019 ([merge request](gitlab-org/gitlab!140409)) **GitLab Enterprise Edition**
+- [Removes keep_deleted_option_label method](gitlab-org/gitlab@0511ddda1030fff71cf9e62b848df24902cb7cc6) by @tedtran2019 ([merge request](gitlab-org/gitlab!140406)) **GitLab Enterprise Edition**
+- [Removes delayed_deletion_disabled method](gitlab-org/gitlab@40b6f6feb436ad8bdac8072baa12adf87ab6185b) by @tedtran2019 ([merge request](gitlab-org/gitlab!140407)) **GitLab Enterprise Edition**
+- [Remove gitlab_routing_helper.rb: upgrade_plan_path](gitlab-org/gitlab@3eb42851d6ee0c6f9e0175ab7f91ea5d6b308e6a) by @tedtran2019 ([merge request](gitlab-org/gitlab!140404)) **GitLab Enterprise Edition**
+- [Remove geo_helper.rb: prepare_error_app_data](gitlab-org/gitlab@6d4d35bf7d48ab06ab37df42fa45d71de8344c80) by @tedtran2019 ([merge request](gitlab-org/gitlab!140400)) **GitLab Enterprise Edition**
+- [Removes users_helper.rb: users_sentence](gitlab-org/gitlab@386f24b229f96465687d8bb36e49ad1a065d9857) by @tedtran2019 ([merge request](gitlab-org/gitlab!140396)) **GitLab Enterprise Edition**
+- [Drop `start_date_sourcing_milestone_id` Col From Vulnerabilities](gitlab-org/gitlab@dd05e8fcf7e5d9d834c47a70aee2322065294e84) ([merge request](gitlab-org/gitlab!138270))
+- [Drop `due_date_sourcing_milestone_id` Col From Vulnerabilities](gitlab-org/gitlab@74d1a0fbbee3a5b865adcabbc93721f3fce72b50) ([merge request](gitlab-org/gitlab!138271))
+- [Drop index users_forbidden_state_idx](gitlab-org/gitlab@adf2f61035c7214a8c7ac4c66cf2a42745371844) ([merge request](gitlab-org/gitlab!139958))
+
+### Performance (4 changes)
+
+- [Cleanup referenced FK ci_job_artifacts](gitlab-org/gitlab@2e7c416c999dbc1feb67d7a0803e10cacab6e341) ([merge request](gitlab-org/gitlab!141474))
+- [Bulk create license scan result policies](gitlab-org/gitlab@6b884e14c0be4178d564c52bef71f2ec592d85e0) ([merge request](gitlab-org/gitlab!139163)) **GitLab Enterprise Edition**
+- [Remove feature flag `optimize_where_full_path_in`](gitlab-org/gitlab@95c2f51680291034c3c5a392712555b09cf5631a) ([merge request](gitlab-org/gitlab!141008))
+- [Add pagination to UsersController#groups](gitlab-org/gitlab@f53167b6015a9a8c1777a5cdd90b5f47f0a85198) ([merge request](gitlab-org/gitlab!140194))
+
+### Other (73 changes)
+
+- [Refactor member roles front-end to use GraphQL instead of REST API](gitlab-org/gitlab@c3d919d0c7cb430d4587ad35f41c792c974a86a5) ([merge request](gitlab-org/gitlab!141064)) **GitLab Enterprise Edition**
+- [Add a constraint to ensure application_settings.rate_limits is a hash](gitlab-org/gitlab@a02d2e551e09f731d21eddd2345dea8fd2769bec) ([merge request](gitlab-org/gitlab!141765))
+- [Clean up FF scan_result_any_merge_request from backend](gitlab-org/gitlab@4269aa1e2269974330e7d275df9769b910dee4c4) ([merge request](gitlab-org/gitlab!141506)) **GitLab Enterprise Edition**
+- [Remove unused prompt files for completion and generation](gitlab-org/gitlab@40cc9c3d108613b8d4cea71e04244d410bc2c08a) ([merge request](gitlab-org/gitlab!141545))
+- [Fix tooltips on group "Shared projects" view](gitlab-org/gitlab@019cfd2c2493d0aeb6f7b0457490fdec85954a8a) by @antonykor.ak ([merge request](gitlab-org/gitlab!141493))
+- [Prepare partitioning constraints for ci_pipeline_variables](gitlab-org/gitlab@5bd44c4901547ea8c8d91f38d245d98524463c67) ([merge request](gitlab-org/gitlab!137643))
+- [Add sharding keys for feature category compliance_management](gitlab-org/gitlab@c1492bb0048d9cda22ec2ab8e537a5c4547c69fe) ([merge request](gitlab-org/gitlab!141568))
+- [Add sharding key `group_id` to agent_user_access_group_authorizations](gitlab-org/gitlab@aa2e33373260d5e0b9f7acf51fea249c817f2467) ([merge request](gitlab-org/gitlab!141565))
+- [Add sharding key `project_id` to agent_project_authorizations](gitlab-org/gitlab@0781b1b0aed2338b2788328ceee3c028a3a8a009) ([merge request](gitlab-org/gitlab!141564))
+- [Remove geo_proxy_lfs_batch_requests feature flag](gitlab-org/gitlab@af53d6e333a60e2b7372c5f4d085d76006920c77) ([merge request](gitlab-org/gitlab!141516)) **GitLab Enterprise Edition**
+- [Remove FF bulk_imports_batched_import_export](gitlab-org/gitlab@1d6c783df41dc47768e13b05be56f61c38c14e7c) ([merge request](gitlab-org/gitlab!135394))
+- [test: Test for feature flag in package registry settings](gitlab-org/gitlab@03acd6ba3783a6e039f909966d35a59196d4f4f1) by @gerardo-navarro ([merge request](gitlab-org/gitlab!141113))
+- [Fix text alignment in GitLab Pages Domain-level redirects](gitlab-org/gitlab@4eace52c0b4d3bf767a74364cea4b6480f7cdf18) ([merge request](gitlab-org/gitlab!141447))
+- [Protected packages: Return ServiceResponse for CreateNpmPackageService](gitlab-org/gitlab@1305cba2091e899bece5057e280eb2962feff27f) by @gerardo-navarro ([merge request](gitlab-org/gitlab!140778))
+- [Move group_setting app outside components directory](gitlab-org/gitlab@a819a8be60ad281bdb5326a3a795a3eaa48b7c59) ([merge request](gitlab-org/gitlab!141082)) **GitLab Enterprise Edition**
+- [Docs: Support domain-level redirects](gitlab-org/gitlab@d5a07568327cf154bec69a4fdd4cc39bb3341d39) ([merge request](gitlab-org/gitlab!138515))
+- [Ignore project_import_level column](gitlab-org/gitlab@05f6a5176aae7d4f85e175ebbf54d43bd9071dfb) ([merge request](gitlab-org/gitlab!141188))
+- [Remove in_factory_bot_create?](gitlab-org/gitlab@b823114b0bed11aa6dd53b7afffb2e5c92fe13e8) ([merge request](gitlab-org/gitlab!141286))
+- [Create index asynchronously for system_note_metadata](gitlab-org/gitlab@4d15308a50130f05d3dc4be44c0c5cddc65b83b3) ([merge request](gitlab-org/gitlab!141330))
+- [Remove bulk_import_details_page feature flag](gitlab-org/gitlab@1cedf335988c547892a09e1ca2af64ee1c788291) ([merge request](gitlab-org/gitlab!140719))
+- [Add support for split button loading](gitlab-org/gitlab@32d52d5ba5e9c15ccaf8fb426f57b122a3e74c95) ([merge request](gitlab-org/gitlab!141251)) **GitLab Enterprise Edition**
+- [Remove default values ci_pipeline_chat_data#partition_id](gitlab-org/gitlab@e7ca0ad5dae1215f45b5e7f86ee781dcc23f219c) ([merge request](gitlab-org/gitlab!141071))
+- [Remove feature flag security_policies_variables_precedence](gitlab-org/gitlab@03a62101da58852cc5f2b947b4a6e7a2aefa9850) ([merge request](gitlab-org/gitlab!140883)) **GitLab Enterprise Edition**
+- [Add role to organization_users and assign creator as owner](gitlab-org/gitlab@919a830b673ce3d56e5fc36e3b9fd0b9b62f138c) ([merge request](gitlab-org/gitlab!140817))
+- [Rename app component to reflect its purpose](gitlab-org/gitlab@65021b7868683c2a8628eb1fc5766564336d52a8) ([merge request](gitlab-org/gitlab!140337)) **GitLab Enterprise Edition**
+- [Backfill namespace_id for issue_search_data](gitlab-org/gitlab@23dcb9408278b82377a9dc4453a8f99e2d76addd) ([merge request](gitlab-org/gitlab!128010))
+- [refactor: Add missing feature category to controller tests](gitlab-org/gitlab@f9181f5e4f985129b2f18eb5090d5b953a4527d3) by @gerardo-navarro ([merge request](gitlab-org/gitlab!141121))
+- [Refactor ForkService tests](gitlab-org/gitlab@d98fb44526c5094479ff475220da498c192033ad) ([merge request](gitlab-org/gitlab!141003))
+- [Stablize test to remove side effects](gitlab-org/gitlab@e4b1dfd22277d3a37823e392ab30c7fd4372abce) ([merge request](gitlab-org/gitlab!135165))
+- [Drop plain-text columns from user_credit_card_validations table](gitlab-org/gitlab@3d2839f84a7dec213425c596d256f29dfb03cb4d) ([merge request](gitlab-org/gitlab!139734))
+- [Add index for owasp_top_10 to vulnerability_reads](gitlab-org/gitlab@3c72701980a18d4c7c5b941fc623baa5c88ee37b) ([merge request](gitlab-org/gitlab!141045))
+- [Fix a false-positive test](gitlab-org/gitlab@7fd0489925c0d71abf7bb30843027e00594d6cfc) ([merge request](gitlab-org/gitlab!140988))
+- [Remove the FF use_gitlab_http_v2](gitlab-org/gitlab@cadfad1c11fc7b7edbd998663428f80ae8ae5e78) ([merge request](gitlab-org/gitlab!140789))
+- [Remove feature flag user_approval_rules_removal](gitlab-org/gitlab@a48fe5a6e09ff803ad72a5bc5347d5451b69614a) ([merge request](gitlab-org/gitlab!140887))
+- [Backfill version field batch migration](gitlab-org/gitlab@0c120c2e0211dd72b8f34027a19bc678e3f8b57f) ([merge request](gitlab-org/gitlab!140091))
+- [Upgrade the Sidekiq gem to v7.1.6](gitlab-org/gitlab@e4a291c48ba2f8173d2c8dd462caba5dd0cd83ab) ([merge request](gitlab-org/gitlab!138882))
+- [Remove create_user_ns_outside_model feature flag](gitlab-org/gitlab@51f7c658fab6200e09b58a4f1931585a2c518bf0) ([merge request](gitlab-org/gitlab!140835))
+- [Docs: GitLab Pages rate-limiting for IPv6 should be based on /64 prefix](gitlab-org/gitlab@ff8ca76b7d5799f9a5a0ee568dd70e17c64c2899) ([merge request](gitlab-org/gitlab!140059))
+- [Ban use of License in ApplicationSetting model](gitlab-org/gitlab@843ecc2482277daf9876f86e1c10b2548f0b2df9) ([merge request](gitlab-org/gitlab!140669)) **GitLab Enterprise Edition**
+- [Show the most correct set of approval rules post merge](gitlab-org/gitlab@a0367645ae42b087cbae2ac44a188062a43f92b6) ([merge request](gitlab-org/gitlab!133665))
+- [Migrates OmniAuth login button to use Pajamas](gitlab-org/gitlab@8dd2da2e6485133bc09a36d3f2324deefc3b2c29) ([merge request](gitlab-org/gitlab!140294))
+- [Update AI generated MR text](gitlab-org/gitlab@32a5c20a88382303f8f0d9c45f375068a616d092) ([merge request](gitlab-org/gitlab!140813))
+- [Remove feature flag always_set_pipeline_failure_reason](gitlab-org/gitlab@b6239b10019f4c383012076ee2529c988aee1e94) ([merge request](gitlab-org/gitlab!140494))
+- [Backfill owasp_top_10 on existing vulnerability_reads records](gitlab-org/gitlab@ea49ae6e66d8256d21799f5291671a6fd3c9eab5) ([merge request](gitlab-org/gitlab!139544))
+- [test: Remove duplicate test cases for Npm::CreatePackageService](gitlab-org/gitlab@eae3fc1c7372ad00ab51140b57579f888edf4d0a) by @gerardo-navarro ([merge request](gitlab-org/gitlab!140781))
+- [Remove feature flag allow_streaming_instance_audit_events_to_amazon_s3](gitlab-org/gitlab@f447eeec3ee37c961637ef0ee61f0dcd297ab6d7) ([merge request](gitlab-org/gitlab!140774)) **GitLab Enterprise Edition**
+- [Schedule async validation for merge_request_diffs.project_id FK](gitlab-org/gitlab@e75996c98133e2e2d3f19af7e10b4d7afdbd6c37) ([merge request](gitlab-org/gitlab!140410))
+- [test: Align and refactor test structure for package protection](gitlab-org/gitlab@c8a4d2dabe4099af0c00be455659aebe7facb3ef) by @gerardo-navarro ([merge request](gitlab-org/gitlab!140753))
+- [Remove vite feature flag](gitlab-org/gitlab@a5d841e01f8d6ec213381d2c6de6b1d7a202a222) ([merge request](gitlab-org/gitlab!140733))
+- [Remove old summarize mr worker](gitlab-org/gitlab@9d2a844f11c027afd502ea2b93716ebee3cc7d71) ([merge request](gitlab-org/gitlab!140659))
+- [Refactor event sync worker](gitlab-org/gitlab@d39bcf82fb8c7c40a34ce915ccde8170e1a5a7fa) ([merge request](gitlab-org/gitlab!140126))
+- [Finalize batched background migrations](gitlab-org/gitlab@092feed2ea3a5254039cf67c452497427b9bae4f) ([merge request](gitlab-org/gitlab!132480))
+- [Create index_issues_on_namespace_id_iid_unique index SYNC](gitlab-org/gitlab@31b862f247eac56c8e08453b14eaefdde37910d9) ([merge request](gitlab-org/gitlab!140253))
+- [No-op migration due to incident](gitlab-org/gitlab@7636233e73938120035af6a2cf21012edda54b87) ([merge request](gitlab-org/gitlab!140587))
+- [Refactor Gitlab::Git::Tree#where method](gitlab-org/gitlab@aacb81758ed1e6ead95d711dec9c366a6f26f7f5) ([merge request](gitlab-org/gitlab!140466)) **GitLab Enterprise Edition**
+- [Reuse fallback's connection pool if identical](gitlab-org/gitlab@73f607caea5e1cf96e990bba1c00b52edf746824) ([merge request](gitlab-org/gitlab!139493))
+- [Remove use of deprecated_clipboard_button](gitlab-org/gitlab@30f8d93782b54849a016471c21887f7b827c00f3) by @missy-davies ([merge request](gitlab-org/gitlab!140014))
+- [Remove ci_editor_ai_conversations table and related jobs](gitlab-org/gitlab@064a557e87d3b2e80a44914b7e21d344a4a67643) ([merge request](gitlab-org/gitlab!139626))
+- [Initialize conversion of geo_event_id column type](gitlab-org/gitlab@eab8d49924003d7a2e227e175c5e46797ae65e93) ([merge request](gitlab-org/gitlab!138646)) **GitLab Enterprise Edition**
+- [Remove FF: updated_ai_powered_features_menu_for_sm](gitlab-org/gitlab@c0c01faab7dabd92b62c3251c5e9127d3a3cd79a) ([merge request](gitlab-org/gitlab!139141))
+- [Resolving some group and project cross joins](gitlab-org/gitlab@8936d6d00d544092c2f4bc3a004e33ee8602ae66) ([merge request](gitlab-org/gitlab!139690))
+- [Remove unused index](gitlab-org/gitlab@0f3dbfcb59c2b0ae784f650af5d504f53b98fa4a) ([merge request](gitlab-org/gitlab!140165))
+- [Move modal components to seperate directory](gitlab-org/gitlab@27aced36240705e77a4380bc3569004a91577832) ([merge request](gitlab-org/gitlab!139924)) **GitLab Enterprise Edition**
+- [Refactor assignees widget service](gitlab-org/gitlab@972631ce5f5e3ac89328ff294943b93e5c621d92) by @imskr ([merge request](gitlab-org/gitlab!140001))
+- [Migrate to Pajamas::AvatarComponent for _member](gitlab-org/gitlab@ebee389cffe4c82262b54c43e0a4f21ed49d3471) by @tedtran2019 ([merge request](gitlab-org/gitlab!139848))
+- [Aligning variable name in test relaed to protected containers](gitlab-org/gitlab@b33e8a401c0ecf6190959849817f2b21d50f5762) by @gerardo-navarro ([merge request](gitlab-org/gitlab!140258))
+- [Refactor repository storage move worker scheduling ](gitlab-org/gitlab@308ebfa3d730b1af04708e49a4e2e34091672716) by @tedtran2019 ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139724#note_1700869142))
+- [Refactor UI text for To-Do List empty state](gitlab-org/gitlab@60c8d2d492714bd7266eff1ec650cb434ac9473b) ([merge request](gitlab-org/gitlab!139153))
+- [Preload saml_provider unconditionally to fix N+1 queries](gitlab-org/gitlab@449a46785954f9782ffe0c6e24ff2da1b78da11f) ([merge request](gitlab-org/gitlab!140197)) **GitLab Enterprise Edition**
+- [Finalize system_note_metadata bigint backfill](gitlab-org/gitlab@8ecf9bf0416aaed29dbb51385f92441b5ba41924) ([merge request](gitlab-org/gitlab!138610))
+- [Finalize merge_request_diffs.project_id backfill](gitlab-org/gitlab@26aded629ba0a944e9c1ef138d9d5563de0d86ac) ([merge request](gitlab-org/gitlab!139726))
+- [Bump the finalize_after date of backfill migration](gitlab-org/gitlab@770ab7faa2048bfeb8bddd506e6f37fe18bb4d06) ([merge request](gitlab-org/gitlab!140109))
+- [Remove code_suggestions_completion_api feature](gitlab-org/gitlab@988e2f57f9635ed9cc3896b15965b608fce54756) ([merge request](gitlab-org/gitlab!138174)) **GitLab Enterprise Edition**
+
## 16.7.3 (2024-01-13)
### Fixed (1 change)
diff --git a/app/assets/javascripts/ml/model_registry/components/model_row.vue b/app/assets/javascripts/ml/model_registry/components/model_row.vue
index ffae7e83099..15be7bd0b47 100644
--- a/app/assets/javascripts/ml/model_registry/components/model_row.vue
+++ b/app/assets/javascripts/ml/model_registry/components/model_row.vue
@@ -21,7 +21,7 @@ export default {
if (!this.model.versionCount) return s__('MlModelRegistry|No registered versions');
return n__(
- 'MlModelRegistry|· No other versions',
+ 'MlModelRegistry|· %d version',
'MlModelRegistry|· %d versions',
this.model.versionCount,
);
diff --git a/app/assets/javascripts/observability/client.js b/app/assets/javascripts/observability/client.js
index b7e4ae8e8ea..4fc4ce06528 100644
--- a/app/assets/javascripts/observability/client.js
+++ b/app/assets/javascripts/observability/client.js
@@ -66,6 +66,7 @@ const SUPPORTED_FILTERS = {
period: ['='],
traceId: ['=', '!='],
attribute: ['='],
+ status: ['=', '!='],
// free-text 'search' temporarily ignored https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2309
};
@@ -79,6 +80,7 @@ const FILTER_TO_QUERY_PARAM = {
period: 'period',
traceId: 'trace_id',
attribute: 'attribute',
+ status: 'status',
};
const FILTER_OPERATORS_PREFIX = {
diff --git a/app/assets/javascripts/organizations/groups_and_projects/components/app.vue b/app/assets/javascripts/organizations/groups_and_projects/components/app.vue
index ebe69925491..6f03783d15c 100644
--- a/app/assets/javascripts/organizations/groups_and_projects/components/app.vue
+++ b/app/assets/javascripts/organizations/groups_and_projects/components/app.vue
@@ -1,5 +1,5 @@
<script>
-import { GlCollapsibleListbox, GlSorting, GlSortingItem } from '@gitlab/ui';
+import { GlCollapsibleListbox, GlSorting } from '@gitlab/ui';
import { isEqual } from 'lodash';
import { s__, __ } from '~/locale';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
@@ -31,7 +31,7 @@ export default {
searchInputPlaceholder: s__('Organization|Search or filter list'),
displayListboxHeaderText: __('Display'),
},
- components: { FilteredSearchBar, GlCollapsibleListbox, GlSorting, GlSortingItem },
+ components: { FilteredSearchBar, GlCollapsibleListbox, GlSorting },
filteredSearch: {
tokens: [],
namespace: 'organization_groups_and_projects',
@@ -55,10 +55,10 @@ export default {
}
},
activeSortItem() {
- return this.$options.sortItems.find((sortItem) => sortItem.name === this.sortName);
+ return this.$options.sortItems.find((sortItem) => sortItem.value === this.sortName);
},
sortName() {
- return this.$route.query.sort_name || SORT_ITEM_CREATED.name;
+ return this.$route.query.sort_name || SORT_ITEM_CREATED.value;
},
isAscending() {
return this.$route.query.sort_direction !== SORT_DIRECTION_DESC;
@@ -97,12 +97,12 @@ export default {
onDisplayListboxSelect(display) {
this.pushQuery({ display });
},
- onSortItemClick(sortItem) {
- if (this.$route.query.sort_name === sortItem.name) {
+ onSortItemClick(sortValue) {
+ if (this.$route.query.sort_name === sortValue) {
return;
}
- this.pushQuery({ ...this.$route.query, sort_name: sortItem.name });
+ this.pushQuery({ ...this.$route.query, sort_name: sortValue });
},
onSortDirectionChange(isAscending) {
this.pushQuery({
@@ -158,17 +158,11 @@ export default {
dropdown-class="gl-w-full"
:text="sortText"
:is-ascending="isAscending"
+ :sort-options="$options.sortItems"
+ :sort-by="activeSortItem.value"
@sortDirectionChange="onSortDirectionChange"
- >
- <gl-sorting-item
- v-for="sortItem in $options.sortItems"
- :key="sortItem.name"
- :active="activeSortItem.name === sortItem.name"
- @click="onSortItemClick(sortItem)"
- >
- {{ sortItem.text }}
- </gl-sorting-item>
- </gl-sorting>
+ @sortByChange="onSortItemClick"
+ />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/organizations/groups_and_projects/constants.js b/app/assets/javascripts/organizations/groups_and_projects/constants.js
index d79b632f6fb..7e2533b798b 100644
--- a/app/assets/javascripts/organizations/groups_and_projects/constants.js
+++ b/app/assets/javascripts/organizations/groups_and_projects/constants.js
@@ -20,7 +20,7 @@ export const SORT_DIRECTION_ASC = 'asc';
export const SORT_DIRECTION_DESC = 'desc';
export const SORT_ITEM_CREATED = {
- name: 'created',
+ value: 'created',
text: __('Created'),
};
diff --git a/app/assets/javascripts/releases/components/releases_sort.vue b/app/assets/javascripts/releases/components/releases_sort.vue
index 0f14b579da0..802392140b1 100644
--- a/app/assets/javascripts/releases/components/releases_sort.vue
+++ b/app/assets/javascripts/releases/components/releases_sort.vue
@@ -1,5 +1,5 @@
<script>
-import { GlSorting, GlSortingItem } from '@gitlab/ui';
+import { GlSorting } from '@gitlab/ui';
import {
ASCENDING_ORDER,
DESCENDING_ORDER,
@@ -17,7 +17,6 @@ export default {
name: 'ReleasesSort',
components: {
GlSorting,
- GlSortingItem,
},
props: {
value: {
@@ -45,7 +44,7 @@ export default {
return SORT_OPTIONS;
},
sortText() {
- return this.sortOptions.find((s) => s.orderBy === this.orderBy).label;
+ return this.sortOptions.find((s) => s.value === this.orderBy).text;
},
isDirectionAscending() {
return this.direction === ASCENDING_ORDER;
@@ -56,11 +55,8 @@ export default {
const direction = this.isDirectionAscending ? DESCENDING_ORDER : ASCENDING_ORDER;
this.emitInputEventIfChanged(this.orderBy, direction);
},
- onSortItemClick(item) {
- this.emitInputEventIfChanged(item.orderBy, this.direction);
- },
- isActiveSortItem(item) {
- return this.orderBy === item.orderBy;
+ onSortItemClick(orderBy) {
+ this.emitInputEventIfChanged(orderBy, this.direction);
},
emitInputEventIfChanged(orderBy, direction) {
const newSort = SORT_MAP[orderBy][direction];
@@ -76,16 +72,10 @@ export default {
<gl-sorting
:text="sortText"
:is-ascending="isDirectionAscending"
+ :sort-options="sortOptions"
+ :sort-by="orderBy"
data-testid="releases-sort"
@sortDirectionChange="onDirectionChange"
- >
- <gl-sorting-item
- v-for="item of sortOptions"
- :key="item.orderBy"
- :active="isActiveSortItem(item)"
- @click="onSortItemClick(item)"
- >
- {{ item.label }}
- </gl-sorting-item>
- </gl-sorting>
+ @sortByChange="onSortItemClick"
+ />
</template>
diff --git a/app/assets/javascripts/releases/constants.js b/app/assets/javascripts/releases/constants.js
index 5e9e65a01b3..b07ed67f9ba 100644
--- a/app/assets/javascripts/releases/constants.js
+++ b/app/assets/javascripts/releases/constants.js
@@ -22,12 +22,12 @@ export const CREATED_AT = 'created_at';
export const SORT_OPTIONS = [
{
- orderBy: RELEASED_AT,
- label: __('Released date'),
+ value: RELEASED_AT,
+ text: __('Released date'),
},
{
- orderBy: CREATED_AT,
- label: __('Created date'),
+ value: CREATED_AT,
+ text: __('Created date'),
},
];
diff --git a/app/assets/javascripts/work_items/components/shared/work_item_sidebar_dropdown_widget_with_edit.vue b/app/assets/javascripts/work_items/components/shared/work_item_sidebar_dropdown_widget_with_edit.vue
index 53149f62893..d94d0494ad9 100644
--- a/app/assets/javascripts/work_items/components/shared/work_item_sidebar_dropdown_widget_with_edit.vue
+++ b/app/assets/javascripts/work_items/components/shared/work_item_sidebar_dropdown_widget_with_edit.vue
@@ -1,6 +1,7 @@
<script>
import { GlButton, GlForm, GlLoadingIcon, GlCollapsibleListbox } from '@gitlab/ui';
-import { isEmpty } from 'lodash';
+import { isEmpty, debounce } from 'lodash';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { s__, __ } from '~/locale';
@@ -104,6 +105,9 @@ export default {
},
},
},
+ created() {
+ this.debouncedSearchKeyUpdate = debounce(this.setSearchKey, DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
+ },
methods: {
setSearchKey(value) {
this.$emit('searchStarted', value);
@@ -174,7 +178,7 @@ export default {
:selected="localSelectedItem"
:reset-button-label="resetButton"
@reset="unassignValue"
- @search="setSearchKey"
+ @search="debouncedSearchKeyUpdate"
@select="handleItemClick"
@shown="onListboxShown"
@hidden="onListboxHide"
diff --git a/app/assets/javascripts/work_items/components/work_item_milestone_with_edit.vue b/app/assets/javascripts/work_items/components/work_item_milestone_with_edit.vue
index 45c12cb2e08..87b41c9d9ea 100644
--- a/app/assets/javascripts/work_items/components/work_item_milestone_with_edit.vue
+++ b/app/assets/javascripts/work_items/components/work_item_milestone_with_edit.vue
@@ -4,7 +4,6 @@ import * as Sentry from '~/sentry/sentry_browser_wrapper';
import Tracking from '~/tracking';
import { s__, __ } from '~/locale';
import { MILESTONE_STATE } from '~/sidebar/constants';
-import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import WorkItemSidebarDropdownWidgetWithEdit from '~/work_items/components/shared/work_item_sidebar_dropdown_widget_with_edit.vue';
import projectMilestonesQuery from '~/sidebar/queries/project_milestones.query.graphql';
import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
@@ -102,7 +101,6 @@ export default {
apollo: {
milestones: {
query: projectMilestonesQuery,
- debounce: DEFAULT_DEBOUNCE_AND_THROTTLE_MS,
variables() {
return {
fullPath: this.fullPath,
diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb
index 6ff0f55d2f6..4d3d7b5e74b 100644
--- a/app/controllers/import/bulk_imports_controller.rb
+++ b/app/controllers/import/bulk_imports_controller.rb
@@ -148,11 +148,12 @@ class Import::BulkImportsController < ApplicationController
end
def verify_blocked_uri
- Gitlab::UrlBlocker.validate!(
+ Gitlab::HTTP_V2::UrlBlocker.validate!(
session[url_key],
allow_localhost: allow_local_requests?,
allow_local_network: allow_local_requests?,
- schemes: %w[http https]
+ schemes: %w[http https],
+ deny_all_requests_except_allowed: Gitlab::CurrentSettings.deny_all_requests_except_allowed?
)
rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e
clear_session_data
diff --git a/app/controllers/import/gitea_controller.rb b/app/controllers/import/gitea_controller.rb
index 4e95c6527c3..b5840f9644d 100644
--- a/app/controllers/import/gitea_controller.rb
+++ b/app/controllers/import/gitea_controller.rb
@@ -92,11 +92,12 @@ class Import::GiteaController < Import::GithubController
end
def verify_blocked_uri
- @verified_url_and_hostname ||= Gitlab::UrlBlocker.validate!(
+ @verified_url_and_hostname ||= Gitlab::HTTP_V2::UrlBlocker.validate!(
provider_url,
allow_localhost: allow_local_requests?,
allow_local_network: allow_local_requests?,
- schemes: %w[http https]
+ schemes: %w[http https],
+ deny_all_requests_except_allowed: Gitlab::CurrentSettings.deny_all_requests_except_allowed?
)
rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e
session[access_token_key] = nil
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index fcd87f46f67..d98d443bdc9 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -57,7 +57,7 @@ class InvitesController < ApplicationController
def member?
strong_memoize(:is_member) do
- @member.source.users.include?(current_user)
+ @member.source.has_user?(current_user)
end
end
diff --git a/app/finders/ci/runners_finder.rb b/app/finders/ci/runners_finder.rb
index 18be2aec2e2..66b16e875c1 100644
--- a/app/finders/ci/runners_finder.rb
+++ b/app/finders/ci/runners_finder.rb
@@ -29,6 +29,7 @@ module Ci
items = by_runner_type(items)
items = by_tag_list(items)
items = by_creator_id(items)
+ items = by_creator_username(items)
items = by_version_prefix(items)
items = request_tag_list(items)
@@ -130,6 +131,16 @@ module Ci
items.with_creator_id(creator_id)
end
+ def by_creator_username(items)
+ creator_username = @params[:creator_username].presence
+ return items unless creator_username
+
+ creator_id = User.find_by_username(creator_username)&.id
+ return Ci::Runner.none unless creator_id
+
+ items.with_creator_id(creator_id)
+ end
+
def by_version_prefix(items)
sanitized_prefix = @params.fetch(:version_prefix, '')[/^[\d+.]+/]
return items unless sanitized_prefix
diff --git a/app/finders/personal_access_tokens_finder.rb b/app/finders/personal_access_tokens_finder.rb
index 5af08cf0660..659c52e200a 100644
--- a/app/finders/personal_access_tokens_finder.rb
+++ b/app/finders/personal_access_tokens_finder.rb
@@ -24,6 +24,7 @@ class PersonalAccessTokensFinder
tokens = by_last_used_before(tokens)
tokens = by_last_used_after(tokens)
tokens = by_search(tokens)
+ tokens = tokens.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/436657")
sort(tokens)
end
diff --git a/app/graphql/resolvers/ci/runners_resolver.rb b/app/graphql/resolvers/ci/runners_resolver.rb
index 38d2ebe046b..a289bee9806 100644
--- a/app/graphql/resolvers/ci/runners_resolver.rb
+++ b/app/graphql/resolvers/ci/runners_resolver.rb
@@ -45,6 +45,11 @@ module Resolvers
required: false,
description: 'Filter runners by creator ID.'
+ argument :creator_username, GraphQL::Types::String,
+ required: false,
+ description: 'Filter runners by creator username.',
+ alpha: { milestone: '16.7' }
+
argument :version_prefix, GraphQL::Types::String,
required: false,
description: "Filter runners by version. Runners that contain runner managers with the version at " \
@@ -81,6 +86,7 @@ module Resolvers
sort: params[:sort]&.to_s,
creator_id:
params[:creator_id] ? ::GitlabSchema.parse_gid(params[:creator_id], expected_type: ::User).model_id : nil,
+ creator_username: params[:creator_username],
version_prefix: params[:version_prefix],
preload: {} # we'll handle preloading ourselves
}.compact
diff --git a/app/models/concerns/has_user_type.rb b/app/models/concerns/has_user_type.rb
index c3f702a4e69..871ffda3d90 100644
--- a/app/models/concerns/has_user_type.rb
+++ b/app/models/concerns/has_user_type.rb
@@ -89,6 +89,8 @@ module HasUserType
return resource.maintainers if resource.is_a?(Project)
- resource.owners
+ resource
+ .owners
+ .allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/436658")
end
end
diff --git a/app/models/group.rb b/app/models/group.rb
index bbf34ce21c0..1d2cadc24f3 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -42,10 +42,8 @@ class Group < Namespace
foreign_key: :member_namespace_id, inverse_of: :group, class_name: 'GroupMember'
alias_method :members, :group_members
- has_many :users, -> { allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/432604") },
- through: :group_members
- has_many :owners, -> { allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/432604") },
- through: :all_owner_members, source: :user
+ has_many :users, through: :group_members
+ has_many :owners, through: :all_owner_members, source: :user
has_many :requesters, -> { where.not(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'GroupMember' # rubocop:disable Cop/ActiveRecordDependent
has_many :namespace_requesters, -> { where.not(requested_at: nil).unscope(where: %i[source_id source_type]) },
diff --git a/app/models/member.rb b/app/models/member.rb
index 1771c92d5cd..9c786519155 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -173,7 +173,7 @@ class Member < ApplicationRecord
scope :by_access_level, -> (access_level) { active.where(access_level: access_level) }
scope :all_by_access_level, -> (access_level) { where(access_level: access_level) }
- scope :preload_user, -> { preload(:user) }
+ scope :preload_users, -> { preload(:user) }
scope :preload_user_and_notification_settings, -> do
preload(user: :notification_settings)
diff --git a/app/models/namespaces/user_namespace.rb b/app/models/namespaces/user_namespace.rb
index fde6c4291ee..aabb12cf2cd 100644
--- a/app/models/namespaces/user_namespace.rb
+++ b/app/models/namespaces/user_namespace.rb
@@ -11,7 +11,7 @@ module Namespaces
# mismatch as it always has been a User (personal) namespace.
#
# If you need to make a change here, please ping the
- # Manage/Workspaces group so we can ensure that the
+ # Tenant Scale group so we can ensure that the
# changes do not break existing functionality.
#
# As Namespaces evolve we may be able to relax this restriction
diff --git a/app/models/project_authorization.rb b/app/models/project_authorization.rb
index 194f37fcb89..bb46cd2b6f0 100644
--- a/app/models/project_authorization.rb
+++ b/app/models/project_authorization.rb
@@ -16,7 +16,7 @@ class ProjectAuthorization < ApplicationRecord
scope :non_guests, -> { where('access_level > ?', ::Gitlab::Access::GUEST) }
scope :owners, -> { where(access_level: ::Gitlab::Access::OWNER) }
- scope :preload_user, -> { preload(:user) }
+ scope :preload_users, -> { preload(:user) }
# TODO: To be removed after https://gitlab.com/gitlab-org/gitlab/-/issues/418205
before_create :assign_is_unique
diff --git a/app/models/project_team.rb b/app/models/project_team.rb
index 3af9f946243..5aac6062078 100644
--- a/app/models/project_team.rb
+++ b/app/models/project_team.rb
@@ -104,7 +104,7 @@ class ProjectTeam
def owners
@owners ||=
if group
- group.owners
+ group.owners.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/432606")
else
# workaround until we migrate Project#owners to have membership with
# OWNER access level
diff --git a/app/models/route.rb b/app/models/route.rb
index 1fa0005ffb4..aad23996b69 100644
--- a/app/models/route.rb
+++ b/app/models/route.rb
@@ -27,40 +27,12 @@ class Route < MainClusterwide::ApplicationRecord
def rename_descendants
return unless saved_change_to_path? || saved_change_to_name?
- if Feature.disabled?(:batch_route_updates, Feature.current_request, type: :gitlab_com_derisk)
- descendant_routes = self.class.inside_path(path_before_last_save)
+ changes = {
+ path: { saved: saved_change_to_path?, old_value: path_before_last_save },
+ name: { saved: saved_change_to_name?, old_value: name_before_last_save }
+ }
- descendant_routes.each do |route|
- attributes = {}
-
- if saved_change_to_path? && route.path.present?
- attributes[:path] = route.path.sub(path_before_last_save, path)
- end
-
- if saved_change_to_name? && name_before_last_save.present? && route.name.present?
- attributes[:name] = route.name.sub(name_before_last_save, name)
- end
-
- next if attributes.empty?
-
- old_path = route.path
-
- # Callbacks must be run manually
- route.update_columns(attributes.merge(updated_at: Time.current))
-
- # We are not calling route.delete_conflicting_redirects here, in hopes
- # of avoiding deadlocks. The parent (self, in this method) already
- # called it, which deletes conflicts for all descendants.
- route.create_redirect(old_path) if attributes[:path]
- end
- else
- changes = {
- path: { saved: saved_change_to_path?, old_value: path_before_last_save },
- name: { saved: saved_change_to_name?, old_value: name_before_last_save }
- }
-
- Routes::RenameDescendantsService.new(self).execute(changes) # rubocop: disable CodeReuse/ServiceClass -- Need a service class to encapsulate all the logic.
- end
+ Routes::RenameDescendantsService.new(self).execute(changes) # rubocop: disable CodeReuse/ServiceClass -- Need a service class to encapsulate all the logic.
end
def delete_conflicting_redirects
diff --git a/app/services/groups/transfer_service.rb b/app/services/groups/transfer_service.rb
index 9fc1a05476e..c81a879ad1a 100644
--- a/app/services/groups/transfer_service.rb
+++ b/app/services/groups/transfer_service.rb
@@ -236,7 +236,7 @@ module Groups
def ensure_ownership
return if @new_parent_group
- return unless @group.all_owner_members.empty?
+ return unless @group.all_owner_members.non_invite.empty?
add_owner_on_transferred_group
end
diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb
index e8a684e5da4..0da3326a100 100644
--- a/app/services/projects/import_service.rb
+++ b/app/services/projects/import_service.rb
@@ -166,14 +166,15 @@ module Projects
end
def get_resolved_address
- Gitlab::UrlBlocker
+ Gitlab::HTTP_V2::UrlBlocker
.validate!(
project.import_url,
schemes: Project::VALID_IMPORT_PROTOCOLS,
ports: Project::VALID_IMPORT_PORTS,
allow_localhost: allow_local_requests?,
allow_local_network: allow_local_requests?,
- dns_rebind_protection: dns_rebind_protection?)
+ dns_rebind_protection: dns_rebind_protection?,
+ deny_all_requests_except_allowed: Gitlab::CurrentSettings.deny_all_requests_except_allowed?)
.then do |(import_url, resolved_host)|
next '' if resolved_host.nil? || !import_url.scheme.in?(%w[http https])
diff --git a/app/services/projects/update_remote_mirror_service.rb b/app/services/projects/update_remote_mirror_service.rb
index d5c8e958bbd..6053e834f68 100644
--- a/app/services/projects/update_remote_mirror_service.rb
+++ b/app/services/projects/update_remote_mirror_service.rb
@@ -10,7 +10,11 @@ module Projects
return success unless remote_mirror.enabled?
# Blocked URLs are a hard failure, no need to attempt to retry
- if Gitlab::UrlBlocker.blocked_url?(normalized_url(remote_mirror.url), schemes: Project::VALID_MIRROR_PROTOCOLS)
+ if Gitlab::HTTP_V2::UrlBlocker.blocked_url?(
+ normalized_url(remote_mirror.url),
+ schemes: Project::VALID_MIRROR_PROTOCOLS,
+ deny_all_requests_except_allowed: Gitlab::CurrentSettings.deny_all_requests_except_allowed?
+ )
hard_retry_or_fail(remote_mirror, _('The remote mirror URL is invalid.'), tries)
return error(remote_mirror.last_error)
end
diff --git a/app/validators/addressable_url_validator.rb b/app/validators/addressable_url_validator.rb
index af7be326f51..8fa562a04dd 100644
--- a/app/validators/addressable_url_validator.rb
+++ b/app/validators/addressable_url_validator.rb
@@ -56,7 +56,7 @@ class AddressableUrlValidator < ActiveModel::EachValidator
allow_localhost: true,
allow_local_network: true,
ascii_only: false,
- deny_all_requests_except_allowed: Gitlab::UrlBlocker::DENY_ALL_REQUESTS_EXCEPT_ALLOWED_DEFAULT,
+ deny_all_requests_except_allowed: false,
enforce_user: false,
enforce_sanitization: false,
dns_rebind_protection: false
@@ -83,7 +83,7 @@ class AddressableUrlValidator < ActiveModel::EachValidator
value = strip_value!(record, attribute, value)
- Gitlab::UrlBlocker.validate!(value, **blocker_args)
+ Gitlab::HTTP_V2::UrlBlocker.validate!(value, **blocker_args)
rescue Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e
record.errors.add(attribute, options.fetch(:blocked_message) % { exception_message: e.message })
end
@@ -108,6 +108,10 @@ class AddressableUrlValidator < ActiveModel::EachValidator
if self.class.allow_setting_local_requests?
args[:allow_localhost] = args[:allow_local_network] = true
end
+
+ if deny_all_requests_except_allowed?
+ args[:deny_all_requests_except_allowed] = true
+ end
end
end
@@ -120,4 +124,8 @@ class AddressableUrlValidator < ActiveModel::EachValidator
# See https://gitlab.com/gitlab-org/gitlab/issues/9833
ApplicationSetting.current&.allow_local_requests_from_web_hooks_and_services?
end
+
+ def deny_all_requests_except_allowed?
+ ApplicationSetting.current&.deny_all_requests_except_allowed?
+ end
end
diff --git a/app/views/devise/shared/_footer.html.haml b/app/views/devise/shared/_footer.html.haml
index 44f34e3f342..a8c45566d63 100644
--- a/app/views/devise/shared/_footer.html.haml
+++ b/app/views/devise/shared/_footer.html.haml
@@ -1,6 +1,6 @@
.footer-container.gl-w-full.gl-align-self-end
%hr.gl-m-0
- .container.gl-py-5.gl-display-flex.gl-justify-content-space-between
+ .container.gl-py-5.gl-display-flex.gl-justify-content-space-between.gl-align-items-flex-start
.gl-display-flex.gl-gap-5.gl-flex-wrap
- unless public_visibility_restricted?
= link_to _("Explore"), explore_root_path
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index fbfaaa49b39..0df30a6d445 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -9,6 +9,7 @@
= _('Group members')
%p.gl-w-full.order-md-1
= group_member_header_subtext(@group)
+ = render_if_exists 'groups/group_members/link_to_pending_members'
.gl-display-flex.gl-flex-wrap.gl-align-items-center.gl-gap-3.gl-md-w-auto.gl-w-full
.js-invite-group-trigger{ data: { classes: 'gl-md-w-auto gl-w-full', display_text: _('Invite a group') } }
- if can_admin_service_accounts?(@group)
diff --git a/app/views/shared/integrations/gitlab_slack_application/_slack_integration_form.html.haml b/app/views/shared/integrations/gitlab_slack_application/_slack_integration_form.html.haml
index 57d172b41f4..7f708a1e730 100644
--- a/app/views/shared/integrations/gitlab_slack_application/_slack_integration_form.html.haml
+++ b/app/views/shared/integrations/gitlab_slack_application/_slack_integration_form.html.haml
@@ -29,7 +29,7 @@
= render Pajamas::ButtonComponent.new(href: add_to_slack_link(@project, slack_app_id)) do
= s_('SlackIntegration|Reinstall GitLab for Slack app…')
%p
- = html_escape(s_('SlackIntegration|You may need to reinstall the GitLab for Slack app when we %{linkStart}make updates or change permissions%{linkEnd}.')) % { linkStart: %(<a href="#{help_page_path('user/project/integrations/gitlab_slack_application', anchor: 'update-the-gitlab-for-slack-app')}">).html_safe, linkEnd: '</a>'.html_safe}
+ = html_escape(s_('SlackIntegration|You may need to reinstall the GitLab for Slack app when we %{linkStart}make updates or change permissions%{linkEnd}.')) % { linkStart: %(<a href="#{help_page_path('user/project/integrations/gitlab_slack_application', anchor: 'reinstall-the-gitlab-for-slack-app')}">).html_safe, linkEnd: '</a>'.html_safe}
- else
= render Pajamas::ButtonComponent.new(href: add_to_slack_link(@project, slack_app_id)) do
= s_('SlackIntegration|Install GitLab for Slack app…')
diff --git a/app/workers/bulk_imports/pipeline_worker.rb b/app/workers/bulk_imports/pipeline_worker.rb
index 0bb9464c6de..ca006f81813 100644
--- a/app/workers/bulk_imports/pipeline_worker.rb
+++ b/app/workers/bulk_imports/pipeline_worker.rb
@@ -221,10 +221,6 @@ module BulkImports
remaining_batch_numbers = all_batch_numbers - created_batch_numbers
- if Feature.disabled?(:bulk_import_limit_concurrent_batches, context.portable)
- return LimitedBatches.new(numbers: remaining_batch_numbers, final?: true)
- end
-
limit = next_batch_count
LimitedBatches.new(
diff --git a/app/workers/integrations/irker_worker.rb b/app/workers/integrations/irker_worker.rb
index 4c1f0df0fc7..341b9437bab 100644
--- a/app/workers/integrations/irker_worker.rb
+++ b/app/workers/integrations/irker_worker.rb
@@ -52,11 +52,12 @@ module Integrations
domain = Resolv::IPv6::Regex.match?(ip_address) ? "[#{ip_address}]" : ip_address
begin
- Gitlab::UrlBlocker.validate!(
+ Gitlab::HTTP_V2::UrlBlocker.validate!(
"irc://#{domain}",
allow_localhost: allow_local_requests?,
allow_local_network: allow_local_requests?,
- schemes: ['irc'])
+ schemes: ['irc'],
+ deny_all_requests_except_allowed: Gitlab::CurrentSettings.deny_all_requests_except_allowed?)
@socket = TCPSocket.new ip_address, irker_port
rescue Errno::ECONNREFUSED, Gitlab::HTTP_V2::UrlBlocker::BlockedUrlError => e
logger.fatal "Can't connect to Irker daemon: #{e}"
diff --git a/config/feature_flags/development/bulk_import_limit_concurrent_batches.yml b/config/feature_flags/development/bulk_import_limit_concurrent_batches.yml
deleted file mode 100644
index 72dbf392528..00000000000
--- a/config/feature_flags/development/bulk_import_limit_concurrent_batches.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: bulk_import_limit_concurrent_batches
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136018
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/431561
-milestone: '16.7'
-type: development
-group: group::import and integrate
-default_enabled: true
diff --git a/config/feature_flags/development/compare_project_authorization_linear_cte.yml b/config/feature_flags/development/compare_project_authorization_linear_cte.yml
deleted file mode 100644
index b992cd3897a..00000000000
--- a/config/feature_flags/development/compare_project_authorization_linear_cte.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: compare_project_authorization_linear_cte
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122886
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/414310
-milestone: '16.1'
-type: development
-group: group::authentication
-default_enabled: false
diff --git a/config/feature_flags/development/linear_project_authorization.yml b/config/feature_flags/development/linear_project_authorization.yml
deleted file mode 100644
index e1f639a4a16..00000000000
--- a/config/feature_flags/development/linear_project_authorization.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_project_authorization
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/117988
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/410459
-milestone: '16.0'
-type: development
-group: group::authentication
-default_enabled: false
diff --git a/config/feature_flags/gitlab_com_derisk/batch_route_updates.yml b/config/feature_flags/gitlab_com_derisk/batch_route_updates.yml
deleted file mode 100644
index 8eae0d54435..00000000000
--- a/config/feature_flags/gitlab_com_derisk/batch_route_updates.yml
+++ /dev/null
@@ -1,9 +0,0 @@
----
-name: batch_route_updates
-feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/432065
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139782
-rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17360
-milestone: '16.8'
-group: group::tenant scale
-type: gitlab_com_derisk
-default_enabled: false
diff --git a/db/docs/container_expiration_policies.yml b/db/docs/container_expiration_policies.yml
index b1c203134e7..20d9d41866a 100644
--- a/db/docs/container_expiration_policies.yml
+++ b/db/docs/container_expiration_policies.yml
@@ -8,3 +8,5 @@ description: Project level settings for container registry cleanup policies
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20412
milestone: '12.6'
gitlab_schema: gitlab_main_cell
+sharding_key:
+ project_id: projects
diff --git a/db/docs/container_registry_data_repair_details.yml b/db/docs/container_registry_data_repair_details.yml
index c258fff4832..e67edbd7c8b 100644
--- a/db/docs/container_registry_data_repair_details.yml
+++ b/db/docs/container_registry_data_repair_details.yml
@@ -7,4 +7,12 @@ feature_categories:
description: Contains details for the container registry data repair
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/113029
milestone: '15.10'
-gitlab_schema: gitlab_main
+gitlab_schema: gitlab_main_cell
+allow_cross_joins:
+- gitlab_main_clusterwide
+allow_cross_transactions:
+- gitlab_main_clusterwide
+allow_cross_foreign_keys:
+- gitlab_main_clusterwide
+sharding_key:
+ project_id: projects
diff --git a/db/docs/container_registry_protection_rules.yml b/db/docs/container_registry_protection_rules.yml
index 1764cbc8cda..a2ebb7f5bb3 100644
--- a/db/docs/container_registry_protection_rules.yml
+++ b/db/docs/container_registry_protection_rules.yml
@@ -7,4 +7,12 @@ feature_categories:
description: Represents container protection rules for the container registry.
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133297
milestone: '16.5'
-gitlab_schema: gitlab_main
+gitlab_schema: gitlab_main_cell
+allow_cross_joins:
+- gitlab_main_clusterwide
+allow_cross_transactions:
+- gitlab_main_clusterwide
+allow_cross_foreign_keys:
+- gitlab_main_clusterwide
+sharding_key:
+ project_id: projects
diff --git a/db/docs/container_repositories.yml b/db/docs/container_repositories.yml
index 472385b8e65..5aa88198fc4 100644
--- a/db/docs/container_repositories.yml
+++ b/db/docs/container_repositories.yml
@@ -4,7 +4,16 @@ classes:
- ContainerRepository
feature_categories:
- container_registry
-description: Container registry repositories (images), originally named container_images, renamed in https://gitlab.com/gitlab-org/gitlab/-/commit/01d159b409d8b24d36204979a73de249843d71bf
+description: Container registry repositories (images), originally named container_images,
+ renamed in https://gitlab.com/gitlab-org/gitlab/-/commit/01d159b409d8b24d36204979a73de249843d71bf
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10109
milestone: '9.1'
-gitlab_schema: gitlab_main
+gitlab_schema: gitlab_main_cell
+allow_cross_joins:
+- gitlab_main_clusterwide
+allow_cross_transactions:
+- gitlab_main_clusterwide
+allow_cross_foreign_keys:
+- gitlab_main_clusterwide
+sharding_key:
+ project_id: projects
diff --git a/doc/administration/geo/disaster_recovery/background_verification.md b/doc/administration/geo/disaster_recovery/background_verification.md
index a927450d80f..c9bc957d41f 100644
--- a/doc/administration/geo/disaster_recovery/background_verification.md
+++ b/doc/administration/geo/disaster_recovery/background_verification.md
@@ -104,7 +104,10 @@ If the **primary** and **secondary** sites have a checksum verification mismatch
select its name.
1. On the project administration page, get the values in the **Storage name** and **Relative path** fields.
-1. On a **Gitaly node on the primary** site and a **Gitaly node on the secondary** site, go to the project's repository directory. If using Gitaly Cluster, [check that it is in a healthy state](../../gitaly/troubleshooting.md#check-cluster-health) prior to running these commands.
+1. On a **Gitaly node on the primary** site and a **Gitaly node on the secondary** site, go to the project's repository
+ directory. If using Gitaly Cluster,
+ [check that it is in a healthy state](../../gitaly/troubleshooting_gitaly_cluster.md#check-cluster-health) before
+ running these commands.
The default path is `/var/opt/gitlab/git-data/repositories`. If `git_data_dirs`
is customized, check the directory layout on your server to be sure:
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 4744959ce13..7826b98a663 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -379,7 +379,7 @@ cause problems on some file systems. In this case, `54771` hashes to
#### Identify repositories on disk
-Use the [`praefect metadata`](troubleshooting.md#view-repository-metadata) subcommand to:
+Use the [`praefect metadata`](troubleshooting_gitaly_cluster.md#view-repository-metadata) subcommand to:
- Retrieve a repository's virtual storage and relative path from the metadata store. After you have the hashed storage path, you can use the Rails
console to retrieve the project path.
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index 53ec384ad0c..3a705196949 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -197,7 +197,7 @@ The following options are available:
[Relational Database Service](https://aws.amazon.com/rds/) is recommended.
Setting up PostgreSQL creates empty Praefect tables. For more information, see the
-[relevant troubleshooting section](troubleshooting.md#relation-does-not-exist-errors).
+[relevant troubleshooting section](troubleshooting_gitaly_cluster.md#relation-does-not-exist-errors).
#### Running GitLab and Praefect databases on the same server
@@ -287,7 +287,7 @@ praefect['configuration'] = {
```
If you see Praefect database errors after configuring PostgreSQL, see
-[troubleshooting steps](troubleshooting.md#relation-does-not-exist-errors).
+[troubleshooting steps](troubleshooting_gitaly_cluster.md#relation-does-not-exist-errors).
#### Reads distribution caching
@@ -1689,7 +1689,7 @@ To migrate existing clusters:
- If downtime is unacceptable:
- 1. Determine which Gitaly node is [the current primary](troubleshooting.md#determine-primary-gitaly-node).
+ 1. Determine which Gitaly node is [the current primary](troubleshooting_gitaly_cluster.md#determine-primary-gitaly-node).
1. Comment out the secondary Gitaly nodes from the virtual storage's configuration in `/etc/gitlab/gitlab.rb`
on all Praefect nodes. This ensures there's only one Gitaly node configured, causing both of the election
diff --git a/doc/administration/gitaly/troubleshooting.md b/doc/administration/gitaly/troubleshooting.md
index 6c355f79191..c8e000ad9e1 100644
--- a/doc/administration/gitaly/troubleshooting.md
+++ b/doc/administration/gitaly/troubleshooting.md
@@ -4,18 +4,17 @@ group: Gitaly
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
---
-# Troubleshooting Gitaly and Gitaly Cluster **(FREE SELF)**
+# Troubleshooting Gitaly **(FREE SELF)**
-Refer to the information below when troubleshooting Gitaly and Gitaly Cluster.
-
-## Troubleshoot Gitaly
+Refer to the information below when troubleshooting Gitaly. For information on troubleshooting Gitaly Cluster (Praefect),
+see [Troubleshooting Gitaly Cluster](troubleshooting_gitaly_cluster.md).
The following sections provide possible solutions to Gitaly errors.
See also [Gitaly timeout](../settings/gitaly_timeouts.md) settings,
and our advice on [parsing the `gitaly/current` file](../logs/log_parsing.md#parsing-gitalycurrent).
-### Check versions when using standalone Gitaly servers
+## Check versions when using standalone Gitaly servers
When using standalone Gitaly servers, you must make sure they are the same version
as GitLab to ensure full compatibility:
@@ -24,7 +23,7 @@ as GitLab to ensure full compatibility:
1. Select **Overview > Gitaly Servers**.
1. Confirm all Gitaly servers indicate that they are up to date.
-### Find storage resource details
+## Find storage resource details
You can run the following commands in a [Rails console](../operations/rails_console.md#starting-a-rails-console-session)
to determine the available and used space on a Gitaly storage:
@@ -35,7 +34,7 @@ Gitlab::GitalyClient::ServerService.new("default").storage_disk_statistics
Gitlab::GitalyClient::ServerService.new("<storage name>").disk_statistics
```
-### Use `gitaly-debug`
+## Use `gitaly-debug`
The `gitaly-debug` command provides "production debugging" tools for Gitaly and Git
performance. It is intended to help production engineers and support
@@ -47,7 +46,7 @@ To see the help page of `gitaly-debug` for a list of supported sub-commands, run
gitaly-debug -h
```
-### Commits, pushes, and clones return a 401
+## Commits, pushes, and clones return a 401
```plaintext
remote: GitLab: 401 Unauthorized
@@ -56,14 +55,14 @@ remote: GitLab: 401 Unauthorized
You need to sync your `gitlab-secrets.json` file with your GitLab
application nodes.
-### 500 and `fetching folder content` errors on repository pages
+## 500 and `fetching folder content` errors on repository pages
`Fetching folder content`, and in some cases `500`, errors indicate
connectivity problems between GitLab and Gitaly.
Consult the [client-side gRPC logs](#client-side-grpc-logs)
for details.
-### Client side gRPC logs
+## Client side gRPC logs
Gitaly uses the [gRPC](https://grpc.io/) RPC framework. The Ruby gRPC
client has its own log file which may contain helpful information when
@@ -90,7 +89,7 @@ Check whether `Verify return code` field indicates a
If `openssl` succeeds but `gitlab-rake gitlab:gitaly:check` fails,
check [certificate requirements](tls_support.md#certificate-requirements) for Gitaly.
-### Server side gRPC logs
+## Server side gRPC logs
gRPC tracing can also be enabled in Gitaly itself with the `GODEBUG=http2debug`
environment variable. To set this in a Linux package installation:
@@ -105,7 +104,7 @@ environment variable. To set this in a Linux package installation:
1. [Reconfigure](../restart_gitlab.md#reconfigure-a-linux-package-installation) GitLab.
-### Correlating Git processes with RPCs
+## Correlating Git processes with RPCs
Sometimes you need to find out which Gitaly RPC created a particular Git process.
@@ -123,7 +122,7 @@ sudo cat /proc/$PID/environ | tr '\0' '\n' | grep ^CORRELATION_ID=
This method isn't reliable for `git cat-file` processes, because Gitaly
internally pools and re-uses those across RPCs.
-### Repository changes fail with a `401 Unauthorized` error
+## Repository changes fail with a `401 Unauthorized` error
If you run Gitaly on its own server and notice these conditions:
@@ -224,7 +223,7 @@ the application might be fetching this secret from a different file. Your Gitaly
If that setting is missing, GitLab defaults to using `.gitlab_shell_secret` under
`/opt/gitlab/embedded/service/gitlab-rails/.gitlab_shell_secret`.
-### Repository pushes fail with `401 Unauthorized` and `JWT::VerificationError`
+## Repository pushes fail with `401 Unauthorized` and `JWT::VerificationError`
When attempting `git push`, you can see:
@@ -246,7 +245,7 @@ From GitLab 15.5, GitLab [authenticates with GitLab Shell using a JWT token inst
You should follow the [recommendations on upgrading external Gitaly](../../update/plan_your_upgrade.md#external-gitaly) and upgrade Gitaly before the GitLab
server.
-### Repository pushes fail with a `deny updating a hidden ref` error
+## Repository pushes fail with a `deny updating a hidden ref` error
Due to [a change](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3426)
introduced in GitLab 13.12, Gitaly has read-only, internal GitLab references that users are not
@@ -268,7 +267,7 @@ git push origin +refs/heads/*:refs/heads/* +refs/tags/*:refs/tags/*
Any other namespaces that the administrator wants to push can be included there as well via additional patterns.
-### Command-line tools cannot connect to Gitaly
+## Command-line tools cannot connect to Gitaly
gRPC cannot reach your Gitaly server if:
@@ -307,7 +306,7 @@ unset http_proxy
unset https_proxy
```
-### Permission denied errors appearing in Gitaly or Praefect logs when accessing repositories
+## Permission denied errors appearing in Gitaly or Praefect logs when accessing repositories
You might see the following in Gitaly and Praefect logs:
@@ -328,14 +327,14 @@ This information in the logs is a gRPC call
[error response code](https://grpc.github.io/grpc/core/md_doc_statuscodes.html).
If this error occurs, even though
-[the Gitaly auth tokens are set up correctly](#praefect-errors-in-logs),
+[the Gitaly auth tokens are set up correctly](troubleshooting_gitaly_cluster.md#praefect-errors-in-logs),
it's likely that the Gitaly servers are experiencing
[clock drift](https://en.wikipedia.org/wiki/Clock_drift).
Ensure the Gitaly clients and servers are synchronized, and use an NTP time
server to keep them synchronized.
-### Gitaly not listening on new address after reconfiguring
+## Gitaly not listening on new address after reconfiguring
When updating the `gitaly['configuration'][:listen_addr]` or `gitaly['configuration'][:prometheus_listen_addr]` values, Gitaly may
continue to listen on the old address after a `sudo gitlab-ctl reconfigure`.
@@ -343,7 +342,7 @@ continue to listen on the old address after a `sudo gitlab-ctl reconfigure`.
When this occurs, run `sudo gitlab-ctl restart` to resolve the issue. This should no longer be
necessary because [this issue](https://gitlab.com/gitlab-org/gitaly/-/issues/2521) is resolved.
-### Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly node
+## Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly node
If this error occurs even though file permissions are correct, it's likely that the Gitaly node is
experiencing [clock drift](https://en.wikipedia.org/wiki/Clock_drift).
@@ -351,7 +350,7 @@ experiencing [clock drift](https://en.wikipedia.org/wiki/Clock_drift).
Ensure that the GitLab and Gitaly nodes are synchronized and use an NTP time
server to keep them synchronized if possible.
-### Health check warnings
+## Health check warnings
The following warning in `/var/log/gitlab/praefect/current` can be ignored.
@@ -360,7 +359,7 @@ The following warning in `/var/log/gitlab/praefect/current` can be ignored.
"msg":"error when looking up method info"
```
-### File not found errors
+## File not found errors
The following errors in `/var/log/gitlab/gitaly/current` can be ignored.
They are caused by the GitLab Rails application checking for specific files
@@ -372,7 +371,7 @@ that do not exist in a repository.
"error":"not found: .gitlab-ci.yml"
```
-### Git pushes are slow when Dynatrace is enabled
+## Git pushes are slow when Dynatrace is enabled
Dynatrace can cause the `/opt/gitlab/embedded/bin/gitaly-hooks` reference transaction hook,
to take several seconds to start up and shut down. `gitaly-hooks` is executed twice when users
@@ -380,13 +379,13 @@ push, which causes a significant delay.
If Git pushes are too slow when Dynatrace is enabled, disable Dynatrace.
-### `gitaly check` fails with `401` status code
+## `gitaly check` fails with `401` status code
`gitaly check` can fail with `401` status code if Gitaly can't access the internal GitLab API.
One way to resolve this is to make sure the entry is correct for the GitLab internal API URL configured in `gitlab.rb` with `gitlab_rails['internal_api_url']`.
-### Changes (diffs) don't load for new merge requests when using Gitaly TLS
+## Changes (diffs) don't load for new merge requests when using Gitaly TLS
After enabling [Gitaly with TLS](tls_support.md), changes (diffs) for new merge requests are not generated
and you see the following message in GitLab:
@@ -423,7 +422,7 @@ and:
1. [Reconfigure GitLab](../restart_gitlab.md#reconfigure-a-linux-package-installation) so the certificates are symlinked
1. Restart Gitaly manually `sudo gitlab-ctl restart gitaly` for the certificates to be loaded by the Gitaly process.
-### Gitaly fails to fork processes stored on `noexec` file systems
+## Gitaly fails to fork processes stored on `noexec` file systems
Because of changes [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5999) in GitLab 14.10, applying the `noexec` option to a mount
point (for example, `/var`) causes Gitaly to throw `permission denied` errors related to forking processes. For example:
@@ -437,11 +436,11 @@ To resolve this, remove the `noexec` option from the file system mount. An alter
1. Add `gitaly['runtime_dir'] = '<PATH_WITH_EXEC_PERM>'` to `/etc/gitlab/gitlab.rb` and specify a location without `noexec` set.
1. Run `sudo gitlab-ctl reconfigure`.
-### Commit signing fails with `invalid argument: signing key is encrypted` or `invalid data: tag byte does not have MSB set.`
+## Commit signing fails with `invalid argument: signing key is encrypted` or `invalid data: tag byte does not have MSB set.`
Because Gitaly commit signing is headless and not associated with a specific user, the GPG signing key must be created without a passphrase, or the passphrase must be removed before export.
-### Gitaly logs show errors in `info` messages
+## Gitaly logs show errors in `info` messages
Because of a bug [introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/6201) in GitLab 16.3, additional entries were written to the
[Gitaly logs](../logs/index.md#gitaly-logs). These log entries contained `"level":"info"` but the `msg` string appeared to contain an error.
@@ -458,312 +457,6 @@ safe to ignore.
This bug was [fixed](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/6513/) in GitLab 16.4.5, 16.5.5, and 16.6.0, which prevents these types of messages from
being written to the Gitaly logs.
-## Troubleshoot Praefect (Gitaly Cluster)
-
-The following sections provide possible solutions to Gitaly Cluster errors.
-
-### Check cluster health
-
-> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5688) in GitLab 14.5.
-
-The `check` Praefect sub-command runs a series of checks to determine the health of the Gitaly Cluster.
-
-```shell
-gitlab-ctl praefect check
-```
-
-The following sections describe the checks that are run.
-
-#### Praefect migrations
-
-Because Database migrations must be up to date for Praefect to work correctly, checks if Praefect migrations are up to date.
-
-If this check fails:
-
-1. See the `schema_migrations` table in the database to see which migrations have run.
-1. Run `praefect sql-migrate` to bring the migrations up to date.
-
-#### Node connectivity and disk access
-
-Checks if Praefect can reach all of its Gitaly nodes, and if each Gitaly node has read and write access to all of its storages.
-
-If this check fails:
-
-1. Confirm the network addresses and tokens are set up correctly:
- - In the Praefect configuration.
- - In each Gitaly node's configuration.
-1. On the Gitaly nodes, check that the `gitaly` process being run as `git`. There might be a permissions issue that is preventing Gitaly from
- accessing its storage directories.
-1. Confirm that there are no issues with the network that connects Praefect to Gitaly nodes.
-
-#### Database read and write access
-
-Checks if Praefect can read from and write to the database.
-
-If this check fails:
-
-1. See if the Praefect database is in recovery mode. In recovery mode, tables may be read only. To check, run:
-
- ```sql
- select pg_is_in_recovery()
- ```
-
-1. Confirm that the user that Praefect uses to connect to PostgreSQL has read and write access to the database.
-1. See if the database has been placed into read-only mode. To check, run:
-
- ```sql
- show default_transaction_read_only
- ```
-
-#### Inaccessible repositories
-
-Checks how many repositories are inaccessible because they are missing a primary assignment, or their primary is unavailable.
-
-If this check fails:
-
-1. See if any Gitaly nodes are down. Run `praefect ping-nodes` to check.
-1. Check if there is a high load on the Praefect database. If the Praefect database is slow to respond, it can lead health checks failing to persist
- to the database, leading Praefect to think nodes are unhealthy.
-
-#### Check clock synchronization
-
-> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/4225) in GitLab 14.8.
-
-Authentication between Praefect and the Gitaly servers requires the server times to be
-in sync so the token check succeeds.
-
-This check helps identify the root cause of `permission denied`
-[errors being logged by Praefect](#permission-denied-errors-appearing-in-gitaly-or-praefect-logs-when-accessing-repositories).
-
-For offline environments where access to public `pool.ntp.org` servers is not possible, the Praefect `check` sub-command fails this
-check with an error message similar to:
-
-```plaintext
-checking with NTP service at and allowed clock drift 60000ms [correlation_id: <XXX>]
-Failed (fatal) error: gitaly node at tcp://[gitlab.example-instance.com]:8075: rpc error: code = DeadlineExceeded desc = context deadline exceeded
-```
-
-To resolve this issue, set an environment variable on all Praefect servers to point to an accessible internal NTP server. For example:
-
-```shell
-export NTP_HOST=ntp.example.com
-```
-
-### Praefect errors in logs
-
-If you receive an error, check `/var/log/gitlab/gitlab-rails/production.log`.
-
-Here are common errors and potential causes:
-
-- 500 response code
- - `ActionView::Template::Error (7:permission denied)`
- - `praefect['configuration'][:auth][:token]` and `gitlab_rails['gitaly_token']` do not match on the GitLab server.
- - `Unable to save project. Error: 7:permission denied`
- - Secret token in `praefect['configuration'][:virtual_storage]` on GitLab server does not match the
- value in `gitaly['auth_token']` on one or more Gitaly servers.
-- 503 response code
- - `GRPC::Unavailable (14:failed to connect to all addresses)`
- - GitLab was unable to reach Praefect.
- - `GRPC::Unavailable (14:all SubCons are in TransientFailure...)`
- - Praefect cannot reach one or more of its child Gitaly nodes. Try running
- the Praefect connection checker to diagnose.
-
-### Praefect database experiencing high CPU load
-
-Some common reasons for the Praefect database to experience elevated CPU usage include:
-
-- Prometheus metrics scrapes [running an expensive query](https://gitlab.com/gitlab-org/gitaly/-/issues/3796). If you have GitLab 14.2
- or above, set `praefect['configuration'][:prometheus_exclude_database_from_default_metrics] = true` in `gitlab.rb`.
-- [Read distribution caching](praefect.md#reads-distribution-caching) is disabled, increasing the number of queries made to the
- database when user traffic is high. Ensure read distribution caching is enabled.
-
-### Determine primary Gitaly node
-
-To determine the primary node of a repository:
-
-- In GitLab 14.6 and later, use the [`praefect metadata`](#view-repository-metadata) subcommand.
-- In GitLab 13.12 to GitLab 14.5 with [repository-specific primaries](praefect.md#repository-specific-primary-nodes),
- use the [`gitlab:praefect:replicas` Rake task](../raketasks/praefect.md#replica-checksums).
-- With legacy election strategies in GitLab 13.12 and earlier, the primary was the same for all repositories in a virtual storage.
- To determine the current primary Gitaly node for a specific virtual storage:
-
- - (Recommended) Use the `Shard Primary Election` [Grafana chart](praefect.md#grafana) on the
- [`Gitlab Omnibus - Praefect` dashboard](https://gitlab.com/gitlab-org/grafana-dashboards/-/blob/master/omnibus/praefect.json).
- - If you do not have Grafana set up, use the following command on each host of each
- Praefect node:
-
- ```shell
- curl localhost:9652/metrics | grep gitaly_praefect_primaries
- ```
-
-### View repository metadata
-
-> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/3481) in GitLab 14.6.
-
-Gitaly Cluster maintains a [metadata database](index.md#components) about the repositories stored on the cluster. Use the `praefect metadata` subcommand
-to inspect the metadata for troubleshooting.
-
-You can retrieve a repository's metadata by its Praefect-assigned repository ID:
-
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id <repository-id>
-```
-
-When the physical path on the physical storage starts with `@cluster`, you can
-[find the repository ID in the physical path](index.md#praefect-generated-replica-paths-gitlab-150-and-later).
-
-You can also retrieve a repository's metadata by its virtual storage and relative path:
-
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -virtual-storage <virtual-storage> -relative-path <relative-path>
-```
-
-#### Examples
-
-To retrieve the metadata for a repository with a Praefect-assigned repository ID of 1:
-
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id 1
-```
-
-To retrieve the metadata for a repository with virtual storage `default` and relative path `@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git`:
-
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -virtual-storage default -relative-path @hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git
-```
-
-Either of these examples retrieve the following metadata for an example repository:
-
-```plaintext
-Repository ID: 54771
-Virtual Storage: "default"
-Relative Path: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
-Replica Path: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
-Primary: "gitaly-1"
-Generation: 1
-Replicas:
-- Storage: "gitaly-1"
- Assigned: true
- Generation: 1, fully up to date
- Healthy: true
- Valid Primary: true
- Verified At: 2021-04-01 10:04:20 +0000 UTC
-- Storage: "gitaly-2"
- Assigned: true
- Generation: 0, behind by 1 changes
- Healthy: true
- Valid Primary: false
- Verified At: unverified
-- Storage: "gitaly-3"
- Assigned: true
- Generation: replica not yet created
- Healthy: false
- Valid Primary: false
- Verified At: unverified
-```
-
-#### Available metadata
-
-The metadata retrieved by `praefect metadata` includes the fields in the following tables.
-
-| Field | Description |
-|:------------------|:-------------------------------------------------------------------------------------------------------------------|
-| `Repository ID` | Permanent unique ID assigned to the repository by Praefect. Different to the ID GitLab uses for repositories. |
-| `Virtual Storage` | Name of the virtual storage the repository is stored in. |
-| `Relative Path` | Repository's path in the virtual storage. |
-| `Replica Path` | Where on the Gitaly node's disk the repository's replicas are stored. |
-| `Primary` | Current primary of the repository. |
-| `Generation` | Used by Praefect to track repository changes. Each write in the repository increments the repository's generation. |
-| `Replicas` | A list of replicas that exist or are expected to exist. |
-
-For each replica, the following metadata is available:
-
-| `Replicas` Field | Description |
-|:-----------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `Storage` | Name of the Gitaly storage that contains the replica. |
-| `Assigned` | Indicates whether the replica is expected to exist in the storage. Can be `false` if a Gitaly node is removed from the cluster or if the storage contains an extra copy after the repository's replication factor was decreased. |
-| `Generation` | Latest confirmed generation of the replica. It indicates:<br><br>- The replica is fully up to date if the generation matches the repository's generation.<br>- The replica is outdated if the replica's generation is less than the repository's generation.<br>- `replica not yet created` if the replica does not yet exist at all on the storage. |
-| `Healthy` | Indicates whether the Gitaly node that is hosting this replica is considered healthy by the consensus of Praefect nodes. |
-| `Valid Primary` | Indicates whether the replica is fit to serve as the primary node. If the repository's primary is not a valid primary, a failover occurs on the next write to the repository if there is another replica that is a valid primary. A replica is a valid primary if:<br><br>- It is stored on a healthy Gitaly node.<br>- It is fully up to date.<br>- It is not targeted by a pending deletion job from decreasing replication factor.<br>- It is assigned. |
-| `Verified At` | Indicates last successful verification of the replica by the [verification worker](praefect.md#repository-verification). If the replica has not yet been verified, `unverified` is displayed in place of the last successful verification time. Introduced in GitLab 15.0. |
-
-#### Command fails with 'repository not found'
-
-If the supplied value for `-virtual-storage` is incorrect, the command returns the following error:
-
-```plaintext
-get metadata: rpc error: code = NotFound desc = repository not found
-```
-
-The documented examples specify `-virtual-storage default`. Check the Praefect server setting `praefect['configuration'][:virtual_storage]` in `/etc/gitlab/gitlab.rb`.
-
-### Check that repositories are in sync
-
-Is [some cases](index.md#known-issues) the Praefect database can get out of sync with the underlying Gitaly nodes. To check that
-a given repository is fully synced on all nodes, run the [`gitlab:praefect:replicas` Rake task](../raketasks/praefect.md#replica-checksums) on your Rails node.
-This Rake task checksums the repository on all Gitaly nodes.
-
-The [Praefect `dataloss`](recovery.md#check-for-data-loss) command only checks the state of the repository in the Praefect database, and cannot
-be relied to detect sync problems in this scenario.
-
-### Relation does not exist errors
-
-By default Praefect database tables are created automatically by `gitlab-ctl reconfigure` task.
-
-However, the Praefect database tables are not created on initial reconfigure and can throw
-errors that relations do not exist if either:
-
-- The `gitlab-ctl reconfigure` command isn't executed.
-- Errors occur during the execution.
-
-For example:
-
-- `ERROR: relation "node_status" does not exist at character 13`
-- `ERROR: relation "replication_queue_lock" does not exist at character 40`
-- This error:
-
- ```json
- {"level":"error","msg":"Error updating node: pq: relation \"node_status\" does not exist","pid":210882,"praefectName":"gitlab1x4m:0.0.0.0:2305","time":"2021-04-01T19:26:19.473Z","virtual_storage":"praefect-cluster-1"}
- ```
-
-To solve this, the database schema migration can be done using `sql-migrate` sub-command of
-the `praefect` command:
-
-```shell
-$ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-migrate
-praefect sql-migrate: OK (applied 21 migrations)
-```
-
-### Requests fail with 'repository scoped: invalid Repository' errors
-
-This indicates that the virtual storage name used in the
-[Praefect configuration](praefect.md#praefect) does not match the storage name used in
-[`gitaly['configuration'][:storage][<index>][:name]` setting](praefect.md#gitaly) for GitLab.
-
-Resolve this by matching the virtual storage names used in Praefect and GitLab configuration.
-
-### Gitaly Cluster performance issues on cloud platforms
-
-Praefect does not require a lot of CPU or memory, and can run on small virtual machines.
-Cloud services may place other limits on the resources that small VMs can use, such as
-disk IO and network traffic.
-
-Praefect nodes generate a lot of network traffic. The following symptoms can be observed if their network bandwidth has
-been throttled by the cloud service:
-
-- Poor performance of Git operations.
-- High network latency.
-- High memory use by Praefect.
-
-Possible solutions:
-
-- Provision larger VMs to gain access to larger network traffic allowances.
-- Use your cloud service's monitoring and logging to check that the Praefect nodes are not exhausting their traffic allowances.
-
-### `gitlab-ctl reconfigure` fails with error: `STDOUT: praefect: configuration error: error reading config file: toml: cannot store TOML string into a Go int`
-
-This error occurs when `praefect['database_port']` or `praefect['database_direct_port']` are configured as a string instead of an integer.
-
## Profiling Gitaly
Gitaly exposes several of the Go built-in performance profiling tools on the Prometheus listen port. For example, if Prometheus is listening
diff --git a/doc/administration/gitaly/troubleshooting_gitaly_cluster.md b/doc/administration/gitaly/troubleshooting_gitaly_cluster.md
new file mode 100644
index 00000000000..9f1ae36b742
--- /dev/null
+++ b/doc/administration/gitaly/troubleshooting_gitaly_cluster.md
@@ -0,0 +1,312 @@
+---
+stage: Systems
+group: Gitaly
+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
+---
+
+# Troubleshooting Gitaly Cluster **(FREE SELF)**
+
+Refer to the information below when troubleshooting Gitaly Cluster (Praefect). For information on troubleshooting Gitaly,
+see [Troubleshooting Gitaly](troubleshooting.md).
+
+## Check cluster health
+
+> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5688) in GitLab 14.5.
+
+The `check` Praefect sub-command runs a series of checks to determine the health of the Gitaly Cluster.
+
+```shell
+gitlab-ctl praefect check
+```
+
+The following sections describe the checks that are run.
+
+### Praefect migrations
+
+Because Database migrations must be up to date for Praefect to work correctly, checks if Praefect migrations are up to date.
+
+If this check fails:
+
+1. See the `schema_migrations` table in the database to see which migrations have run.
+1. Run `praefect sql-migrate` to bring the migrations up to date.
+
+### Node connectivity and disk access
+
+Checks if Praefect can reach all of its Gitaly nodes, and if each Gitaly node has read and write access to all of its storages.
+
+If this check fails:
+
+1. Confirm the network addresses and tokens are set up correctly:
+ - In the Praefect configuration.
+ - In each Gitaly node's configuration.
+1. On the Gitaly nodes, check that the `gitaly` process being run as `git`. There might be a permissions issue that is preventing Gitaly from
+ accessing its storage directories.
+1. Confirm that there are no issues with the network that connects Praefect to Gitaly nodes.
+
+### Database read and write access
+
+Checks if Praefect can read from and write to the database.
+
+If this check fails:
+
+1. See if the Praefect database is in recovery mode. In recovery mode, tables may be read only. To check, run:
+
+ ```sql
+ select pg_is_in_recovery()
+ ```
+
+1. Confirm that the user that Praefect uses to connect to PostgreSQL has read and write access to the database.
+1. See if the database has been placed into read-only mode. To check, run:
+
+ ```sql
+ show default_transaction_read_only
+ ```
+
+### Inaccessible repositories
+
+Checks how many repositories are inaccessible because they are missing a primary assignment, or their primary is unavailable.
+
+If this check fails:
+
+1. See if any Gitaly nodes are down. Run `praefect ping-nodes` to check.
+1. Check if there is a high load on the Praefect database. If the Praefect database is slow to respond, it can lead health checks failing to persist
+ to the database, leading Praefect to think nodes are unhealthy.
+
+### Check clock synchronization
+
+> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/4225) in GitLab 14.8.
+
+Authentication between Praefect and the Gitaly servers requires the server times to be
+in sync so the token check succeeds.
+
+This check helps identify the root cause of `permission denied`
+[errors being logged by Praefect](troubleshooting.md#permission-denied-errors-appearing-in-gitaly-or-praefect-logs-when-accessing-repositories).
+
+For offline environments where access to public `pool.ntp.org` servers is not possible, the Praefect `check` sub-command fails this
+check with an error message similar to:
+
+```plaintext
+checking with NTP service at and allowed clock drift 60000ms [correlation_id: <XXX>]
+Failed (fatal) error: gitaly node at tcp://[gitlab.example-instance.com]:8075: rpc error: code = DeadlineExceeded desc = context deadline exceeded
+```
+
+To resolve this issue, set an environment variable on all Praefect servers to point to an accessible internal NTP server. For example:
+
+```shell
+export NTP_HOST=ntp.example.com
+```
+
+## Praefect errors in logs
+
+If you receive an error, check `/var/log/gitlab/gitlab-rails/production.log`.
+
+Here are common errors and potential causes:
+
+- 500 response code
+ - `ActionView::Template::Error (7:permission denied)`
+ - `praefect['configuration'][:auth][:token]` and `gitlab_rails['gitaly_token']` do not match on the GitLab server.
+ - `Unable to save project. Error: 7:permission denied`
+ - Secret token in `praefect['configuration'][:virtual_storage]` on GitLab server does not match the
+ value in `gitaly['auth_token']` on one or more Gitaly servers.
+- 503 response code
+ - `GRPC::Unavailable (14:failed to connect to all addresses)`
+ - GitLab was unable to reach Praefect.
+ - `GRPC::Unavailable (14:all SubCons are in TransientFailure...)`
+ - Praefect cannot reach one or more of its child Gitaly nodes. Try running
+ the Praefect connection checker to diagnose.
+
+## Praefect database experiencing high CPU load
+
+Some common reasons for the Praefect database to experience elevated CPU usage include:
+
+- Prometheus metrics scrapes [running an expensive query](https://gitlab.com/gitlab-org/gitaly/-/issues/3796). If you have GitLab 14.2
+ or above, set `praefect['configuration'][:prometheus_exclude_database_from_default_metrics] = true` in `gitlab.rb`.
+- [Read distribution caching](praefect.md#reads-distribution-caching) is disabled, increasing the number of queries made to the
+ database when user traffic is high. Ensure read distribution caching is enabled.
+
+## Determine primary Gitaly node
+
+To determine the primary node of a repository:
+
+- In GitLab 14.6 and later, use the [`praefect metadata`](#view-repository-metadata) subcommand.
+- In GitLab 13.12 to GitLab 14.5 with [repository-specific primaries](praefect.md#repository-specific-primary-nodes),
+ use the [`gitlab:praefect:replicas` Rake task](../raketasks/praefect.md#replica-checksums).
+- With legacy election strategies in GitLab 13.12 and earlier, the primary was the same for all repositories in a virtual storage.
+ To determine the current primary Gitaly node for a specific virtual storage:
+
+ - (Recommended) Use the `Shard Primary Election` [Grafana chart](praefect.md#grafana) on the
+ [`Gitlab Omnibus - Praefect` dashboard](https://gitlab.com/gitlab-org/grafana-dashboards/-/blob/master/omnibus/praefect.json).
+ - If you do not have Grafana set up, use the following command on each host of each
+ Praefect node:
+
+ ```shell
+ curl localhost:9652/metrics | grep gitaly_praefect_primaries
+ ```
+
+## View repository metadata
+
+> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/3481) in GitLab 14.6.
+
+Gitaly Cluster maintains a [metadata database](index.md#components) about the repositories stored on the cluster. Use the `praefect metadata` subcommand
+to inspect the metadata for troubleshooting.
+
+You can retrieve a repository's metadata by its Praefect-assigned repository ID:
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id <repository-id>
+```
+
+When the physical path on the physical storage starts with `@cluster`, you can
+[find the repository ID in the physical path](index.md#praefect-generated-replica-paths-gitlab-150-and-later).
+
+You can also retrieve a repository's metadata by its virtual storage and relative path:
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -virtual-storage <virtual-storage> -relative-path <relative-path>
+```
+
+### Examples
+
+To retrieve the metadata for a repository with a Praefect-assigned repository ID of 1:
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id 1
+```
+
+To retrieve the metadata for a repository with virtual storage `default` and relative path `@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git`:
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -virtual-storage default -relative-path @hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git
+```
+
+Either of these examples retrieve the following metadata for an example repository:
+
+```plaintext
+Repository ID: 54771
+Virtual Storage: "default"
+Relative Path: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
+Replica Path: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
+Primary: "gitaly-1"
+Generation: 1
+Replicas:
+- Storage: "gitaly-1"
+ Assigned: true
+ Generation: 1, fully up to date
+ Healthy: true
+ Valid Primary: true
+ Verified At: 2021-04-01 10:04:20 +0000 UTC
+- Storage: "gitaly-2"
+ Assigned: true
+ Generation: 0, behind by 1 changes
+ Healthy: true
+ Valid Primary: false
+ Verified At: unverified
+- Storage: "gitaly-3"
+ Assigned: true
+ Generation: replica not yet created
+ Healthy: false
+ Valid Primary: false
+ Verified At: unverified
+```
+
+### Available metadata
+
+The metadata retrieved by `praefect metadata` includes the fields in the following tables.
+
+| Field | Description |
+|:------------------|:-------------------------------------------------------------------------------------------------------------------|
+| `Repository ID` | Permanent unique ID assigned to the repository by Praefect. Different to the ID GitLab uses for repositories. |
+| `Virtual Storage` | Name of the virtual storage the repository is stored in. |
+| `Relative Path` | Repository's path in the virtual storage. |
+| `Replica Path` | Where on the Gitaly node's disk the repository's replicas are stored. |
+| `Primary` | Current primary of the repository. |
+| `Generation` | Used by Praefect to track repository changes. Each write in the repository increments the repository's generation. |
+| `Replicas` | A list of replicas that exist or are expected to exist. |
+
+For each replica, the following metadata is available:
+
+| `Replicas` Field | Description |
+|:-----------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `Storage` | Name of the Gitaly storage that contains the replica. |
+| `Assigned` | Indicates whether the replica is expected to exist in the storage. Can be `false` if a Gitaly node is removed from the cluster or if the storage contains an extra copy after the repository's replication factor was decreased. |
+| `Generation` | Latest confirmed generation of the replica. It indicates:<br><br>- The replica is fully up to date if the generation matches the repository's generation.<br>- The replica is outdated if the replica's generation is less than the repository's generation.<br>- `replica not yet created` if the replica does not yet exist at all on the storage. |
+| `Healthy` | Indicates whether the Gitaly node that is hosting this replica is considered healthy by the consensus of Praefect nodes. |
+| `Valid Primary` | Indicates whether the replica is fit to serve as the primary node. If the repository's primary is not a valid primary, a failover occurs on the next write to the repository if there is another replica that is a valid primary. A replica is a valid primary if:<br><br>- It is stored on a healthy Gitaly node.<br>- It is fully up to date.<br>- It is not targeted by a pending deletion job from decreasing replication factor.<br>- It is assigned. |
+| `Verified At` | Indicates last successful verification of the replica by the [verification worker](praefect.md#repository-verification). If the replica has not yet been verified, `unverified` is displayed in place of the last successful verification time. Introduced in GitLab 15.0. |
+
+### Command fails with 'repository not found'
+
+If the supplied value for `-virtual-storage` is incorrect, the command returns the following error:
+
+```plaintext
+get metadata: rpc error: code = NotFound desc = repository not found
+```
+
+The documented examples specify `-virtual-storage default`. Check the Praefect server setting `praefect['configuration'][:virtual_storage]` in `/etc/gitlab/gitlab.rb`.
+
+## Check that repositories are in sync
+
+Is [some cases](index.md#known-issues) the Praefect database can get out of sync with the underlying Gitaly nodes. To check that
+a given repository is fully synced on all nodes, run the [`gitlab:praefect:replicas` Rake task](../raketasks/praefect.md#replica-checksums) on your Rails node.
+This Rake task checksums the repository on all Gitaly nodes.
+
+The [Praefect `dataloss`](recovery.md#check-for-data-loss) command only checks the state of the repository in the Praefect database, and cannot
+be relied to detect sync problems in this scenario.
+
+## Relation does not exist errors
+
+By default Praefect database tables are created automatically by `gitlab-ctl reconfigure` task.
+
+However, the Praefect database tables are not created on initial reconfigure and can throw
+errors that relations do not exist if either:
+
+- The `gitlab-ctl reconfigure` command isn't executed.
+- Errors occur during the execution.
+
+For example:
+
+- `ERROR: relation "node_status" does not exist at character 13`
+- `ERROR: relation "replication_queue_lock" does not exist at character 40`
+- This error:
+
+ ```json
+ {"level":"error","msg":"Error updating node: pq: relation \"node_status\" does not exist","pid":210882,"praefectName":"gitlab1x4m:0.0.0.0:2305","time":"2021-04-01T19:26:19.473Z","virtual_storage":"praefect-cluster-1"}
+ ```
+
+To solve this, the database schema migration can be done using `sql-migrate` sub-command of
+the `praefect` command:
+
+```shell
+$ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-migrate
+praefect sql-migrate: OK (applied 21 migrations)
+```
+
+## Requests fail with 'repository scoped: invalid Repository' errors
+
+This indicates that the virtual storage name used in the
+[Praefect configuration](praefect.md#praefect) does not match the storage name used in
+[`gitaly['configuration'][:storage][<index>][:name]` setting](praefect.md#gitaly) for GitLab.
+
+Resolve this by matching the virtual storage names used in Praefect and GitLab configuration.
+
+## Gitaly Cluster performance issues on cloud platforms
+
+Praefect does not require a lot of CPU or memory, and can run on small virtual machines.
+Cloud services may place other limits on the resources that small VMs can use, such as
+disk IO and network traffic.
+
+Praefect nodes generate a lot of network traffic. The following symptoms can be observed if their network bandwidth has
+been throttled by the cloud service:
+
+- Poor performance of Git operations.
+- High network latency.
+- High memory use by Praefect.
+
+Possible solutions:
+
+- Provision larger VMs to gain access to larger network traffic allowances.
+- Use your cloud service's monitoring and logging to check that the Praefect nodes are not exhausting their traffic allowances.
+
+## `gitlab-ctl reconfigure` fails with error: `STDOUT: praefect: configuration error: error reading config file: toml: cannot store TOML string into a Go int`
+
+This error occurs when `praefect['database_port']` or `praefect['database_direct_port']` are configured as a string instead of an integer.
diff --git a/doc/administration/server_hooks.md b/doc/administration/server_hooks.md
index 562c8547d90..406964a117e 100644
--- a/doc/administration/server_hooks.md
+++ b/doc/administration/server_hooks.md
@@ -118,7 +118,7 @@ The location to copy the scripts to depends on where repositories are stored:
- In GitLab 15.3 and later, new repositories are created using
[Praefect-generated replica paths](gitaly/index.md#praefect-generated-replica-paths-gitlab-150-and-later),
which are not the hashed storage path. The replica path can be identified by
- [querying the Praefect repository metadata](../administration/gitaly/troubleshooting.md#view-repository-metadata)
+ [querying the Praefect repository metadata](../administration/gitaly/troubleshooting_gitaly_cluster.md#view-repository-metadata)
using `-relative-path` to specify the expected GitLab hashed storage path.
## Create global server hooks for all repositories
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 37515ddce91..f5198c54136 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -820,6 +820,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="queryrunnersactive"></a>`active` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated** in 14.8. This was renamed. Use: `paused`. |
| <a id="queryrunnerscreatorid"></a>`creatorId` | [`UserID`](#userid) | Filter runners by creator ID. |
+| <a id="queryrunnerscreatorusername"></a>`creatorUsername` **{warning-solid}** | [`String`](#string) | **Introduced** in 16.7. This feature is an Experiment. It can be changed or removed at any time. Filter runners by creator username. |
| <a id="queryrunnerspaused"></a>`paused` | [`Boolean`](#boolean) | Filter runners by `paused` (true) or `active` (false) status. |
| <a id="queryrunnerssearch"></a>`search` | [`String`](#string) | Filter by full token or partial text in description field. |
| <a id="queryrunnerssort"></a>`sort` | [`CiRunnerSort`](#cirunnersort) | Sort order of results. |
@@ -20313,6 +20314,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="grouprunnersactive"></a>`active` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated** in 14.8. This was renamed. Use: `paused`. |
| <a id="grouprunnerscreatorid"></a>`creatorId` | [`UserID`](#userid) | Filter runners by creator ID. |
+| <a id="grouprunnerscreatorusername"></a>`creatorUsername` **{warning-solid}** | [`String`](#string) | **Introduced** in 16.7. This feature is an Experiment. It can be changed or removed at any time. Filter runners by creator username. |
| <a id="grouprunnersmembership"></a>`membership` | [`CiRunnerMembershipFilter`](#cirunnermembershipfilter) | Control which runners to include in the results. |
| <a id="grouprunnerspaused"></a>`paused` | [`Boolean`](#boolean) | Filter runners by `paused` (true) or `active` (false) status. |
| <a id="grouprunnerssearch"></a>`search` | [`String`](#string) | Filter by full token or partial text in description field. |
@@ -25651,6 +25653,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="projectrunnersactive"></a>`active` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated** in 14.8. This was renamed. Use: `paused`. |
| <a id="projectrunnerscreatorid"></a>`creatorId` | [`UserID`](#userid) | Filter runners by creator ID. |
+| <a id="projectrunnerscreatorusername"></a>`creatorUsername` **{warning-solid}** | [`String`](#string) | **Introduced** in 16.7. This feature is an Experiment. It can be changed or removed at any time. Filter runners by creator username. |
| <a id="projectrunnerspaused"></a>`paused` | [`Boolean`](#boolean) | Filter runners by `paused` (true) or `active` (false) status. |
| <a id="projectrunnerssearch"></a>`search` | [`String`](#string) | Filter by full token or partial text in description field. |
| <a id="projectrunnerssort"></a>`sort` | [`CiRunnerSort`](#cirunnersort) | Sort order of results. |
diff --git a/doc/architecture/blueprints/google_artifact_registry_integration/backend.md b/doc/architecture/blueprints/google_artifact_registry_integration/backend.md
index 8213e3ede32..0e2c528a8b0 100644
--- a/doc/architecture/blueprints/google_artifact_registry_integration/backend.md
+++ b/doc/architecture/blueprints/google_artifact_registry_integration/backend.md
@@ -32,7 +32,7 @@ We can't build this feature on the GitLab side because this will require to walk
It would be better to centralize the access to the official Ruby client. This way, it's very easy to check for permissions.
-We suggest having a custom client class located in `Integrations::GoogleCloudPlatform::ArtifactRegistry::Client`. That class will need to require a `User` and a `Integrations::GoogleCloudPlatform::ArtifactRegistry` (see [Project Integration](#project-integration)).
+We suggest having a custom client class located in `GoogleCloudPlatform::ArtifactRegistry::Client`. That class will need to require a `User` and a `Integrations::GoogleCloudPlatform::ArtifactRegistry` (see [Project Integration](#project-integration)).
The client will then need to expose three functions: `#repository`, `#docker_images` and `#docker_image` that will be mapped to the similarly name functions of the official client.
@@ -81,18 +81,18 @@ In order to support the other repository formats in follow ups, we choose to not
All GraphQL changes should be marked as [`alpha`](../../../development/api_graphql_styleguide.md#mark-schema-items-as-alpha).
-First, on the [`ProjectType`](../../../api/graphql/reference/index.md#project), we will need a new field `google_cloud_platform_artifact_registry_repository_artifacts`. This will return a list of an [abstract](../../../api/graphql/reference/index.md#abstract-types) new type: `Integrations::GoogleCloudPlatform::ArtifactRegistry::ArtifactType`. This list will have pagination support. Ordering options will be available.
+First, on the [`ProjectType`](../../../api/graphql/reference/index.md#project), we will need a new field `google_cloud_platform_artifact_registry_repository_artifacts`. This will return a list of an [abstract](../../../api/graphql/reference/index.md#abstract-types) new type: `GoogleCloudPlatform::ArtifactRegistry::ArtifactType`. This list will have pagination support. Ordering options will be available.
-We will have `Integrations::GoogleCloudPlatform::ArtifactRegistry::DockerImage` as a concrete type of `Integrations::GoogleCloudPlatform::ArtifactRegistry::ArtifactType` with the following fields:
+We will have `GoogleCloudPlatform::ArtifactRegistry::DockerImage` as a concrete type of `GoogleCloudPlatform::ArtifactRegistry::ArtifactType` with the following fields:
- `name`. A string.
- `uri`. A string.
- `image_size_bytes`. A integer.
- `upload_time`. A timestamp.
-Then, we will need a new query `Query.google_cloud_platform_registry_registry_artifact_details` that given a name of a `Integrations::GoogleCloudPlatform::ArtifactRegistry::DockerImage` will return a single `Integrations::GoogleCloudPlatform::ArtifactRegistry::ArtifacDetailsType` with the following fields:
+Then, we will need a new query `Query.google_cloud_platform_registry_registry_artifact_details` that given a name of a `GoogleCloudPlatform::ArtifactRegistry::DockerImage` will return a single `GoogleCloudPlatform::ArtifactRegistry::ArtifacDetailsType` with the following fields:
-- all fields of `Integrations::GoogleCloudPlatform::ArtifactRegistry::ArtifactType`.
+- all fields of `GoogleCloudPlatform::ArtifactRegistry::ArtifactType`.
- `tags`. An array of strings.
- `media_type`. A string.
- `build_time`. A timestamp.
diff --git a/doc/security/unlock_user.md b/doc/security/unlock_user.md
index 179fd5eae3e..9a35673ab8e 100644
--- a/doc/security/unlock_user.md
+++ b/doc/security/unlock_user.md
@@ -31,7 +31,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
If 2FA is not enabled users are locked after three failed sign-in attempts within 24 hours. These users remain locked until:
- Their next successful sign-in, at which point they are sent an email with a six-digit unlock code and redirected to a verification page where they can unlock their account by entering the code.
-- GitLab Support [manually unlock](https://about.gitlab.com/handbook/support/workflows/reinstating-blocked-accounts.html#manual-unlock) the account after account ownership is verified.
+- GitLab Support [manually unlock](https://about.gitlab.com/handbook/support/workflows/reinstating-blocked-accounts/#manual-unlock) the account after account ownership is verified.
If 2FA is enabled, users are locked after three failed sign-in attempts. Accounts are unlocked automatically after 30 minutes.
diff --git a/doc/update/versions/gitlab_15_changes.md b/doc/update/versions/gitlab_15_changes.md
index 203d13a20e6..c1eb034f7f5 100644
--- a/doc/update/versions/gitlab_15_changes.md
+++ b/doc/update/versions/gitlab_15_changes.md
@@ -635,7 +635,7 @@ A [license caching issue](https://gitlab.com/gitlab-org/gitlab/-/issues/376706)
creating, deleting, and renaming Git repositories.
To identify the replica path,
- [query the Praefect repository metadata](../../administration/gitaly/troubleshooting.md#view-repository-metadata)
+ [query the Praefect repository metadata](../../administration/gitaly/troubleshooting_gitaly_cluster.md#view-repository-metadata)
and pass the `@hashed` storage path to `-relative-path`.
With this information, you can correctly install
diff --git a/doc/user/project/integrations/gitlab_slack_app_troubleshooting.md b/doc/user/project/integrations/gitlab_slack_app_troubleshooting.md
index 3a1bc746d5b..5a0e3458107 100644
--- a/doc/user/project/integrations/gitlab_slack_app_troubleshooting.md
+++ b/doc/user/project/integrations/gitlab_slack_app_troubleshooting.md
@@ -28,7 +28,7 @@ GitLab error: project or alias not found
To resolve this issue, ensure:
- The project full path is correct.
-- If using a [project alias](gitlab_slack_application.md#create-a-project-alias-for-slash-commands), the alias is correct.
+- If using a [project alias](gitlab_slack_application.md#create-a-project-alias), the alias is correct.
- The GitLab for Slack app is [enabled for the project](gitlab_slack_application.md#from-project-integration-settings).
## Slash commands return `dispatch_failed` in Slack
@@ -46,4 +46,4 @@ If you're not receiving notifications to a Slack channel, ensure:
## App Home does not display properly
-If the [App Home](https://api.slack.com/start/overview#app_home) does not display properly, ensure your [app is up to date](gitlab_slack_application.md#update-the-gitlab-for-slack-app).
+If the [App Home](https://api.slack.com/start/overview#app_home) does not display properly, ensure your [app is up to date](gitlab_slack_application.md#reinstall-the-gitlab-for-slack-app).
diff --git a/doc/user/project/integrations/gitlab_slack_application.md b/doc/user/project/integrations/gitlab_slack_application.md
index 0a42b363eb6..3664c56824d 100644
--- a/doc/user/project/integrations/gitlab_slack_application.md
+++ b/doc/user/project/integrations/gitlab_slack_application.md
@@ -24,7 +24,7 @@ Prerequisites:
In GitLab 15.0 and later, the GitLab for Slack app uses
[granular permissions](https://medium.com/slack-developer-blog/more-precision-less-restrictions-a3550006f9c3).
-Although functionality has not changed, you should [reinstall the app](#update-the-gitlab-for-slack-app).
+Although functionality has not changed, you should [reinstall the app](#reinstall-the-gitlab-for-slack-app).
### From project integration settings
@@ -36,9 +36,6 @@ To install the GitLab for Slack app from project integration settings:
1. Select **Install GitLab for Slack app**.
1. On the Slack confirmation page, select **Allow**.
-To update the app in your Slack workspace to the latest version,
-you can also select **Reinstall GitLab for Slack app**.
-
### From the Slack App Directory **(FREE SAAS)**
On GitLab.com, you can also install the GitLab for Slack app from the
@@ -49,17 +46,18 @@ To install the GitLab for Slack app from the Slack App Directory:
1. Go to the [GitLab for Slack page](https://gitlab.com/-/profile/slack/edit).
1. Select a GitLab project to link with your Slack workspace.
-## Update the GitLab for Slack app
+## Reinstall the GitLab for Slack app
-When GitLab releases new features for the GitLab for Slack app, you might have to manually update your app to use the new features.
+When GitLab releases new features for the GitLab for Slack app, you might have to reinstall the app to use these features.
-To update your GitLab for Slack app:
+To reinstall the GitLab for Slack app:
-1. On the left sidebar, select **Search or go to** and find a project for
- which the GitLab for Slack app is configured.
+1. On the left sidebar, select **Search or go to** and find a project
+ where the GitLab for Slack app is [installed](#install-the-gitlab-for-slack-app).
1. Select **Settings > Integrations**.
1. Select **GitLab for Slack app**.
1. Select **Reinstall GitLab for Slack app**.
+1. On the Slack confirmation page, select **Allow**.
The GitLab for Slack app is updated for all projects that use the integration.
@@ -67,17 +65,18 @@ Alternatively, you can [configure the integration](https://about.gitlab.com/solu
## Slash commands
-You can use slash commands to run common GitLab operations. Replace `<project>` with a project full path.
+You can use slash commands to run common GitLab operations.
-**For the GitLab for Slack app**:
+For the GitLab for Slack app:
- You must authorize your Slack user on GitLab.com when you run your first slash command.
-- You can [create a shorter project alias](#create-a-project-alias-for-slash-commands) for slash commands.
+- You can [create a project alias](#create-a-project-alias) for slash commands.
-**For [Slack slash commands](slack_slash_commands.md) on self-managed GitLab and [Mattermost slash commands](mattermost_slash_commands.md)**,
-replace `/gitlab` with the slash command trigger name configured for your integration.
+The following slash commands are available in GitLab:
-The following slash commands are available:
+- For [Slack slash commands](slack_slash_commands.md) on self-managed GitLab and [Mattermost slash commands](mattermost_slash_commands.md),
+ replace `/gitlab` with the trigger name of the slash command you've configured for the integration.
+- Replace `<project>` with a project full path.
| Command | Description |
| ------- | ----------- |
@@ -85,88 +84,90 @@ The following slash commands are available:
| `/gitlab <project> issue new <title>` <kbd>Shift</kbd>+<kbd>Enter</kbd> `<description>` | Creates a new issue with the title `<title>` and description `<description>`. |
| `/gitlab <project> issue show <id>` | Shows the issue with the ID `<id>`. |
| `/gitlab <project> issue close <id>` | Closes the issue with the ID `<id>`. |
-| `/gitlab <project> issue search <query>` | Shows up to five issues matching `<query>`. |
+| `/gitlab <project> issue search <query>` | Shows up to five issues that match `<query>`. |
| `/gitlab <project> issue move <id> to <project>` | Moves the issue with the ID `<id>` to `<project>`. |
| `/gitlab <project> issue comment <id>` <kbd>Shift</kbd>+<kbd>Enter</kbd> `<comment>` | Adds a new comment with the comment body `<comment>` to the issue with the ID `<id>`. |
-| `/gitlab <project> deploy <from> to <to>` | [Deploys](#the-deploy-slash-command) from the `<from>` environment to the `<to>` environment. |
+| `/gitlab <project> deploy <from> to <to>` | [Deploys](#deploy-command) from the `<from>` environment to the `<to>` environment. |
| `/gitlab <project> run <job name> <arguments>` | Executes the [ChatOps](../../../ci/chatops/index.md) job `<job name>` on the default branch. |
-| `/gitlab incident declare` | Opens a dialog to [create a new incident from Slack](../../../operations/incident_management/slack.md) (Beta). |
+| `/gitlab incident declare` | Opens a dialog to [create a new incident from Slack](../../../operations/incident_management/slack.md). |
-### The `deploy` slash command
+### `deploy` command
-To deploy to an environment, GitLab tries to find a deployment manual action in the pipeline.
+To deploy to an environment, GitLab tries to find a manual deployment action in the pipeline.
-If only one action is defined for a given environment, it is triggered.
-If more than one action is defined, GitLab tries to find an action name
-that matches the environment name to deploy to.
+If only one deployment action is defined for an environment, that action is triggered.
+If more than one deployment action is defined, GitLab tries to find an action name
+that matches the environment name.
-The command returns an error if no matching action is found.
+The command returns an error if GitLab cannot find a matching deployment action.
-### Create a project alias for slash commands
+### Create a project alias
-By default, slash commands expect a project full path. To create a shorter project alias in the GitLab for Slack app:
+By default, slash commands expect a project full path. To create a project alias in the GitLab for Slack app:
-1. On the left sidebar, select **Search or go to** and find your project.
+1. On the left sidebar, select **Search or go to** and find a project
+ where the GitLab for Slack app is [installed](#install-the-gitlab-for-slack-app).
1. Select **Settings > Integrations**.
1. Select **GitLab for Slack app**.
-1. The current **Project Alias**, if any, is displayed. To edit this value,
- select **Edit**.
-1. Enter your desired alias, and select **Save changes**.
+1. Next to the project path or alias, select **Edit**.
+1. Enter the new alias and select **Save changes**.
## Slack notifications
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/381012) in GitLab 15.9.
-With Slack notifications, GitLab can send messages to Slack workspace channels for certain GitLab [events](#notification-events).
+You can receive notifications to Slack channels for certain GitLab [events](#notification-events).
### Configure notifications
To configure Slack notifications:
-1. On the left sidebar, select **Search or go to** and find a project for
- which the GitLab for Slack app is [installed](#install-the-gitlab-for-slack-app).
+1. On the left sidebar, select **Search or go to** and find a project
+ where the GitLab for Slack app is [installed](#install-the-gitlab-for-slack-app).
1. Select **Settings > Integrations**.
1. Select **GitLab for Slack app**.
-1. In the **Trigger** section, select the checkbox for each GitLab
- event you want to receive a notification for in Slack. For a full list, see
- [Notification events](#notification-events).
-1. For each checkbox you select, enter the name of the channel that receives the notifications (for example, `#my-channel`).
- - To send notifications to multiple Slack channels, enter up to 10 channel names separated by commas (for example, `#channel-one, #channel-two`).
-
- NOTE:
- If the channel is private, you must also [add the GitLab for Slack app to the private channel](#receive-notifications-to-a-private-channel).
-
-1. Select the **Notify only broken pipelines** checkbox to notify only on failures.
-1. From the **Branches for which notifications are to be sent** dropdown list, select which branches you want to receive notifications (if relevant to your events).
-1. Leave the **Labels to be notified** text box blank to receive all notifications, or
- add labels the issue or merge request must have to trigger a
- notification.
+1. In the **Trigger** section:
+ - Select the checkbox for each GitLab [event](#notification-events) you want to receive notifications for in Slack.
+ - For each checkbox you select, enter the names of the Slack channels you want to receive notifications.
+ You can enter up to 10 channel names separated by commas (for example, `#channel-one, #channel-two`).
+
+ NOTE:
+ If the Slack channel is private, you must [add the GitLab for Slack app to the channel](#receive-notifications-to-a-private-channel).
+
+1. Optional. In the **Notification settings** section:
+ - Select the **Notify only broken pipelines** checkbox
+ to receive notifications for failed pipelines only.
+ - From the **Branches for which notifications are to be sent** dropdown list,
+ select the branches you want to receive notifications for.
+ - For **Labels to be notified**, enter any or all of the labels a GitLab
+ issue, merge request, or comment must have to receive notifications for.
+ Leave blank to receive notifications for all events.
+1. Optional. Select **Test settings**.
1. Select **Save changes**.
-Your Slack workspace can now start receiving GitLab event notifications.
-
### Receive notifications to a private channel
To receive notifications to a private Slack channel, you must add the GitLab for Slack app to the channel:
-1. Mention the app in the channel by typing `@GitLab` and pressing <kbd>Enter</kbd>.
+1. Mention the app in the channel by entering `@GitLab`.
1. Select **Add to Channel**.
### Notification events
-The following events are available for Slack notifications:
-
-| Event name | Description |
-|--------------------------------------------------------------------------|------------------------------------------------------|
-| **Push** | A push to the repository. |
-| **Issue** | An issue is created, updated, or closed. |
-| **Confidential issue** | A confidential issue is created, updated, or closed. |
-| **Merge request** | A merge request is created, updated, or merged. |
-| **Note** | A comment is added. |
-| **Confidential note** | A confidential note is added. |
-| **Tag push** | A new tag is pushed to the repository. |
-| **Pipeline** | A pipeline status changed. |
-| **Wiki page** | A wiki page is created or updated. |
-| **Deployment** | A deployment starts or finishes. |
-| **Alert** | A new, unique alert is recorded. |
-| [**Vulnerability**](../../application_security/vulnerabilities/index.md) | A new, unique vulnerability is recorded. |
+The following GitLab events are available for Slack notifications:
+
+| Event | Description |
+|----------------------------------------------------------------------|---------------------------------------------------------------|
+| Push | A push is made to the repository. |
+| Issue | An issue is created, closed, or reopened. |
+| Confidential issue | A confidential issue is created, closed, or reopened. |
+| Merge request | A merge request is created, merged, closed, or reopened. |
+| Note | A comment is added. |
+| Confidential note | An internal note or comment on a confidential issue is added. |
+| Tag push | A tag is pushed to the repository or removed. |
+| Pipeline | A pipeline status changes. |
+| Wiki page | A wiki page is created or updated. |
+| Deployment | A deployment is started or finished. |
+| [Incident](../../../operations/incident_management/slack.md) | An incident is created, closed, or reopened. |
+| [Vulnerability](../../application_security/vulnerabilities/index.md) | A new, unique vulnerability is recorded. |
+| Alert | A new, unique alert is recorded. |
diff --git a/doc/user/project/integrations/slack_slash_commands.md b/doc/user/project/integrations/slack_slash_commands.md
index 49fbd0eb694..a5a6d80e75b 100644
--- a/doc/user/project/integrations/slack_slash_commands.md
+++ b/doc/user/project/integrations/slack_slash_commands.md
@@ -27,7 +27,7 @@ Slack slash commands are scoped to a project. To configure Slack slash commands:
1. Select **Settings > Integrations**.
1. Select **Slack slash commands** and leave this browser tab open.
1. In a new browser tab, sign in to Slack and [add a new slash command](https://my.slack.com/services/new/slash-commands).
-1. Enter a slash command trigger name. You could use the project name.
+1. Enter a trigger name for the slash command. You could use the project name.
1. Select **Add Slash Command Integration**.
1. In the Slack browser tab:
1. Complete the fields with information from the GitLab browser tab.
diff --git a/lib/gitlab/cleanup/personal_access_tokens.rb b/lib/gitlab/cleanup/personal_access_tokens.rb
index a1e4b5765c2..fbc8c24f3cc 100644
--- a/lib/gitlab/cleanup/personal_access_tokens.rb
+++ b/lib/gitlab/cleanup/personal_access_tokens.rb
@@ -56,13 +56,15 @@ module Gitlab
.active
.owner_is_human
.created_before(cut_off_date)
- .for_users(group.users)
+ .for_users(group.group_members.select(:user_id))
+ .allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/436661")
else
PersonalAccessToken
.active
.owner_is_human
.last_used_before_or_unused(cut_off_date)
- .for_users(group.users)
+ .for_users(group.group_members.select(:user_id))
+ .allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/436661")
end
end
@@ -72,9 +74,12 @@ module Gitlab
# updated
attrs = access_tokens.as_json(only: [:id, :user_id])
- # Use `update_all` to bypass any validations which might
- # prevent revocation. Manually specify updated_at.
- affected_row_count = dry_run ? 0 : access_tokens.update_all(revoked: true, updated_at: @revocation_time)
+ cross_joins_issue = "https://gitlab.com/gitlab-org/gitlab/-/issues/436661"
+ affected_row_count = ::Gitlab::Database.allow_cross_joins_across_databases(url: cross_joins_issue) do
+ # Use `update_all` to bypass any validations which might
+ # prevent revocation. Manually specify updated_at.
+ dry_run ? 0 : access_tokens.update_all(revoked: true, updated_at: @revocation_time)
+ end
message = {
dry_run: dry_run,
diff --git a/lib/gitlab/hook_data/project_builder.rb b/lib/gitlab/hook_data/project_builder.rb
index 1f7459e57af..6e24f99a498 100644
--- a/lib/gitlab/hook_data/project_builder.rb
+++ b/lib/gitlab/hook_data/project_builder.rb
@@ -54,10 +54,10 @@ module Gitlab
# Can be consolidate again once https://gitlab.com/gitlab-org/gitlab/-/issues/432606 is addressed
if project.group
project.group.all_owner_members.select(:id, :user_id)
- .preload_user.find_each.map { |member| owner_data(member.user) if member.user }
+ .preload_users.find_each.map { |member| owner_data(member.user) if member.user }
else
data = []
- project.project_authorizations.owners.preload_user.each_batch(column: :user_id) do |relation|
+ project.project_authorizations.owners.preload_users.each_batch(column: :user_id) do |relation|
data.concat(relation.map { |member| owner_data(member.user) })
end
data |= Array.wrap(owner_data(project.owner)) if project.owner
diff --git a/lib/gitlab/project_authorizations.rb b/lib/gitlab/project_authorizations.rb
index 0fcb8321dae..a3a14439b74 100644
--- a/lib/gitlab/project_authorizations.rb
+++ b/lib/gitlab/project_authorizations.rb
@@ -12,46 +12,6 @@ module Gitlab
end
def calculate
- if Feature.enabled?(:compare_project_authorization_linear_cte, user)
- linear_relation = calculate_with_linear_query
- recursive_relation = calculate_with_recursive_query
- recursive_set = Set.new(recursive_relation.to_a.pluck(:project_id, :access_level))
- linear_set = Set.new(linear_relation.to_a.pluck(:project_id, :access_level))
- if linear_set == recursive_set
- Gitlab::AppJsonLogger.info(event: 'linear_authorized_projects_check',
- user_id: user.id,
- matching_results: true)
- return calculate_with_linear_query
- else
- Gitlab::AppJsonLogger.warn(event: 'linear_authorized_projects_check',
- user_id: user.id,
- matching_results: false)
- end
- end
-
- Gitlab::AppJsonLogger.info(event: 'linear_authorized_projects_check_with_flag',
- feature_flag_status: Feature.enabled?(:linear_project_authorization, user))
-
- if Feature.enabled?(:linear_project_authorization, user)
- calculate_with_linear_query
- else
- calculate_with_recursive_query
- end
- end
-
- private
-
- def calculate_with_linear_query
- cte = linear_cte
- cte_alias = cte.table.alias(Group.table_name)
-
- ProjectAuthorization
- .unscoped
- .with(cte.to_arel)
- .select_from_union(relations(cte_alias: cte_alias))
- end
-
- def calculate_with_recursive_query
cte = recursive_cte
cte_alias = cte.table.alias(Group.table_name)
@@ -62,6 +22,8 @@ module Gitlab
.select_from_union(relations(cte_alias: cte_alias))
end
+ private
+
# Builds a recursive CTE that gets all the groups the current user has
# access to, including any nested groups and any shared groups.
def recursive_cte
@@ -97,32 +59,6 @@ module Gitlab
cte
end
- def linear_cte
- # Groups shared with user and their parent groups
- shared_groups = Group
- .select("namespaces.id, MAX(LEAST(members.access_level, group_group_links.group_access)) as access_level")
- .joins("INNER JOIN group_group_links ON group_group_links.shared_group_id = namespaces.id
- OR namespaces.traversal_ids @> ARRAY[group_group_links.shared_group_id::int]")
- .joins("INNER JOIN members ON group_group_links.shared_with_group_id = members.source_id")
- .merge(user.group_members)
- .merge(GroupMember.active_state)
- .group("namespaces.id")
-
- # Groups the user is a member of and their parent groups.
- lateral_query = Group.as_ids.where("namespaces.traversal_ids @> ARRAY [members.source_id]")
- member_groups_with_ancestors = GroupMember.select("namespaces.id, MAX(members.access_level) as access_level")
- .joins("CROSS JOIN LATERAL (#{lateral_query.to_sql}) as namespaces")
- .group("namespaces.id")
- .merge(user.group_members)
- .merge(GroupMember.active_state)
-
- union = Namespace
- .select("namespaces.id, access_level")
- .from_union([shared_groups, member_groups_with_ancestors])
-
- Gitlab::SQL::CTE.new(:linear_namespaces_cte, union)
- end
-
# Builds a LEFT JOIN to join optional memberships onto the CTE.
def join_members_on_namespaces
members = Member.arel_table
diff --git a/lib/tasks/gitlab/seed/group_seed.rake b/lib/tasks/gitlab/seed/group_seed.rake
index cc9180d56a3..c9b901b92c5 100644
--- a/lib/tasks/gitlab/seed/group_seed.rake
+++ b/lib/tasks/gitlab/seed/group_seed.rake
@@ -147,7 +147,7 @@ class GroupSeeder
epic_params = {
title: FFaker::Lorem.sentence(6),
description: FFaker::Lorem.paragraphs(3).join("\n\n"),
- author: group.users.sample,
+ author: group.group_members.non_invite.sample.user,
group: group
}
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index e262305d5be..024e188bcba 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -31385,7 +31385,7 @@ msgstr ""
msgid "MlModelRegistry|Versions"
msgstr ""
-msgid "MlModelRegistry|· No other versions"
+msgid "MlModelRegistry|· %d version"
msgid_plural "MlModelRegistry|· %d versions"
msgstr[0] ""
msgstr[1] ""
@@ -44041,7 +44041,7 @@ msgstr ""
msgid "SecurityOrchestration|Enabled"
msgstr ""
-msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
+msgid "SecurityOrchestration|Enforce %{linkStart}security policies%{linkEnd} for this project."
msgstr ""
msgid "SecurityOrchestration|Every time a pipeline runs for %{branches}%{branchExceptionsString}"
@@ -51679,6 +51679,9 @@ msgstr ""
msgid "Tracing|Duration (ms)"
msgstr ""
+msgid "Tracing|Error"
+msgstr ""
+
msgid "Tracing|Error: Failed to load trace details. Try reloading the page."
msgstr ""
@@ -51727,6 +51730,9 @@ msgstr ""
msgid "Tracing|Metadata"
msgstr ""
+msgid "Tracing|Ok"
+msgstr ""
+
msgid "Tracing|Operation"
msgstr ""
@@ -51742,6 +51748,9 @@ msgstr ""
msgid "Tracing|Service"
msgstr ""
+msgid "Tracing|Status"
+msgstr ""
+
msgid "Tracing|Time range"
msgstr ""
@@ -53231,6 +53240,9 @@ msgstr ""
msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
msgstr ""
+msgid "User caps is enabled for this group, visit the %{pending_members_link_start}pending members%{pending_members_link_end} page to manage them."
+msgstr ""
+
msgid "User created at"
msgstr ""
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index a08fab8efa9..8c6c4d29f62 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -408,7 +408,7 @@ module QA
# Revisit after merge page re-architect is done https://gitlab.com/gitlab-org/gitlab/-/issues/300042
# To remove page refresh logic if possible
wait_until_ready_to_merge
- wait_until { !find_element('merge-button').text.include?('when pipeline succeeds') } # rubocop:disable Rails/NegateInclude
+ wait_until { !find_element('merge-button').text.include?('auto-merge') } # rubocop:disable Rails/NegateInclude
click_element('merge-button')
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb
index 206964cb9bf..c00dbf1b0b8 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb
@@ -5,7 +5,7 @@ module QA
describe 'Repository tags', :reliable, product_group: :source_code, quarantine: {
type: :flaky,
issue: "https://gitlab.com/gitlab-org/gitlab/-/issues/438349",
- only: { job: 'gdk-qa-reliable' }
+ only: { job: /gdk-qa-.*/ }
} do
let(:project) { create(:project, :with_readme, name: 'project-for-tags') }
let(:developer_user) do
diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb
index feebdd972aa..f806563928e 100644
--- a/spec/controllers/groups/group_members_controller_spec.rb
+++ b/spec/controllers/groups/group_members_controller_spec.rb
@@ -337,7 +337,7 @@ RSpec.describe Groups::GroupMembersController do
expect(controller).to set_flash.to "You left the \"#{group.name}\" group."
expect(response).to redirect_to(dashboard_groups_path)
- expect(group.users).not_to include user
+ expect(group).not_to have_user(user)
end
it 'supports json request', :aggregate_failures do
@@ -401,7 +401,7 @@ RSpec.describe Groups::GroupMembersController do
expect(controller).to set_flash.to "You left the \"#{subgroup.human_name}\" group."
expect(response).to redirect_to(dashboard_groups_path)
- expect(subgroup.users).not_to include user
+ expect(subgroup).not_to have_user(user)
end
end
end
@@ -416,7 +416,7 @@ RSpec.describe Groups::GroupMembersController do
expect(controller).to set_flash.to "You left the \"#{group.name}\" group."
expect(response).to redirect_to(dashboard_groups_path)
- expect(group.users).not_to include user
+ expect(group).not_to have_user(user)
end
end
end
@@ -434,7 +434,7 @@ RSpec.describe Groups::GroupMembersController do
expect(controller).to set_flash.to 'Your access request to the group has been withdrawn.'
expect(response).to redirect_to(group_path(group))
expect(group.requesters).to be_empty
- expect(group.users).not_to include user
+ expect(group).not_to have_user(user)
end
end
end
@@ -451,7 +451,7 @@ RSpec.describe Groups::GroupMembersController do
expect(controller).to set_flash.to 'Your request for access has been queued for review.'
expect(response).to redirect_to(group_path(group))
expect(group.requesters.exists?(user_id: user)).to be_truthy
- expect(group.users).not_to include user
+ expect(group).not_to have_user(user)
end
end
diff --git a/spec/controllers/import/gitea_controller_spec.rb b/spec/controllers/import/gitea_controller_spec.rb
index 3dfda909a93..e3242480937 100644
--- a/spec/controllers/import/gitea_controller_spec.rb
+++ b/spec/controllers/import/gitea_controller_spec.rb
@@ -74,8 +74,8 @@ RSpec.describe Import::GiteaController, feature_category: :importers do
before do
session[:gitea_access_token] = token
- allow(Gitlab::UrlBlocker).to receive(:validate!).with(https_uri, anything).and_return([Addressable::URI.parse(https_uri), uri])
- allow(Gitlab::UrlBlocker).to receive(:validate!).with(http_uri, anything).and_return([Addressable::URI.parse(ip_uri), uri])
+ allow(Gitlab::HTTP_V2::UrlBlocker).to receive(:validate!).with(https_uri, anything).and_return([Addressable::URI.parse(https_uri), uri])
+ allow(Gitlab::HTTP_V2::UrlBlocker).to receive(:validate!).with(http_uri, anything).and_return([Addressable::URI.parse(ip_uri), uri])
allow(Gitlab::LegacyGithubImport::Client).to receive(:new).and_return(double('Gitlab::LegacyGithubImport::Client', repos: [], orgs: []))
end
diff --git a/spec/features/groups/members/leave_group_spec.rb b/spec/features/groups/members/leave_group_spec.rb
index 632155cd7e4..85255187457 100644
--- a/spec/features/groups/members/leave_group_spec.rb
+++ b/spec/features/groups/members/leave_group_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe 'Groups > Members > Leave group', feature_category: :groups_and_p
expect(page).to have_current_path(dashboard_groups_path, ignore_query: true)
expect(page).to have_content left_group_message(group)
- expect(group.users).not_to include(user)
+ expect(group).not_to have_user(user)
end
it 'guest leaves the group by url param', :js do
@@ -39,7 +39,7 @@ RSpec.describe 'Groups > Members > Leave group', feature_category: :groups_and_p
accept_gl_confirm(button_text: 'Leave group')
expect(page).to have_current_path(dashboard_groups_path, ignore_query: true)
- expect(group.users).not_to include(user)
+ expect(group).not_to have_user(user)
end
it 'guest leaves the group as last member', :js do
@@ -52,7 +52,7 @@ RSpec.describe 'Groups > Members > Leave group', feature_category: :groups_and_p
expect(page).to have_current_path(dashboard_groups_path, ignore_query: true)
expect(page).to have_content left_group_message(group)
- expect(group.users).not_to include(user)
+ expect(group).not_to have_user(user)
end
it 'owner leaves the group if they are not the last owner', :js do
@@ -66,7 +66,7 @@ RSpec.describe 'Groups > Members > Leave group', feature_category: :groups_and_p
expect(page).to have_current_path(dashboard_groups_path, ignore_query: true)
expect(page).to have_content left_group_message(group)
- expect(group.users).not_to include(user)
+ expect(group).not_to have_user(user)
end
it 'owner can not leave the group if they are the last owner', :js do
diff --git a/spec/features/groups/members/manage_members_spec.rb b/spec/features/groups/members/manage_members_spec.rb
index dd64ddcede5..000a44492a6 100644
--- a/spec/features/groups/members/manage_members_spec.rb
+++ b/spec/features/groups/members/manage_members_spec.rb
@@ -63,7 +63,7 @@ RSpec.describe 'Groups > Members > Manage members', feature_category: :groups_an
aggregate_failures do
expect(page).not_to have_content(user2.name)
- expect(group.users).not_to include(user2)
+ expect(group).not_to have_user(user2)
end
end
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index 04ac94685cf..47ca74ec092 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -256,7 +256,7 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures, feature_cate
it 'does not accept the pending invitation and does not redirect to the group path' do
expect(page).not_to have_current_path(group_path(group), ignore_query: true)
- expect(group.reload.users).not_to include(user)
+ expect(group.reload).not_to have_user(user)
end
context 'when the secondary email address is confirmed' do
@@ -264,7 +264,7 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures, feature_cate
it 'accepts the pending invitation and redirects to the group path' do
expect(page).to have_current_path(group_path(group), ignore_query: true)
- expect(group.reload.users).to include(user)
+ expect(group.reload).to have_user(user)
end
end
end
diff --git a/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb b/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb
index 8f448d06db1..a09c43c4bd2 100644
--- a/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb
+++ b/spec/features/merge_request/user_views_merge_request_from_deleted_fork_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe 'User views merged merge request from deleted fork', feature_cate
before do
sign_in user
- fork_owner = source_project.namespace.owners.first
+ fork_owner = source_project.namespace.all_owner_members.non_invite.first.user
# Place the source_project in the weird in between state
source_project.update_attribute(:pending_delete, true)
Projects::DestroyService.new(source_project, fork_owner, {}).__send__(:trash_project_repositories!)
diff --git a/spec/features/projects/releases/user_views_releases_spec.rb b/spec/features/projects/releases/user_views_releases_spec.rb
index d0111d0b9c8..f56c088a27b 100644
--- a/spec/features/projects/releases/user_views_releases_spec.rb
+++ b/spec/features/projects/releases/user_views_releases_spec.rb
@@ -87,9 +87,9 @@ RSpec.describe 'User views releases', :js, feature_category: :continuous_deliver
context 'sorting' do
def sort_page(by:, direction:)
within '[data-testid="releases-sort"]' do
- find('.dropdown-toggle').click
+ find('[data-testid="base-dropdown-toggle"]').click
- click_button(by, class: 'dropdown-item')
+ find('li.gl-new-dropdown-item', text: by).click
find('.sorting-direction-button').click if direction == :ascending
end
diff --git a/spec/finders/ci/runners_finder_spec.rb b/spec/finders/ci/runners_finder_spec.rb
index 7e9ef2139c9..b1252b53127 100644
--- a/spec/finders/ci/runners_finder_spec.rb
+++ b/spec/finders/ci/runners_finder_spec.rb
@@ -153,7 +153,7 @@ RSpec.describe Ci::RunnersFinder, feature_category: :fleet_visibility do
end
end
- context 'by creator' do
+ context 'by creator id' do
it 'calls the corresponding scope on Ci::Runner' do
expect(Ci::Runner).to receive(:with_creator_id).with('1').and_call_original
@@ -161,6 +161,24 @@ RSpec.describe Ci::RunnersFinder, feature_category: :fleet_visibility do
end
end
+ context 'by creator username' do
+ let_it_be(:admin_runner) { create(:ci_runner, creator: admin) }
+
+ it 'calls the corresponding scope on Ci::Runner' do
+ expect(Ci::Runner).to receive(:with_creator_id).with(admin.id).and_call_original
+
+ result = described_class.new(current_user: admin, params: { creator_username: admin.username }).execute
+ expect(result).to match_array [admin_runner]
+ end
+
+ it 'does not call the scope when the username is not found and is empty' do
+ expect(Ci::Runner).not_to receive(:with_creator_id)
+
+ result = described_class.new(current_user: admin, params: { creator_username: "not a username" }).execute
+ expect(result).to be_empty
+ end
+ end
+
context 'by version' do
it 'calls the corresponding scope on Ci::Runner' do
expect(Ci::Runner).to receive(:with_version_prefix).with('15.').and_call_original
diff --git a/spec/frontend/ml/model_registry/components/model_row_spec.js b/spec/frontend/ml/model_registry/components/model_row_spec.js
index 9d16ce5c466..09729292355 100644
--- a/spec/frontend/ml/model_registry/components/model_row_spec.js
+++ b/spec/frontend/ml/model_registry/components/model_row_spec.js
@@ -34,7 +34,7 @@ describe('ModelRow', () => {
expect(findVersionLink().text()).toBe(mockModels[1].version);
expect(findVersionLink().attributes('href')).toBe(mockModels[1].versionPath);
- expect(findMessage('· No other versions').exists()).toBe(true);
+ expect(findMessage('· 1 version').exists()).toBe(true);
});
it('Shows no version message if model has no versions', () => {
diff --git a/spec/frontend/observability/client_spec.js b/spec/frontend/observability/client_spec.js
index 0a852d9e000..1bd0112746b 100644
--- a/spec/frontend/observability/client_spec.js
+++ b/spec/frontend/observability/client_spec.js
@@ -263,6 +263,10 @@ describe('buildClient', () => {
{ operator: '!=', value: 'not-service' },
],
period: [{ operator: '=', value: '5m' }],
+ status: [
+ { operator: '=', value: 'ok' },
+ { operator: '!=', value: 'error' },
+ ],
traceId: [
{ operator: '=', value: 'trace-id' },
{ operator: '!=', value: 'not-trace-id' },
@@ -276,7 +280,8 @@ describe('buildClient', () => {
'&service_name=service&not[service_name]=not-service' +
'&period=5m' +
'&trace_id=trace-id&not[trace_id]=not-trace-id' +
- '&attr_name=name1&attr_value=value1',
+ '&attr_name=name1&attr_value=value1' +
+ '&status=ok&not[status]=error',
);
});
describe('date range time filter', () => {
diff --git a/spec/frontend/organizations/groups_and_projects/components/app_spec.js b/spec/frontend/organizations/groups_and_projects/components/app_spec.js
index e2301de8607..7215750c3c7 100644
--- a/spec/frontend/organizations/groups_and_projects/components/app_spec.js
+++ b/spec/frontend/organizations/groups_and_projects/components/app_spec.js
@@ -1,4 +1,4 @@
-import { GlCollapsibleListbox, GlSorting, GlSortingItem } from '@gitlab/ui';
+import { GlCollapsibleListbox, GlSorting } from '@gitlab/ui';
import App from '~/organizations/groups_and_projects/components/app.vue';
import GroupsView from '~/organizations/shared/components/groups_view.vue';
import ProjectsView from '~/organizations/shared/components/projects_view.vue';
@@ -6,6 +6,7 @@ import { RESOURCE_TYPE_GROUPS, RESOURCE_TYPE_PROJECTS } from '~/organizations/co
import {
SORT_ITEM_CREATED,
SORT_DIRECTION_DESC,
+ SORT_ITEMS,
} from '~/organizations/groups_and_projects/constants';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import {
@@ -84,21 +85,12 @@ describe('GroupsAndProjectsApp', () => {
it('renders sort dropdown with sort items and correct props', () => {
createComponent();
- const sortItems = wrapper.findAllComponents(GlSortingItem).wrappers.map((sortItemWrapper) => ({
- active: sortItemWrapper.attributes('active'),
- text: sortItemWrapper.text(),
- }));
-
expect(findSort().props()).toMatchObject({
isAscending: true,
text: SORT_ITEM_CREATED.text,
+ sortBy: SORT_ITEM_CREATED.value,
+ sortOptions: SORT_ITEMS,
});
- expect(sortItems).toEqual([
- {
- active: 'true',
- text: SORT_ITEM_CREATED.text,
- },
- ]);
});
describe('when filtered search bar is submitted', () => {
@@ -133,12 +125,12 @@ describe('GroupsAndProjectsApp', () => {
beforeEach(() => {
createComponent();
- wrapper.findComponent(GlSortingItem).trigger('click', SORT_ITEM_CREATED);
+ findSort().vm.$emit('sortByChange', SORT_ITEM_CREATED.value);
});
it('updates `sort_name` query string', () => {
expect(routerMock.push).toHaveBeenCalledWith({
- query: { sort_name: SORT_ITEM_CREATED.name, search: 'foo' },
+ query: { sort_name: SORT_ITEM_CREATED.value, search: 'foo' },
});
});
});
diff --git a/spec/frontend/releases/components/releases_sort_spec.js b/spec/frontend/releases/components/releases_sort_spec.js
index 76907b4b8bb..f07f6b31ddf 100644
--- a/spec/frontend/releases/components/releases_sort_spec.js
+++ b/spec/frontend/releases/components/releases_sort_spec.js
@@ -1,8 +1,16 @@
-import { GlSorting, GlSortingItem } from '@gitlab/ui';
+import { GlSorting } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { assertProps } from 'helpers/assert_props';
import ReleasesSort from '~/releases/components/releases_sort.vue';
-import { RELEASED_AT_ASC, RELEASED_AT_DESC, CREATED_ASC, CREATED_DESC } from '~/releases/constants';
+import {
+ RELEASED_AT,
+ RELEASED_AT_ASC,
+ RELEASED_AT_DESC,
+ CREATED_AT,
+ CREATED_ASC,
+ CREATED_DESC,
+ SORT_OPTIONS,
+} from '~/releases/constants';
describe('releases_sort.vue', () => {
let wrapper;
@@ -12,31 +20,18 @@ describe('releases_sort.vue', () => {
propsData: {
value: valueProp,
},
- stubs: {
- GlSortingItem,
- },
});
};
const findSorting = () => wrapper.findComponent(GlSorting);
- const findSortingItems = () => wrapper.findAllComponents(GlSortingItem);
- const findReleasedDateItem = () =>
- findSortingItems().wrappers.find((item) => item.text() === 'Released date');
- const findCreatedDateItem = () =>
- findSortingItems().wrappers.find((item) => item.text() === 'Created date');
- const getSortingItemsInfo = () =>
- findSortingItems().wrappers.map((item) => ({
- label: item.text(),
- active: item.attributes().active === 'true',
- }));
describe.each`
- valueProp | text | isAscending | items
- ${RELEASED_AT_ASC} | ${'Released date'} | ${true} | ${[{ label: 'Released date', active: true }, { label: 'Created date', active: false }]}
- ${RELEASED_AT_DESC} | ${'Released date'} | ${false} | ${[{ label: 'Released date', active: true }, { label: 'Created date', active: false }]}
- ${CREATED_ASC} | ${'Created date'} | ${true} | ${[{ label: 'Released date', active: false }, { label: 'Created date', active: true }]}
- ${CREATED_DESC} | ${'Created date'} | ${false} | ${[{ label: 'Released date', active: false }, { label: 'Created date', active: true }]}
- `('component states', ({ valueProp, text, isAscending, items }) => {
+ valueProp | text | isAscending
+ ${RELEASED_AT_ASC} | ${'Released date'} | ${true}
+ ${RELEASED_AT_DESC} | ${'Released date'} | ${false}
+ ${CREATED_ASC} | ${'Created date'} | ${true}
+ ${CREATED_DESC} | ${'Created date'} | ${false}
+ `('component states', ({ valueProp, text, isAscending }) => {
beforeEach(() => {
createComponent(valueProp);
});
@@ -49,14 +44,10 @@ describe('releases_sort.vue', () => {
}),
);
});
-
- it(`when the sort is ${valueProp}, renders the expected dropdown items`, () => {
- expect(getSortingItemsInfo()).toEqual(items);
- });
});
- const clickReleasedDateItem = () => findReleasedDateItem().vm.$emit('click');
- const clickCreatedDateItem = () => findCreatedDateItem().vm.$emit('click');
+ const clickReleasedDateItem = () => findSorting().vm.$emit('sortByChange', RELEASED_AT);
+ const clickCreatedDateItem = () => findSorting().vm.$emit('sortByChange', CREATED_AT);
const clickSortDirectionButton = () => findSorting().vm.$emit('sortDirectionChange');
const releasedAtDropdownItemDescription = 'released at dropdown item';
@@ -97,4 +88,17 @@ describe('releases_sort.vue', () => {
}).toThrow('Invalid prop: custom validator check failed');
});
});
+
+ describe('dropdown options', () => {
+ it('sets sort options', () => {
+ createComponent(RELEASED_AT_ASC);
+
+ expect(findSorting().props()).toMatchObject({
+ text: 'Released date',
+ isAscending: true,
+ sortBy: RELEASED_AT,
+ sortOptions: SORT_OPTIONS,
+ });
+ });
+ });
});
diff --git a/spec/frontend/work_items/components/work_item_milestone_with_edit_spec.js b/spec/frontend/work_items/components/work_item_milestone_with_edit_spec.js
index 58a57978126..d6ad7b6887b 100644
--- a/spec/frontend/work_items/components/work_item_milestone_with_edit_spec.js
+++ b/spec/frontend/work_items/components/work_item_milestone_with_edit_spec.js
@@ -5,7 +5,6 @@ import WorkItemSidebarDropdownWidgetWithEdit from '~/work_items/components/share
import createMockApollo from 'helpers/mock_apollo_helper';
import { mockTracking } from 'helpers/tracking_helper';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import waitForPromises from 'helpers/wait_for_promises';
import { TRACKING_CATEGORY_SHOW } from '~/work_items/constants';
import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
@@ -99,8 +98,6 @@ describe('WorkItemMilestoneWithEdit component', () => {
it('calls successSearchQueryHandler with variables when dropdown is opened', async () => {
showDropdown();
- await nextTick();
- jest.advanceTimersByTime(DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
await waitForPromises();
@@ -114,8 +111,6 @@ describe('WorkItemMilestoneWithEdit component', () => {
it('shows the skeleton loader when the items are being fetched on click', async () => {
showDropdown();
- await nextTick();
- jest.advanceTimersByTime(DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
await nextTick();
@@ -124,8 +119,6 @@ describe('WorkItemMilestoneWithEdit component', () => {
it('shows the milestones in dropdown when the items have finished fetching', async () => {
showDropdown();
- await nextTick();
- jest.advanceTimersByTime(DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
await waitForPromises();
@@ -135,14 +128,11 @@ describe('WorkItemMilestoneWithEdit component', () => {
);
});
- it('changes the milestone to null when clicked on no milestone', async () => {
- showDropdown();
- await nextTick();
- jest.advanceTimersByTime(DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
-
+ it('changes the milestone to null when clicked on Clear', async () => {
findSidebarDropdownWidget().vm.$emit('updateValue', null);
await nextTick();
+
expect(findSidebarDropdownWidget().props('updateInProgress')).toBe(true);
await waitForPromises();
@@ -154,8 +144,6 @@ describe('WorkItemMilestoneWithEdit component', () => {
const milestoneAtIndex = projectMilestonesResponse.data.workspace.attributes.nodes[0];
showDropdown();
- await nextTick();
- jest.advanceTimersByTime(DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
await waitForPromises();
findSidebarDropdownWidget().vm.$emit('updateValue', milestoneAtIndex.id);
diff --git a/spec/graphql/resolvers/ci/runners_resolver_spec.rb b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
index a0239a6ff34..f59b0ccf8b0 100644
--- a/spec/graphql/resolvers/ci/runners_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
@@ -87,6 +87,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :fleet_visibili
search: 'abc',
sort: :contacted_asc,
creator_id: 'gid://gitlab/User/1',
+ creator_username: 'root',
version_prefix: '15.'
}
end
@@ -102,6 +103,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :fleet_visibili
search: 'abc',
sort: 'contacted_asc',
creator_id: '1',
+ creator_username: 'root',
version_prefix: '15.'
}
end
diff --git a/spec/lib/gitlab/project_authorizations_spec.rb b/spec/lib/gitlab/project_authorizations_spec.rb
index f3dcdfe2a9d..c4cb88cf3f2 100644
--- a/spec/lib/gitlab/project_authorizations_spec.rb
+++ b/spec/lib/gitlab/project_authorizations_spec.rb
@@ -15,465 +15,408 @@ RSpec.describe Gitlab::ProjectAuthorizations, feature_category: :system_access d
service.calculate
end
- # Inline this shared example while cleaning up feature flag linear_project_authorization
- RSpec.shared_examples 'project authorizations' do
- context 'user added to group and project' do
- let(:group) { create(:group) }
- let!(:other_project) { create(:project) }
- let!(:group_project) { create(:project, namespace: group) }
- let!(:owned_project) { create(:project) }
- let(:user) { owned_project.namespace.owner }
+ context 'user added to group and project' do
+ let(:group) { create(:group) }
+ let!(:other_project) { create(:project) }
+ let!(:group_project) { create(:project, namespace: group) }
+ let!(:owned_project) { create(:project) }
+ let(:user) { owned_project.namespace.owner }
- before do
- other_project.add_reporter(user)
- group.add_developer(user)
- end
+ before do
+ other_project.add_reporter(user)
+ group.add_developer(user)
+ end
- it 'returns the correct number of authorizations' do
- expect(authorizations.length).to eq(3)
- end
+ it 'returns the correct number of authorizations' do
+ expect(authorizations.length).to eq(3)
+ end
- it 'includes the correct projects' do
- expect(authorizations.pluck(:project_id))
- .to include(owned_project.id, other_project.id, group_project.id)
- end
+ it 'includes the correct projects' do
+ expect(authorizations.pluck(:project_id))
+ .to include(owned_project.id, other_project.id, group_project.id)
+ end
- it 'includes the correct access levels' do
- mapping = map_access_levels(authorizations)
+ it 'includes the correct access levels' do
+ mapping = map_access_levels(authorizations)
- expect(mapping[owned_project.id]).to eq(Gitlab::Access::OWNER)
- expect(mapping[other_project.id]).to eq(Gitlab::Access::REPORTER)
- expect(mapping[group_project.id]).to eq(Gitlab::Access::DEVELOPER)
- end
+ expect(mapping[owned_project.id]).to eq(Gitlab::Access::OWNER)
+ expect(mapping[other_project.id]).to eq(Gitlab::Access::REPORTER)
+ expect(mapping[group_project.id]).to eq(Gitlab::Access::DEVELOPER)
end
+ end
- context 'unapproved access request' do
- let_it_be(:group) { create(:group) }
- let_it_be(:user) { create(:user) }
+ context 'unapproved access request' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
- subject(:mapping) { map_access_levels(authorizations) }
+ subject(:mapping) { map_access_levels(authorizations) }
- context 'group membership' do
- let!(:group_project) { create(:project, namespace: group) }
+ context 'group membership' do
+ let!(:group_project) { create(:project, namespace: group) }
- before do
- create(:group_member, :developer, :access_request, user: user, group: group)
- end
+ before do
+ create(:group_member, :developer, :access_request, user: user, group: group)
+ end
- it 'does not create authorization' do
- expect(mapping[group_project.id]).to be_nil
- end
+ it 'does not create authorization' do
+ expect(mapping[group_project.id]).to be_nil
end
+ end
- context 'inherited group membership' do
- let!(:sub_group) { create(:group, parent: group) }
- let!(:sub_group_project) { create(:project, namespace: sub_group) }
+ context 'inherited group membership' do
+ let!(:sub_group) { create(:group, parent: group) }
+ let!(:sub_group_project) { create(:project, namespace: sub_group) }
- before do
- create(:group_member, :developer, :access_request, user: user, group: group)
- end
+ before do
+ create(:group_member, :developer, :access_request, user: user, group: group)
+ end
- it 'does not create authorization' do
- expect(mapping[sub_group_project.id]).to be_nil
- end
+ it 'does not create authorization' do
+ expect(mapping[sub_group_project.id]).to be_nil
end
+ end
- context 'project membership' do
- let!(:group_project) { create(:project, namespace: group) }
+ context 'project membership' do
+ let!(:group_project) { create(:project, namespace: group) }
- before do
- create(:project_member, :developer, :access_request, user: user, project: group_project)
- end
+ before do
+ create(:project_member, :developer, :access_request, user: user, project: group_project)
+ end
- it 'does not create authorization' do
- expect(mapping[group_project.id]).to be_nil
- end
+ it 'does not create authorization' do
+ expect(mapping[group_project.id]).to be_nil
end
+ end
- context 'shared group' do
- let!(:shared_group) { create(:group) }
- let!(:shared_group_project) { create(:project, namespace: shared_group) }
+ context 'shared group' do
+ let!(:shared_group) { create(:group) }
+ let!(:shared_group_project) { create(:project, namespace: shared_group) }
- before do
- create(:group_group_link, shared_group: shared_group, shared_with_group: group)
- create(:group_member, :developer, :access_request, user: user, group: group)
- end
+ before do
+ create(:group_group_link, shared_group: shared_group, shared_with_group: group)
+ create(:group_member, :developer, :access_request, user: user, group: group)
+ end
- it 'does not create authorization' do
- expect(mapping[shared_group_project.id]).to be_nil
- end
+ it 'does not create authorization' do
+ expect(mapping[shared_group_project.id]).to be_nil
end
+ end
- context 'shared project' do
- let!(:another_group) { create(:group) }
- let!(:shared_project) { create(:project, namespace: another_group) }
+ context 'shared project' do
+ let!(:another_group) { create(:group) }
+ let!(:shared_project) { create(:project, namespace: another_group) }
- before do
- create(:project_group_link, group: group, project: shared_project)
- create(:group_member, :developer, :access_request, user: user, group: group)
- end
+ before do
+ create(:project_group_link, group: group, project: shared_project)
+ create(:group_member, :developer, :access_request, user: user, group: group)
+ end
- it 'does not create authorization' do
- expect(mapping[shared_project.id]).to be_nil
- end
+ it 'does not create authorization' do
+ expect(mapping[shared_project.id]).to be_nil
end
end
+ end
- context 'user with minimal access to group' do
- let_it_be(:group) { create(:group) }
- let_it_be(:user) { create(:user) }
-
- subject(:mapping) { map_access_levels(authorizations) }
+ context 'user with minimal access to group' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
- context 'group membership' do
- let!(:group_project) { create(:project, namespace: group) }
+ subject(:mapping) { map_access_levels(authorizations) }
- before do
- create(:group_member, :minimal_access, user: user, source: group)
- end
+ context 'group membership' do
+ let!(:group_project) { create(:project, namespace: group) }
- it 'does not create authorization' do
- expect(mapping[group_project.id]).to be_nil
- end
+ before do
+ create(:group_member, :minimal_access, user: user, source: group)
end
- context 'inherited group membership' do
- let!(:sub_group) { create(:group, parent: group) }
- let!(:sub_group_project) { create(:project, namespace: sub_group) }
-
- before do
- create(:group_member, :minimal_access, user: user, source: group)
- end
-
- it 'does not create authorization' do
- expect(mapping[sub_group_project.id]).to be_nil
- end
+ it 'does not create authorization' do
+ expect(mapping[group_project.id]).to be_nil
end
+ end
- context 'shared group' do
- let!(:shared_group) { create(:group) }
- let!(:shared_group_project) { create(:project, namespace: shared_group) }
+ context 'inherited group membership' do
+ let!(:sub_group) { create(:group, parent: group) }
+ let!(:sub_group_project) { create(:project, namespace: sub_group) }
- before do
- create(:group_group_link, shared_group: shared_group, shared_with_group: group)
- create(:group_member, :minimal_access, user: user, source: group)
- end
+ before do
+ create(:group_member, :minimal_access, user: user, source: group)
+ end
- it 'does not create authorization' do
- expect(mapping[shared_group_project.id]).to be_nil
- end
+ it 'does not create authorization' do
+ expect(mapping[sub_group_project.id]).to be_nil
end
+ end
- context 'shared project' do
- let!(:another_group) { create(:group) }
- let!(:shared_project) { create(:project, namespace: another_group) }
+ context 'shared group' do
+ let!(:shared_group) { create(:group) }
+ let!(:shared_group_project) { create(:project, namespace: shared_group) }
- before do
- create(:project_group_link, group: group, project: shared_project)
- create(:group_member, :minimal_access, user: user, source: group)
- end
+ before do
+ create(:group_group_link, shared_group: shared_group, shared_with_group: group)
+ create(:group_member, :minimal_access, user: user, source: group)
+ end
- it 'does not create authorization' do
- expect(mapping[shared_project.id]).to be_nil
- end
+ it 'does not create authorization' do
+ expect(mapping[shared_group_project.id]).to be_nil
end
end
- context 'with nested groups' do
- let(:group) { create(:group) }
- let!(:nested_group) { create(:group, parent: group) }
- let!(:nested_project) { create(:project, namespace: nested_group) }
- let(:user) { create(:user) }
+ context 'shared project' do
+ let!(:another_group) { create(:group) }
+ let!(:shared_project) { create(:project, namespace: another_group) }
before do
- group.add_developer(user)
+ create(:project_group_link, group: group, project: shared_project)
+ create(:group_member, :minimal_access, user: user, source: group)
end
- it 'includes nested groups' do
- expect(authorizations.pluck(:project_id)).to include(nested_project.id)
+ it 'does not create authorization' do
+ expect(mapping[shared_project.id]).to be_nil
end
+ end
+ end
- it 'inherits access levels when the user is not a member of a nested group' do
- mapping = map_access_levels(authorizations)
+ context 'with nested groups' do
+ let(:group) { create(:group) }
+ let!(:nested_group) { create(:group, parent: group) }
+ let!(:nested_project) { create(:project, namespace: nested_group) }
+ let(:user) { create(:user) }
- expect(mapping[nested_project.id]).to eq(Gitlab::Access::DEVELOPER)
- end
+ before do
+ group.add_developer(user)
+ end
- it 'uses the greatest access level when a user is a member of a nested group' do
- nested_group.add_maintainer(user)
+ it 'includes nested groups' do
+ expect(authorizations.pluck(:project_id)).to include(nested_project.id)
+ end
- mapping = map_access_levels(authorizations)
+ it 'inherits access levels when the user is not a member of a nested group' do
+ mapping = map_access_levels(authorizations)
- expect(mapping[nested_project.id]).to eq(Gitlab::Access::MAINTAINER)
- end
+ expect(mapping[nested_project.id]).to eq(Gitlab::Access::DEVELOPER)
+ end
+
+ it 'uses the greatest access level when a user is a member of a nested group' do
+ nested_group.add_maintainer(user)
+
+ mapping = map_access_levels(authorizations)
+
+ expect(mapping[nested_project.id]).to eq(Gitlab::Access::MAINTAINER)
end
+ end
+
+ context 'with shared projects' do
+ let_it_be(:shared_with_group) { create(:group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, group: create(:group)) }
- context 'with shared projects' do
- let_it_be(:shared_with_group) { create(:group) }
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project, group: create(:group)) }
+ let(:mapping) { map_access_levels(authorizations) }
- let(:mapping) { map_access_levels(authorizations) }
+ before do
+ create(:project_group_link, :developer, project: project, group: shared_with_group)
+ shared_with_group.add_maintainer(user)
+ end
+
+ it 'creates proper authorizations' do
+ expect(mapping[project.id]).to eq(Gitlab::Access::DEVELOPER)
+ end
+ context 'even when the `lock_memberships_to_ldap` setting has been turned ON' do
before do
- create(:project_group_link, :developer, project: project, group: shared_with_group)
- shared_with_group.add_maintainer(user)
+ stub_application_setting(lock_memberships_to_ldap: true)
end
it 'creates proper authorizations' do
expect(mapping[project.id]).to eq(Gitlab::Access::DEVELOPER)
end
+ end
- context 'even when the `lock_memberships_to_ldap` setting has been turned ON' do
- before do
- stub_application_setting(lock_memberships_to_ldap: true)
- end
-
- it 'creates proper authorizations' do
- expect(mapping[project.id]).to eq(Gitlab::Access::DEVELOPER)
- end
+ context 'when the group containing the project has forbidden group shares for any of its projects' do
+ before do
+ project.namespace.update!(share_with_group_lock: true)
end
- context 'when the group containing the project has forbidden group shares for any of its projects' do
- before do
- project.namespace.update!(share_with_group_lock: true)
- end
-
- it 'does not create authorizations' do
- expect(mapping[project.id]).to be_nil
- end
+ it 'does not create authorizations' do
+ expect(mapping[project.id]).to be_nil
end
end
+ end
- context 'with shared groups' do
- let(:parent_group_user) { create(:user) }
- let(:group_user) { create(:user) }
- let(:child_group_user) { create(:user) }
+ context 'with shared groups' do
+ let(:parent_group_user) { create(:user) }
+ let(:group_user) { create(:user) }
+ let(:child_group_user) { create(:user) }
- let_it_be(:group_parent) { create(:group, :private) }
- let_it_be(:group) { create(:group, :private, parent: group_parent) }
- let_it_be(:group_child) { create(:group, :private, parent: group) }
+ let_it_be(:group_parent) { create(:group, :private) }
+ let_it_be(:group) { create(:group, :private, parent: group_parent) }
+ let_it_be(:group_child) { create(:group, :private, parent: group) }
- let_it_be(:shared_group_parent) { create(:group, :private) }
- let_it_be(:shared_group) { create(:group, :private, parent: shared_group_parent) }
- let_it_be(:shared_group_child) { create(:group, :private, parent: shared_group) }
+ let_it_be(:shared_group_parent) { create(:group, :private) }
+ let_it_be(:shared_group) { create(:group, :private, parent: shared_group_parent) }
+ let_it_be(:shared_group_child) { create(:group, :private, parent: shared_group) }
- let_it_be(:project_parent) { create(:project, group: shared_group_parent) }
- let_it_be(:project) { create(:project, group: shared_group) }
- let_it_be(:project_child) { create(:project, group: shared_group_child) }
+ let_it_be(:project_parent) { create(:project, group: shared_group_parent) }
+ let_it_be(:project) { create(:project, group: shared_group) }
+ let_it_be(:project_child) { create(:project, group: shared_group_child) }
- before do
- group_parent.add_owner(parent_group_user)
- group.add_owner(group_user)
- group_child.add_owner(child_group_user)
+ before do
+ group_parent.add_owner(parent_group_user)
+ group.add_owner(group_user)
+ group_child.add_owner(child_group_user)
- create(:group_group_link, shared_group: shared_group, shared_with_group: group)
- end
+ create(:group_group_link, shared_group: shared_group, shared_with_group: group)
+ end
- context 'group user' do
- let(:user) { group_user }
+ context 'group user' do
+ let(:user) { group_user }
- it 'creates proper authorizations' do
- mapping = map_access_levels(authorizations)
+ it 'creates proper authorizations' do
+ mapping = map_access_levels(authorizations)
- expect(mapping[project_parent.id]).to be_nil
- expect(mapping[project.id]).to eq(Gitlab::Access::DEVELOPER)
- expect(mapping[project_child.id]).to eq(Gitlab::Access::DEVELOPER)
- end
+ expect(mapping[project_parent.id]).to be_nil
+ expect(mapping[project.id]).to eq(Gitlab::Access::DEVELOPER)
+ expect(mapping[project_child.id]).to eq(Gitlab::Access::DEVELOPER)
end
+ end
- context 'with lower group access level than max access level for share' do
- let(:user) { create(:user) }
+ context 'with lower group access level than max access level for share' do
+ let(:user) { create(:user) }
- it 'creates proper authorizations' do
- group.add_reporter(user)
+ it 'creates proper authorizations' do
+ group.add_reporter(user)
- mapping = map_access_levels(authorizations)
+ mapping = map_access_levels(authorizations)
- expect(mapping[project_parent.id]).to be_nil
- expect(mapping[project.id]).to eq(Gitlab::Access::REPORTER)
- expect(mapping[project_child.id]).to eq(Gitlab::Access::REPORTER)
- end
+ expect(mapping[project_parent.id]).to be_nil
+ expect(mapping[project.id]).to eq(Gitlab::Access::REPORTER)
+ expect(mapping[project_child.id]).to eq(Gitlab::Access::REPORTER)
end
+ end
- context 'parent group user' do
- let(:user) { parent_group_user }
+ context 'parent group user' do
+ let(:user) { parent_group_user }
- it 'creates proper authorizations' do
- mapping = map_access_levels(authorizations)
+ it 'creates proper authorizations' do
+ mapping = map_access_levels(authorizations)
- expect(mapping[project_parent.id]).to be_nil
- expect(mapping[project.id]).to be_nil
- expect(mapping[project_child.id]).to be_nil
- end
+ expect(mapping[project_parent.id]).to be_nil
+ expect(mapping[project.id]).to be_nil
+ expect(mapping[project_child.id]).to be_nil
end
+ end
- context 'child group user' do
- let(:user) { child_group_user }
+ context 'child group user' do
+ let(:user) { child_group_user }
- it 'creates proper authorizations' do
- mapping = map_access_levels(authorizations)
+ it 'creates proper authorizations' do
+ mapping = map_access_levels(authorizations)
- expect(mapping[project_parent.id]).to be_nil
- expect(mapping[project.id]).to be_nil
- expect(mapping[project_child.id]).to be_nil
- end
+ expect(mapping[project_parent.id]).to be_nil
+ expect(mapping[project.id]).to be_nil
+ expect(mapping[project_child.id]).to be_nil
end
+ end
- context 'user without accepted access request' do
- let!(:user) { create(:user) }
+ context 'user without accepted access request' do
+ let!(:user) { create(:user) }
- it 'does not have access to group and its projects' do
- create(:group_member, :developer, :access_request, user: user, group: group)
+ it 'does not have access to group and its projects' do
+ create(:group_member, :developer, :access_request, user: user, group: group)
- mapping = map_access_levels(authorizations)
+ mapping = map_access_levels(authorizations)
- expect(mapping[project_parent.id]).to be_nil
- expect(mapping[project.id]).to be_nil
- expect(mapping[project_child.id]).to be_nil
- end
+ expect(mapping[project_parent.id]).to be_nil
+ expect(mapping[project.id]).to be_nil
+ expect(mapping[project_child.id]).to be_nil
end
+ end
- context 'unrelated project owner' do
- let(:common_id) { non_existing_record_id }
- let!(:group) { create(:group, id: common_id) }
- let!(:unrelated_project) { create(:project, id: common_id) }
- let(:user) { unrelated_project.first_owner }
+ context 'unrelated project owner' do
+ let(:common_id) { non_existing_record_id }
+ let!(:group) { create(:group, id: common_id) }
+ let!(:unrelated_project) { create(:project, id: common_id) }
+ let(:user) { unrelated_project.first_owner }
- it 'does not have access to group and its projects' do
- mapping = map_access_levels(authorizations)
+ it 'does not have access to group and its projects' do
+ mapping = map_access_levels(authorizations)
- expect(mapping[project_parent.id]).to be_nil
- expect(mapping[project.id]).to be_nil
- expect(mapping[project_child.id]).to be_nil
- end
+ expect(mapping[project_parent.id]).to be_nil
+ expect(mapping[project.id]).to be_nil
+ expect(mapping[project_child.id]).to be_nil
end
end
+ end
- context 'with pending memberships' do
- let_it_be(:group) { create(:group) }
- let_it_be(:user) { create(:user) }
-
- subject(:mapping) { map_access_levels(authorizations) }
+ context 'with pending memberships' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
- context 'group membership' do
- let!(:group_project) { create(:project, namespace: group) }
+ subject(:mapping) { map_access_levels(authorizations) }
- before do
- create(:group_member, :developer, :awaiting, user: user, group: group)
- end
+ context 'group membership' do
+ let!(:group_project) { create(:project, namespace: group) }
- it 'does not create authorization' do
- expect(mapping[group_project.id]).to be_nil
- end
+ before do
+ create(:group_member, :developer, :awaiting, user: user, group: group)
end
- context 'inherited group membership' do
- let!(:sub_group) { create(:group, parent: group) }
- let!(:sub_group_project) { create(:project, namespace: sub_group) }
-
- before do
- create(:group_member, :developer, :awaiting, user: user, group: group)
- end
-
- it 'does not create authorization' do
- expect(mapping[sub_group_project.id]).to be_nil
- end
+ it 'does not create authorization' do
+ expect(mapping[group_project.id]).to be_nil
end
+ end
- context 'project membership' do
- let!(:group_project) { create(:project, namespace: group) }
-
- before do
- create(:project_member, :developer, :awaiting, user: user, project: group_project)
- end
+ context 'inherited group membership' do
+ let!(:sub_group) { create(:group, parent: group) }
+ let!(:sub_group_project) { create(:project, namespace: sub_group) }
- it 'does not create authorization' do
- expect(mapping[group_project.id]).to be_nil
- end
+ before do
+ create(:group_member, :developer, :awaiting, user: user, group: group)
end
- context 'shared group' do
- let!(:shared_group) { create(:group) }
- let!(:shared_group_project) { create(:project, namespace: shared_group) }
-
- before do
- create(:group_group_link, shared_group: shared_group, shared_with_group: group)
- create(:group_member, :developer, :awaiting, user: user, group: group)
- end
-
- it 'does not create authorization' do
- expect(mapping[shared_group_project.id]).to be_nil
- end
+ it 'does not create authorization' do
+ expect(mapping[sub_group_project.id]).to be_nil
end
+ end
- context 'shared project' do
- let!(:another_group) { create(:group) }
- let!(:shared_project) { create(:project, namespace: another_group) }
-
- before do
- create(:project_group_link, group: group, project: shared_project)
- create(:group_member, :developer, :awaiting, user: user, group: group)
- end
+ context 'project membership' do
+ let!(:group_project) { create(:project, namespace: group) }
- it 'does not create authorization' do
- expect(mapping[shared_project.id]).to be_nil
- end
+ before do
+ create(:project_member, :developer, :awaiting, user: user, project: group_project)
end
- end
- end
-
- context 'it compares values for correctness' do
- let_it_be(:user) { create(:user) }
- context 'when values returned by the queries are the same' do
- it 'logs a message indicating that the values are the same' do
- expect(Gitlab::AppJsonLogger).to receive(:info).with(event: 'linear_authorized_projects_check',
- user_id: user.id,
- matching_results: true)
- service.calculate
+ it 'does not create authorization' do
+ expect(mapping[group_project.id]).to be_nil
end
end
- context 'when values returned by queries are diffrent' do
+ context 'shared group' do
+ let!(:shared_group) { create(:group) }
+ let!(:shared_group_project) { create(:project, namespace: shared_group) }
+
before do
- create(:project_authorization)
- allow(service).to receive(:calculate_with_linear_query).and_return(ProjectAuthorization.all)
+ create(:group_group_link, shared_group: shared_group, shared_with_group: group)
+ create(:group_member, :developer, :awaiting, user: user, group: group)
end
- it 'logs a message indicating that the values are different' do
- expect(Gitlab::AppJsonLogger).to receive(:warn).with(event: 'linear_authorized_projects_check',
- user_id: user.id,
- matching_results: false)
- service.calculate
+ it 'does not create authorization' do
+ expect(mapping[shared_group_project.id]).to be_nil
end
end
- end
-
- context 'when feature_flag linear_project_authorization is disabled' do
- before do
- stub_feature_flags(linear_project_authorization: false)
- end
-
- it_behaves_like 'project authorizations'
- end
- context 'when feature_flag compare_project_authorization_linear_cte is disabled' do
- before do
- stub_feature_flags(compare_project_authorization_linear_cte: false)
- end
+ context 'shared project' do
+ let!(:another_group) { create(:group) }
+ let!(:shared_project) { create(:project, namespace: another_group) }
- it_behaves_like 'project authorizations'
- end
+ before do
+ create(:project_group_link, group: group, project: shared_project)
+ create(:group_member, :developer, :awaiting, user: user, group: group)
+ end
- context 'when feature_flag linear_project_authorization and compare_project_authorization_linear_cte are disabled' do
- before do
- stub_feature_flags(linear_project_authorization: false)
- stub_feature_flags(compare_project_authorization_linear_cte: false)
+ it 'does not create authorization' do
+ expect(mapping[shared_project.id]).to be_nil
+ end
end
-
- it_behaves_like 'project authorizations'
end
-
- it_behaves_like 'project authorizations'
end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index d4f7db3bddd..59f69013b37 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -525,16 +525,17 @@ RSpec.describe Ci::Runner, type: :model, feature_category: :runner do
end
describe '.with_creator_id' do
- subject { described_class.with_creator_id('1') }
+ let_it_be(:admin) { create(:admin, username: 'root') }
+ let_it_be(:user2) { create(:user, username: 'user2') }
- let_it_be(:runner1) { create(:ci_runner, creator_id: 2) }
- let_it_be(:runner2) { create(:ci_runner, creator_id: 1) }
- let_it_be(:runner3) { create(:ci_runner, creator_id: 1) }
- let_it_be(:runner4) { create(:ci_runner, creator_id: nil) }
+ let_it_be(:user_runner1) { create(:ci_runner, creator: user2) }
+ let_it_be(:admin_runner1) { create(:ci_runner, creator: admin) }
+ let_it_be(:admin_runner2) { create(:ci_runner, creator: admin) }
+ let_it_be(:runner_without_creator) { create(:ci_runner, creator: nil) }
- it "returns runners with creator_id '1'" do
- is_expected.to contain_exactly(runner2, runner3)
- end
+ subject { described_class.with_creator_id(admin.id.to_s) }
+
+ it { is_expected.to contain_exactly(admin_runner1, admin_runner2) }
end
describe '.with_version_prefix' do
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 26a9a364ea6..90c882c42b9 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -1241,7 +1241,10 @@ RSpec.describe Group, feature_category: :groups_and_projects do
end
describe '#users' do
- it { expect(group.users).to eq(group.owners) }
+ let(:group_users) { group.users.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/436662") }
+ let(:group_owners) { group.owners.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/436662") }
+
+ it { expect(group_users).to eq(group_owners) }
end
describe '#human_name' do
@@ -1599,7 +1602,9 @@ RSpec.describe Group, feature_category: :groups_and_projects do
it 'returns the owners of a Group' do
members = setup_group_members(group)
- expect(group.owners).to eq([members[:owner]])
+ expect(
+ group.owners.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/436662")
+ ).to eq([members[:owner]])
end
end
@@ -2546,7 +2551,7 @@ RSpec.describe Group, feature_category: :groups_and_projects do
end
describe '#bots' do
- subject { group.bots }
+ subject { group.bots.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/436662") }
let_it_be(:group) { create(:group) }
let_it_be(:project_bot) { create(:user, :project_bot) }
diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb
index cd721b9f163..728b42abe53 100644
--- a/spec/models/project_team_spec.rb
+++ b/spec/models/project_team_spec.rb
@@ -91,15 +91,18 @@ RSpec.describe ProjectTeam, feature_category: :groups_and_projects do
let(:project) { create(:project, group: group) }
let(:user1) { create(:user) }
let(:user2) { create(:user) }
+ let(:user3) { create(:user) }
before do
group.add_owner(user1)
group.add_owner(user2)
+ group.add_developer(user3)
end
specify { expect(project.team.owners).to contain_exactly(user1, user2) }
specify { expect(project.team.owner?(user1)).to be_truthy }
specify { expect(project.team.owner?(user2)).to be_truthy }
+ specify { expect(project.team.owner?(user3)).to be_falsey }
end
end
diff --git a/spec/models/route_spec.rb b/spec/models/route_spec.rb
index 8a791a19dec..7cada013636 100644
--- a/spec/models/route_spec.rb
+++ b/spec/models/route_spec.rb
@@ -74,7 +74,7 @@ RSpec.describe Route do
let!(:another_group) { create(:group, path: 'gittlab', name: 'gitllab') }
let!(:another_group_nested) { create(:group, path: 'git_lab', name: 'git_lab', parent: another_group) }
- shared_examples_for 'path update' do
+ context 'path update' do
context 'when route name is set' do
before do
route.update!(path: 'bar')
@@ -116,7 +116,7 @@ RSpec.describe Route do
end
end
- shared_examples_for 'name update' do
+ context 'name update' do
it 'updates children routes with new path' do
route.update!(name: 'bar')
@@ -134,18 +134,6 @@ RSpec.describe Route do
.to change { route.name }.from(nil).to('bar')
end
end
-
- it_behaves_like 'path update'
- it_behaves_like 'name update'
-
- context 'when the feature flag `batch_route_updates` if turned off' do
- before do
- stub_feature_flags(batch_route_updates: false)
- end
-
- it_behaves_like 'path update'
- it_behaves_like 'name update'
- end
end
describe '#create_redirect_for_old_path' do
diff --git a/spec/services/groups/participants_service_spec.rb b/spec/services/groups/participants_service_spec.rb
index beab7311b93..2588e8923f6 100644
--- a/spec/services/groups/participants_service_spec.rb
+++ b/spec/services/groups/participants_service_spec.rb
@@ -54,7 +54,8 @@ RSpec.describe Groups::ParticipantsService, feature_category: :groups_and_projec
subgroup.add_developer(create(:user))
subproject.add_developer(create(:user))
- expected_users = (group.self_and_hierarchy.flat_map(&:users) + subproject.users)
+ group_hierarchy_users = group.self_and_hierarchy.flat_map(&:group_members).map(&:user)
+ expected_users = (group_hierarchy_users + subproject.users)
.map { |user| user_to_autocompletable(user) }
expect(expected_users.count).to eq(4)
diff --git a/spec/services/groups/transfer_service_spec.rb b/spec/services/groups/transfer_service_spec.rb
index a3020241377..ce67c4c51fe 100644
--- a/spec/services/groups/transfer_service_spec.rb
+++ b/spec/services/groups/transfer_service_spec.rb
@@ -841,12 +841,12 @@ RSpec.describe Groups::TransferService, :sidekiq_inline, feature_category: :grou
let(:transfer_service) { described_class.new(subgroup, user) }
it 'ensures there is still an owner for the transferred group' do
- expect(subgroup.owners).to be_empty
+ expect(subgroup.all_owner_members).to be_empty
transfer_service.execute(nil)
subgroup.reload
- expect(subgroup.owners).to match_array(user)
+ expect(subgroup.all_owner_members.map(&:user)).to match_array(user)
end
context 'when group has explicit owner' do
@@ -854,12 +854,12 @@ RSpec.describe Groups::TransferService, :sidekiq_inline, feature_category: :grou
let!(:another_member) { create(:group_member, :owner, group: subgroup, user: another_owner) }
it 'does not add additional owner' do
- expect(subgroup.owners).to match_array(another_owner)
+ expect(subgroup.all_owner_members.map(&:user)).to match_array(another_owner)
transfer_service.execute(nil)
subgroup.reload
- expect(subgroup.owners).to match_array(another_owner)
+ expect(subgroup.all_owner_members.map(&:user)).to match_array(another_owner)
end
end
end
diff --git a/spec/services/projects/import_service_spec.rb b/spec/services/projects/import_service_spec.rb
index dd6e82b9ef2..7d0d1f5ed90 100644
--- a/spec/services/projects/import_service_spec.rb
+++ b/spec/services/projects/import_service_spec.rb
@@ -315,14 +315,15 @@ RSpec.describe Projects::ImportService, feature_category: :importers do
allow(Gitlab::CurrentSettings).to receive(:dns_rebinding_protection_enabled?).and_return(false)
project.import_url = "https://example.com/group/project"
- allow(Gitlab::UrlBlocker).to receive(:validate!)
+ allow(Gitlab::HTTP_V2::UrlBlocker).to receive(:validate!)
.with(
project.import_url,
ports: Project::VALID_IMPORT_PORTS,
schemes: Project::VALID_IMPORT_PROTOCOLS,
allow_local_network: false,
allow_localhost: false,
- dns_rebind_protection: false
+ dns_rebind_protection: false,
+ deny_all_requests_except_allowed: false
)
.and_return([Addressable::URI.parse("https://example.com/group/project"), nil])
end
@@ -350,14 +351,15 @@ RSpec.describe Projects::ImportService, feature_category: :importers do
before do
project.import_url = "https://example.com/group/project"
- allow(Gitlab::UrlBlocker).to receive(:validate!)
+ allow(Gitlab::HTTP_V2::UrlBlocker).to receive(:validate!)
.with(
project.import_url,
ports: Project::VALID_IMPORT_PORTS,
schemes: Project::VALID_IMPORT_PROTOCOLS,
allow_local_network: false,
allow_localhost: false,
- dns_rebind_protection: true
+ dns_rebind_protection: true,
+ deny_all_requests_except_allowed: false
)
.and_return([Addressable::URI.parse("https://172.16.123.1/group/project"), 'example.com'])
end
@@ -378,14 +380,15 @@ RSpec.describe Projects::ImportService, feature_category: :importers do
before do
project.import_url = 'https://gitlab.com/gitlab-org/gitlab-development-kit'
- allow(Gitlab::UrlBlocker).to receive(:validate!)
+ allow(Gitlab::HTTP_V2::UrlBlocker).to receive(:validate!)
.with(
project.import_url,
ports: Project::VALID_IMPORT_PORTS,
schemes: Project::VALID_IMPORT_PROTOCOLS,
allow_local_network: false,
allow_localhost: false,
- dns_rebind_protection: true
+ dns_rebind_protection: true,
+ deny_all_requests_except_allowed: false
)
.and_return([Addressable::URI.parse('https://[2606:4700:90:0:f22e:fbec:5bed:a9b9]/gitlab-org/gitlab-development-kit'), 'gitlab.com'])
end
@@ -408,14 +411,15 @@ RSpec.describe Projects::ImportService, feature_category: :importers do
before do
project.import_url = "http://example.com/group/project"
- allow(Gitlab::UrlBlocker).to receive(:validate!)
+ allow(Gitlab::HTTP_V2::UrlBlocker).to receive(:validate!)
.with(
project.import_url,
ports: Project::VALID_IMPORT_PORTS,
schemes: Project::VALID_IMPORT_PROTOCOLS,
allow_local_network: false,
allow_localhost: false,
- dns_rebind_protection: true
+ dns_rebind_protection: true,
+ deny_all_requests_except_allowed: false
)
.and_return([Addressable::URI.parse("http://172.16.123.1/group/project"), 'example.com'])
end
@@ -437,14 +441,15 @@ RSpec.describe Projects::ImportService, feature_category: :importers do
before do
project.import_url = "git://example.com/group/project.git"
- allow(Gitlab::UrlBlocker).to receive(:validate!)
+ allow(Gitlab::HTTP_V2::UrlBlocker).to receive(:validate!)
.with(
project.import_url,
ports: Project::VALID_IMPORT_PORTS,
schemes: Project::VALID_IMPORT_PROTOCOLS,
allow_local_network: false,
allow_localhost: false,
- dns_rebind_protection: true
+ dns_rebind_protection: true,
+ deny_all_requests_except_allowed: false
)
.and_return([Addressable::URI.parse("git://172.16.123.1/group/project"), 'example.com'])
end
diff --git a/spec/services/projects/participants_service_spec.rb b/spec/services/projects/participants_service_spec.rb
index 167df7996ca..c178f75cd38 100644
--- a/spec/services/projects/participants_service_spec.rb
+++ b/spec/services/projects/participants_service_spec.rb
@@ -225,7 +225,7 @@ RSpec.describe Projects::ParticipantsService, feature_category: :groups_and_proj
create(:project_group_link, group: invited_public_group, project: public_project)
- expect(usernames).to include(invited_public_group.users.first.username)
+ expect(usernames).to include(invited_public_group.group_members.first.user.username)
end
it 'returns members of the ancestral groups of the private group' do
diff --git a/spec/services/projects/update_remote_mirror_service_spec.rb b/spec/services/projects/update_remote_mirror_service_spec.rb
index b65f7a50e4c..5585c9e8179 100644
--- a/spec/services/projects/update_remote_mirror_service_spec.rb
+++ b/spec/services/projects/update_remote_mirror_service_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe Projects::UpdateRemoteMirrorService, feature_category: :source_co
context 'when the URL is blocked' do
before do
- allow(Gitlab::UrlBlocker).to receive(:blocked_url?).and_return(true)
+ allow(Gitlab::HTTP_V2::UrlBlocker).to receive(:blocked_url?).and_return(true)
end
it 'hard retries and returns error status' do
diff --git a/spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb b/spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb
index 625f16824b4..ec46c4a9ed8 100644
--- a/spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb
+++ b/spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb
@@ -168,7 +168,13 @@ RSpec.shared_examples 'PUT resource access tokens available' do
it 'removes membership of bot user' do
subject
- expect(resource.reload.bots).not_to include(access_token_user)
+ resource_bots = if resource.is_a?(Project)
+ resource.bots
+ elsif resource.is_a?(Group)
+ User.bots.id_in(resource.all_group_members.non_invite.pluck_primary_key)
+ end
+
+ expect(resource_bots).not_to include(access_token_user)
end
it 'creates GhostUserMigration records to handle migration in a worker' do
diff --git a/spec/validators/addressable_url_validator_spec.rb b/spec/validators/addressable_url_validator_spec.rb
index c95c0563a55..56c71ec5630 100644
--- a/spec/validators/addressable_url_validator_spec.rb
+++ b/spec/validators/addressable_url_validator_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe AddressableUrlValidator do
value.is_a?(Proc) ? value.call : value
end
- expect(Gitlab::UrlBlocker)
+ expect(Gitlab::HTTP_V2::UrlBlocker)
.to receive(:validate!)
.with(badge.link_url, expected_opts)
.and_return(true)
@@ -338,7 +338,7 @@ RSpec.describe AddressableUrlValidator do
context 'not given' do
before do
- allow(Gitlab::CurrentSettings).to receive(:current_application_settings?).and_return(true)
+ allow(ApplicationSetting).to receive(:current).and_return(ApplicationSetting.new)
stub_application_setting(deny_all_requests_except_allowed: app_setting)
end
diff --git a/spec/workers/bulk_imports/pipeline_worker_spec.rb b/spec/workers/bulk_imports/pipeline_worker_spec.rb
index 368c7537641..c565195dc84 100644
--- a/spec/workers/bulk_imports/pipeline_worker_spec.rb
+++ b/spec/workers/bulk_imports/pipeline_worker_spec.rb
@@ -618,43 +618,6 @@ RSpec.describe BulkImports::PipelineWorker, feature_category: :importers do
end
end
end
-
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(bulk_import_limit_concurrent_batches: false)
- end
-
- it 'does not limit batches' do
- expect(BulkImports::PipelineBatchWorker).to receive(:perform_async).exactly(3).times
- expect(worker).to receive(:log_extra_metadata_on_done).with(:tracker_batch_numbers_enqueued, [1, 2, 3])
- expect(worker).to receive(:log_extra_metadata_on_done).with(:tracker_final_batch_was_enqueued, true)
-
- worker.perform(pipeline_tracker.id, pipeline_tracker.stage, entity.id)
-
- pipeline_tracker.reload
-
- expect(pipeline_tracker.status_name).to eq(:started)
- expect(pipeline_tracker.batched).to eq(true)
- expect(pipeline_tracker.batches.pluck_batch_numbers).to contain_exactly(1, 2, 3)
- expect(described_class.jobs).to be_empty
- end
-
- it 'still enqueues only missing pipelines batches' do
- create(:bulk_import_batch_tracker, tracker: pipeline_tracker, batch_number: 2)
- expect(BulkImports::PipelineBatchWorker).to receive(:perform_async).twice
- expect(worker).to receive(:log_extra_metadata_on_done).with(:tracker_batch_numbers_enqueued, [1, 3])
- expect(worker).to receive(:log_extra_metadata_on_done).with(:tracker_final_batch_was_enqueued, true)
-
- worker.perform(pipeline_tracker.id, pipeline_tracker.stage, entity.id)
-
- pipeline_tracker.reload
-
- expect(pipeline_tracker.status_name).to eq(:started)
- expect(pipeline_tracker.batched).to eq(true)
- expect(pipeline_tracker.batches.pluck_batch_numbers).to contain_exactly(1, 2, 3)
- expect(described_class.jobs).to be_empty
- end
- end
end
end
end
diff --git a/vendor/project_templates/typo3_distribution.tar.gz b/vendor/project_templates/typo3_distribution.tar.gz
index 8f831914b95..fbbfa30ffe8 100644
--- a/vendor/project_templates/typo3_distribution.tar.gz
+++ b/vendor/project_templates/typo3_distribution.tar.gz
Binary files differ