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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/CODEOWNERS227
-rw-r--r--app/assets/javascripts/ci/job_details/components/job_header.vue35
-rw-r--r--app/assets/javascripts/ci/job_details/job_app.vue5
-rw-r--r--app/controllers/concerns/issuable_collections.rb2
-rw-r--r--app/graphql/types/ci/job_trace_type.rb11
-rw-r--r--app/models/bulk_imports/entity.rb4
-rw-r--r--app/models/pages/lookup_path.rb2
-rw-r--r--app/models/pages/virtual_domain.rb10
-rw-r--r--app/services/bulk_imports/create_pipeline_trackers_service.rb72
-rw-r--r--app/workers/all_queues.yml9
-rw-r--r--app/workers/bulk_import_worker.rb55
-rw-r--r--app/workers/pages/invalidate_domain_cache_worker.rb37
-rw-r--r--config/feature_flags/development/api_keyset_pagination_multi_order.yml8
-rw-r--r--config/feature_flags/development/graphql_job_trace_html_summary_max_size.yml (renamed from config/feature_flags/development/cache_pages_domain_api.yml)11
-rw-r--r--config/sidekiq_queues.yml2
-rw-r--r--doc/administration/backup_restore/restore_gitlab.md16
-rw-r--r--doc/administration/raketasks/maintenance.md6
-rw-r--r--doc/api/graphql/reference/index.md2
-rw-r--r--doc/api/rest/index.md1
-rw-r--r--doc/api/users.md2
-rw-r--r--doc/ci/review_apps/img/enable_review_app_v16.pngbin0 -> 105290 bytes
-rw-r--r--doc/ci/review_apps/index.md4
-rw-r--r--lib/api/internal/pages.rb11
-rw-r--r--lib/api/users.rb6
-rw-r--r--lib/gitlab/ci/trace.rb4
-rw-r--r--lib/gitlab/ci/trace/stream.rb41
-rw-r--r--lib/gitlab/database/tables_truncate.rb52
-rw-r--r--lib/gitlab/event_store.rb20
-rw-r--r--lib/gitlab/pages.rb1
-rw-r--r--lib/gitlab/pages/virtual_host_finder.rb18
-rw-r--r--lib/gitlab/pagination/cursor_based_keyset.rb31
-rw-r--r--lib/gitlab/pagination/keyset/cursor_based_request_context.rb8
-rw-r--r--lib/system_check/app/table_truncate_check.rb34
-rw-r--r--lib/system_check/rake_task/app_task.rb1
-rw-r--r--locale/gitlab.pot3
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb41
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb6
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb17
-rw-r--r--spec/features/merge_request/user_sets_to_auto_merge_spec.rb (renamed from spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb)46
-rw-r--r--spec/frontend/ci/job_details/components/job_header_spec.js33
-rw-r--r--spec/graphql/types/ci/job_trace_type_spec.rb114
-rw-r--r--spec/lib/gitlab/ci/trace/stream_spec.rb50
-rw-r--r--spec/lib/gitlab/database/tables_truncate_spec.rb278
-rw-r--r--spec/lib/gitlab/pages/cache_control_spec.rb88
-rw-r--r--spec/lib/gitlab/pages/virtual_host_finder_spec.rb58
-rw-r--r--spec/lib/gitlab/pagination/cursor_based_keyset_spec.rb102
-rw-r--r--spec/lib/system_check/app/table_truncate_check_spec.rb75
-rw-r--r--spec/models/bulk_imports/entity_spec.rb8
-rw-r--r--spec/models/pages/virtual_domain_spec.rb15
-rw-r--r--spec/requests/api/users_spec.rb43
-rw-r--r--spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb176
-rw-r--r--spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb3
-rw-r--r--spec/support/shared_examples/requests/api_keyset_pagination_shared_examples.rb8
-rw-r--r--spec/workers/bulk_import_worker_spec.rb169
-rw-r--r--spec/workers/pages/invalidate_domain_cache_worker_spec.rb267
56 files changed, 1146 insertions, 1204 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index ddcb8f2ffaf..56816fe6b2b 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -2,12 +2,14 @@
# project here: https://gitlab.com/gitlab-org/gitlab/-/project_members
# As described in https://docs.gitlab.com/ee/user/project/code_owners.html
-* @gitlab-org/maintainers/rails-backend @gitlab-org/maintainers/frontend @gitlab-org/maintainers/database @gl-quality/qe-maintainers @gl-quality/tooling-maintainers @gitlab-org/delivery @gitlab-org/maintainers/cicd-templates @nolith @gitlab-org/tw-leadership
+# In order to support release automation, each required approval group MUST
+# include @gitlab-bot
+* @gitlab-bot @gitlab-org/maintainers/rails-backend @gitlab-org/maintainers/frontend @gitlab-org/maintainers/database @gl-quality/qe-maintainers @gl-quality/tooling-maintainers @gitlab-org/delivery @gitlab-org/maintainers/cicd-templates @nolith @gitlab-org/tw-leadership
-.gitlab/CODEOWNERS @gitlab-org/development-leaders @gitlab-org/tw-leadership
+.gitlab/CODEOWNERS @gitlab-bot @gitlab-org/development-leaders @gitlab-org/tw-leadership
## Allows release tooling to update the Gitaly Version
-GITALY_SERVER_VERSION @project_278964_bot6 @gitlab-org/maintainers/rails-backend @gitlab-org/delivery
+GITALY_SERVER_VERSION @gitlab-bot @project_278964_bot6 @gitlab-org/maintainers/rails-backend @gitlab-org/delivery
## Files that are excluded from required approval
## These rules override the * rule above, so that changes to docs and templates
@@ -23,13 +25,13 @@ GITALY_SERVER_VERSION @project_278964_bot6 @gitlab-org/maintainers/rails-backend
## Technical writing files that do not need `*` rule approval,
## but still require an approval from a TW team DRI for each file.
-/data/deprecations/templates/ @marcel.amirault @sarahgerman @gitlab-org/tw-leadership
-.markdownlint.yml @marcel.amirault @eread @aqualls @gitlab-org/tw-leadership
-/doc/.markdownlint/ @marcel.amirault @eread @aqualls @gitlab-org/tw-leadership
-/doc/.vale/ @marcel.amirault @eread @aqualls @gitlab-org/tw-leadership
-/lib/tasks/gitlab/tw/codeowners.rake @aqualls @gitlab-org/tw-leadership
-/scripts/lint-doc.sh @marcel.amirault @eread @axil @sarahgerman @gitlab-org/tw-leadership
-/scripts/lint-docs-metadata.sh @marcel.amirault @eread @axil @sarahgerman @gitlab-org/tw-leadership
+/data/deprecations/templates/ @gitlab-bot @marcel.amirault @sarahgerman @gitlab-org/tw-leadership
+.markdownlint.yml @gitlab-bot @marcel.amirault @eread @aqualls @gitlab-org/tw-leadership
+/doc/.markdownlint/ @gitlab-bot @marcel.amirault @eread @aqualls @gitlab-org/tw-leadership
+/doc/.vale/ @gitlab-bot @marcel.amirault @eread @aqualls @gitlab-org/tw-leadership
+/lib/tasks/gitlab/tw/codeowners.rake @gitlab-bot @aqualls @gitlab-org/tw-leadership
+/scripts/lint-doc.sh @gitlab-bot @marcel.amirault @eread @axil @sarahgerman @gitlab-org/tw-leadership
+/scripts/lint-docs-metadata.sh @gitlab-bot @marcel.amirault @eread @axil @sarahgerman @gitlab-org/tw-leadership
^[Source code editing]
.solargraph.yml.example @igor.drozdov
@@ -48,13 +50,13 @@ GITALY_SERVER_VERSION @project_278964_bot6 @gitlab-org/maintainers/rails-backend
/spec/frontend_integration/
/ee/spec/frontend_integration/
-[Clickhouse] @gitlab-org/maintainers/clickhouse
+[Clickhouse] @gitlab-bot @gitlab-org/maintainers/clickhouse
/db/click_house/
/ee/db/click_house/
/**/click(_|-)?house/
## We list db/ subfolders explicitly as we don't want to match Clickhouse files
-[Database] @gitlab-org/maintainers/database
+[Database] @gitlab-bot @gitlab-org/maintainers/database
/db/database_connections/
/ee/db/database_connections/
/db/docs/
@@ -79,31 +81,31 @@ GITALY_SERVER_VERSION @project_278964_bot6 @gitlab-org/maintainers/rails-backend
/ee/app/finders/
/rubocop/rubocop-migrations.yml
-[Pipeline configuration] @gl-quality/eng-prod
+[Pipeline configuration] @gitlab-bot @gl-quality/eng-prod
/.gitlab-ci.yml
/.gitlab/ci/
-/.gitlab/ci/docs.gitlab-ci.yml @gl-quality/eng-prod @gl-docsteam
-/.gitlab/ci/frontend.gitlab-ci.yml @gl-quality/eng-prod @gitlab-org/maintainers/frontend
-/.gitlab/ci/package-and-test/ @gl-quality/eng-prod @gl-quality/qe-maintainers
-/.gitlab/ci/qa.gitlab-ci.yml @gl-quality/eng-prod @gl-quality/qe-maintainers
-/.gitlab/ci/qa-common/ @gl-quality/eng-prod @gl-quality/qe-maintainers
-/.gitlab/ci/releases.gitlab-ci.yml @gl-quality/eng-prod @gitlab-org/delivery
-/.gitlab/ci/reports.gitlab-ci.yml @gl-quality/eng-prod @gitlab-com/gl-security/appsec
-/.gitlab/ci/review-apps/qa.gitlab-ci.yml @gl-quality/eng-prod @gl-quality/qe-maintainers
-/.gitlab/ci/test-on-gdk/ @gl-quality/eng-prod @gl-quality/qe-maintainers
+/.gitlab/ci/docs.gitlab-ci.yml @gitlab-bot @gl-quality/eng-prod @gl-docsteam
+/.gitlab/ci/frontend.gitlab-ci.yml @gitlab-bot @gl-quality/eng-prod @gitlab-org/maintainers/frontend
+/.gitlab/ci/package-and-test/ @gitlab-bot @gl-quality/eng-prod @gl-quality/qe-maintainers
+/.gitlab/ci/qa.gitlab-ci.yml @gitlab-bot @gl-quality/eng-prod @gl-quality/qe-maintainers
+/.gitlab/ci/qa-common/ @gitlab-bot @gl-quality/eng-prod @gl-quality/qe-maintainers
+/.gitlab/ci/releases.gitlab-ci.yml @gitlab-bot @gl-quality/eng-prod @gitlab-org/delivery
+/.gitlab/ci/reports.gitlab-ci.yml @gitlab-bot @gl-quality/eng-prod @gitlab-com/gl-security/appsec
+/.gitlab/ci/review-apps/qa.gitlab-ci.yml @gitlab-bot @gl-quality/eng-prod @gl-quality/qe-maintainers
+/.gitlab/ci/test-on-gdk/ @gitlab-bot @gl-quality/eng-prod @gl-quality/qe-maintainers
/gems/gem.gitlab-ci.yml
-[Tooling] @gl-quality/eng-prod
+[Tooling] @gitlab-bot @gl-quality/eng-prod
Dangerfile
/danger/
/tooling/danger/
/scripts/
-/scripts/**/*.rb @gl-quality/eng-prod @gitlab-org/maintainers/rails-backend
-/scripts/**/glfm/**/* @gl-quality/eng-prod @gitlab-org/plan-stage/backend-engineers
-/scripts/**/*.js @gl-quality/eng-prod @gitlab-org/maintainers/frontend
-/scripts/frontend/ @gl-quality/eng-prod @gitlab-org/maintainers/frontend
-/scripts/remote_development/ @gitlab-org/maintainers/remote-development/backend
-/scripts/review_apps/seed-dast-test-data.sh @gl-quality/eng-prod @dappelt @ngeorge1
+/scripts/**/*.rb @gitlab-bot @gl-quality/eng-prod @gitlab-org/maintainers/rails-backend
+/scripts/**/glfm/**/* @gitlab-bot @gl-quality/eng-prod @gitlab-org/plan-stage/backend-engineers
+/scripts/**/*.js @gitlab-bot @gl-quality/eng-prod @gitlab-org/maintainers/frontend
+/scripts/frontend/ @gitlab-bot @gl-quality/eng-prod @gitlab-org/maintainers/frontend
+/scripts/remote_development/ @gitlab-bot @gitlab-org/maintainers/remote-development/backend
+/scripts/review_apps/seed-dast-test-data.sh @gitlab-bot @gl-quality/eng-prod @dappelt @ngeorge1
/.codeclimate.yml
/.dockerignore
/.editorconfig
@@ -415,7 +417,7 @@ Dangerfile
^[Workhorse] @gitlab-org/maintainers/gitlab-workhorse
/workhorse/
-[Application Security] @gitlab-com/gl-security/appsec
+[Application Security] @gitlab-bot @gitlab-com/gl-security/appsec
/app/assets/javascripts/lib/dompurify.js
/app/assets/javascripts/gfm_auto_complete.js
/ee/app/assets/javascripts/gfm_auto_complete.js
@@ -1024,7 +1026,7 @@ lib/gitlab/checks/**
/doc/user/workspace/ @ashrafkhamis
# End rake-managed-docs-block
-[Authentication and Authorization] @gitlab-org/manage/authentication-and-authorization/approvers
+[Authentication and Authorization] @gitlab-bot @gitlab-org/manage/authentication-and-authorization/approvers
/app/assets/javascripts/access_tokens/
/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql
/app/assets/javascripts/authentication/
@@ -1270,7 +1272,7 @@ lib/gitlab/checks/**
/lib/tasks/gitlab/password.rake
/lib/tasks/tokens.rake
-[Verify] @gitlab-org/maintainers/cicd-verify @shinya.maeda @stanhu @ayufan
+[Verify] @gitlab-bot @gitlab-org/maintainers/cicd-verify @shinya.maeda @stanhu @ayufan
# With these catch-all rules we will require backend approval and use it as an
# opportunity to refine specific rules defined in this section.
# Note that frontend, CI templates and other concerns should be kept within
@@ -1341,93 +1343,93 @@ lib/gitlab/checks/**
/ee/lib/ee/api/entities/merge_train.rb
# Overrides for Verify. These files below require approval from teams outside Verify.
-/**/lib/**/ci/reports/**/ @gitlab-org/maintainers/rails-backend
-/**/lib/**/ci/parsers/**/ @gitlab-org/maintainers/rails-backend
-/ee/lib/gitlab/ci/parsers/license_compliance/ @gitlab-org/secure/composition-analysis-be
-/ee/lib/gitlab/ci/parsers/security/ @gitlab-org/govern/threat-insights-backend-team
-/ee/lib/gitlab/ci/reports/coverage_fuzzing/ @gitlab-org/secure/fuzzing-be
-/ee/lib/gitlab/ci/reports/dependency_list/ @gitlab-org/secure/composition-analysis-be
-/ee/lib/gitlab/ci/reports/license_scanning/ @gitlab-org/secure/composition-analysis-be
-/ee/lib/gitlab/ci/reports/security/ @gitlab-org/govern/threat-insights-backend-team
+/**/lib/**/ci/reports/**/ @gitlab-bot @gitlab-org/maintainers/rails-backend
+/**/lib/**/ci/parsers/**/ @gitlab-bot @gitlab-org/maintainers/rails-backend
+/ee/lib/gitlab/ci/parsers/license_compliance/ @gitlab-bot @gitlab-org/secure/composition-analysis-be
+/ee/lib/gitlab/ci/parsers/security/ @gitlab-bot @gitlab-org/govern/threat-insights-backend-team
+/ee/lib/gitlab/ci/reports/coverage_fuzzing/ @gitlab-bot @gitlab-org/secure/fuzzing-be
+/ee/lib/gitlab/ci/reports/dependency_list/ @gitlab-bot @gitlab-org/secure/composition-analysis-be
+/ee/lib/gitlab/ci/reports/license_scanning/ @gitlab-bot @gitlab-org/secure/composition-analysis-be
+/ee/lib/gitlab/ci/reports/security/ @gitlab-bot @gitlab-org/govern/threat-insights-backend-team
# Verify frontend
-/**/javascripts/ci/ @gitlab-org/ci-cd/verify/frontend
-/**/javascripts/token_access/ @gitlab-org/ci-cd/verify/frontend
-/**/javascripts/admin/application_settings/runner_token_expiration/ @gitlab-org/ci-cd/verify/frontend
-/**/javascripts/usage_quotas/pipelines/ @gitlab-org/ci-cd/verify/frontend @sheldonled @aalakkad @kpalchyk
+/**/javascripts/ci/ @gitlab-bot @gitlab-org/ci-cd/verify/frontend
+/**/javascripts/token_access/ @gitlab-bot @gitlab-org/ci-cd/verify/frontend
+/**/javascripts/admin/application_settings/runner_token_expiration/ @gitlab-bot @gitlab-org/ci-cd/verify/frontend
+/**/javascripts/usage_quotas/pipelines/ @gitlab-bot @gitlab-org/ci-cd/verify/frontend @sheldonled @aalakkad @kpalchyk
## Verify:Runner Fleet Backend
-/app/controllers/admin/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/controllers/concerns/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/controllers/groups/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/controllers/projects/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/controllers/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/finders/ci/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/graphql/mutations/ci/runner/ @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/graphql/resolvers/ci/*_runners_resolver.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/graphql/resolvers/ci/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/graphql/types/ci/runner_*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/graphql/types/namespace/shared_runners_setting_enum.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/graphql/types/permission_types/ci/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/models/ci/build_runner_session.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/models/ci/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/models/concerns/ci/has_runner_executor.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/models/concerns/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/models/preloaders/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/policies/ci/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/presenters/ci/runner_*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/serializers/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/services/groups/update_shared_runners_service.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/services/ci/runners/ @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/app/workers/ci/runners/ @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/db/docs/ci_runner*.yml @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/ee/app/controllers/ee/admin/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/ee/app/controllers/ee/groups/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/ee/app/graphql/ee/mutations/ci/runner/ @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/ee/app/graphql/ee/types/ci/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/ee/app/graphql/resolvers/ci/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/ee/app/models/ee/ci/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/ee/app/policies/ee/ci/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/ee/app/services/audit_events/*runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/ee/app/services/ci/runners/ @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/ee/app/services/ee/ci/runners/ @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/ee/app/workers/ci/runners/ @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/lib/api/ci/helpers/runner.rb @gitlab-org/maintainers/cicd-verify @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/lib/api/ci/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/lib/api/ci/runner.rb @gitlab-org/maintainers/cicd-verify @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/lib/api/entities/ci/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/lib/gitlab/audit/ci_runner_token_author.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/lib/gitlab/ci/runner*.rb @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/lib/gitlab/seeders/ci/runner/ @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
-/lib/tasks/gitlab/seed/runner_fleet.rake @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/controllers/admin/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/controllers/concerns/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/controllers/groups/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/controllers/projects/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/controllers/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/finders/ci/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/graphql/mutations/ci/runner/ @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/graphql/resolvers/ci/*_runners_resolver.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/graphql/resolvers/ci/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/graphql/types/ci/runner_*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/graphql/types/namespace/shared_runners_setting_enum.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/graphql/types/permission_types/ci/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/models/ci/build_runner_session.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/models/ci/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/models/concerns/ci/has_runner_executor.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/models/concerns/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/models/preloaders/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/policies/ci/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/presenters/ci/runner_*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/serializers/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/services/groups/update_shared_runners_service.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/services/ci/runners/ @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/app/workers/ci/runners/ @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/db/docs/ci_runner*.yml @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/ee/app/controllers/ee/admin/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/ee/app/controllers/ee/groups/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/ee/app/graphql/ee/mutations/ci/runner/ @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/ee/app/graphql/ee/types/ci/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/ee/app/graphql/resolvers/ci/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/ee/app/models/ee/ci/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/ee/app/policies/ee/ci/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/ee/app/services/audit_events/*runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/ee/app/services/ci/runners/ @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/ee/app/services/ee/ci/runners/ @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/ee/app/workers/ci/runners/ @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/lib/api/ci/helpers/runner.rb @gitlab-bot @gitlab-org/maintainers/cicd-verify @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/lib/api/ci/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/lib/api/ci/runner.rb @gitlab-bot @gitlab-org/maintainers/cicd-verify @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/lib/api/entities/ci/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/lib/gitlab/audit/ci_runner_token_author.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/lib/gitlab/ci/runner*.rb @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/lib/gitlab/seeders/ci/runner/ @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
+/lib/tasks/gitlab/seed/runner_fleet.rake @gitlab-bot @gitlab-org/ci-cd/runner-fleet-team/backend-approvers
# CI/CD templates require approval from specific owners.
-/lib/gitlab/ci/templates/ @gitlab-org/maintainers/cicd-templates
-/lib/gitlab/ci/templates/Security/ @gonzoyumo @twoodham @amarpatel
-/lib/gitlab/ci/templates/Security/API-Fuzzing.*.yml @gitlab-org/secure/dynamic-analysis
-/lib/gitlab/ci/templates/Security/Container-Scanning.*.yml @gitlab-org/secure/composition-analysis-be
-/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.*.yml @gitlab-org/secure/dynamic-analysis
-/lib/gitlab/ci/templates/Security/DAST.*.yml @gitlab-org/secure/dynamic-analysis
-/lib/gitlab/ci/templates/Security/Dependency-Scanning.*.yml @gitlab-org/secure/composition-analysis-be
-/lib/gitlab/ci/templates/Security/License-Scanning.*.yml @gitlab-org/secure/composition-analysis-be
-/lib/gitlab/ci/templates/Security/SAST.*.yml @gitlab-org/secure/static-analysis
-/lib/gitlab/ci/templates/Security/Secret-Detection.*.yml @gitlab-org/secure/static-analysis
-/lib/gitlab/ci/templates/Security/Secure-Binaries.*.yml @gitlab-org/secure/static-analysis @gitlab-org/secure/composition-analysis-be @gitlab-org/secure/dynamic-analysis
+/lib/gitlab/ci/templates/ @gitlab-bot @gitlab-org/maintainers/cicd-templates
+/lib/gitlab/ci/templates/Security/ @gitlab-bot @gonzoyumo @twoodham @amarpatel
+/lib/gitlab/ci/templates/Security/API-Fuzzing.*.yml @gitlab-bot @gitlab-org/secure/dynamic-analysis
+/lib/gitlab/ci/templates/Security/Container-Scanning.*.yml @gitlab-bot @gitlab-org/secure/composition-analysis-be
+/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.*.yml @gitlab-bot @gitlab-org/secure/dynamic-analysis
+/lib/gitlab/ci/templates/Security/DAST.*.yml @gitlab-bot @gitlab-org/secure/dynamic-analysis
+/lib/gitlab/ci/templates/Security/Dependency-Scanning.*.yml @gitlab-bot @gitlab-org/secure/composition-analysis-be
+/lib/gitlab/ci/templates/Security/License-Scanning.*.yml @gitlab-bot @gitlab-org/secure/composition-analysis-be
+/lib/gitlab/ci/templates/Security/SAST.*.yml @gitlab-bot @gitlab-org/secure/static-analysis
+/lib/gitlab/ci/templates/Security/Secret-Detection.*.yml @gitlab-bot @gitlab-org/secure/static-analysis
+/lib/gitlab/ci/templates/Security/Secure-Binaries.*.yml @gitlab-bot @gitlab-org/secure/static-analysis @gitlab-org/secure/composition-analysis-be @gitlab-org/secure/dynamic-analysis
# Note: The `Fortify-FoD-sast.gitlab-ci.yml` template is provided and maintained by Fortify, an official Technology Partner with GitLab.
-/lib/gitlab/ci/templates/Jobs/Container-Scanning.*.yml @gitlab-org/secure/composition-analysis-be
-/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.*.yml @gitlab-org/secure/composition-analysis-be
-/lib/gitlab/ci/templates/Jobs/License-Scanning.*.yml @gitlab-org/secure/composition-analysis-be
-/lib/gitlab/ci/templates/Jobs/SAST.*.yml @gitlab-org/secure/static-analysis
-/lib/gitlab/ci/templates/Jobs/Secret-Detection.*.yml @gitlab-org/secure/static-analysis
+/lib/gitlab/ci/templates/Jobs/Container-Scanning.*.yml @gitlab-bot @gitlab-org/secure/composition-analysis-be
+/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.*.yml @gitlab-bot @gitlab-org/secure/composition-analysis-be
+/lib/gitlab/ci/templates/Jobs/License-Scanning.*.yml @gitlab-bot @gitlab-org/secure/composition-analysis-be
+/lib/gitlab/ci/templates/Jobs/SAST.*.yml @gitlab-bot @gitlab-org/secure/static-analysis
+/lib/gitlab/ci/templates/Jobs/Secret-Detection.*.yml @gitlab-bot @gitlab-org/secure/static-analysis
-[Data Stores::Tenant Scale] @abdwdd @alexpooley @manojmj
+[Data Stores::Tenant Scale] @gitlab-bot @abdwdd @alexpooley @manojmj
lib/api/entities/basic_project_details.rb
lib/api/entities/project_with_access.rb
lib/api/entities/project_identity.rb
lib/api/entities/project.rb
ee/lib/ee/api/entities/project.rb
-[Compliance] @gitlab-org/govern/compliance
+[Compliance] @gitlab-bot @gitlab-org/govern/compliance
/app/services/audit_events/build_service.rb
/ee/app/services/ee/audit_events/build_service.rb
/ee/spec/services/audit_events/custom_audit_event_service_spec.rb
@@ -1490,21 +1492,22 @@ ee/lib/ee/api/entities/project.rb
/app/workers/releases/create_evidence_worker.rb
/app/workers/releases/manage_evidence_worker.rb
-^[Fulfillment::Utilization] @sheldonled @aalakkad @kpalchyk
+^[Fulfillment::Utilization] @gitlab-bot @sheldonled @aalakkad @kpalchyk
/ee/app/assets/javascripts/usage_quotas/components/
/ee/app/assets/javascripts/usage_quotas/seats/
/ee/app/assets/javascripts/usage_quotas/storage/
-[Manage::Foundations] @gitlab-org/manage/foundations/engineering
+[Manage::Foundations] @gitlab-bot @gitlab-org/manage/foundations/engineering
/lib/sidebars/
/ee/lib/sidebars/
-[Global Search] @gitlab-org/search-team/migration-maintainers
+[Global Search] @gitlab-bot @gitlab-org/search-team/migration-maintainers
/ee/elastic/migrate/
/ee/spec/elastic/migrate/
/ee/spec/support/elastic.rb
-[Create::IDE - Remote Development Backend] @gitlab-org/maintainers/remote-development/backend
+[Create::IDE - Remote Development Backend] @gitlab-bot @gitlab-org/maintainers/remote-development/backend
+
/ee/app/models/remote_development/
/ee/app/policies/remote_development/
/ee/app/finders/remote_development/
@@ -1519,7 +1522,7 @@ ee/lib/ee/api/entities/project.rb
/ee/spec/policies/remote_development/
/ee/spec/requests/api/graphql/mutations/remote_development/
/ee/spec/requests/api/graphql/remote_development/
-/ee/spec/features/remote_development/ @gitlab-org/maintainers/remote-development/backend @gitlab-org/maintainers/remote-development/frontend
+/ee/spec/features/remote_development/ @gitlab-bot @gitlab-org/maintainers/remote-development/backend @gitlab-org/maintainers/remote-development/frontend
/ee/spec/finders/remote_development/
/ee/spec/support/shared_contexts/remote_development/
/ee/spec/graphql/types/remote_development/
@@ -1528,9 +1531,9 @@ ee/lib/ee/api/entities/project.rb
/ee/spec/fixtures/remote_development/
/ee/spec/controllers/remote_development/
/ee/spec/services/remote_development/
-/qa/qa/specs/features/**/remote_development/ @gitlab-org/maintainers/remote-development/backend @gl-quality/qe-maintainers
+/qa/qa/specs/features/**/remote_development/ @gitlab-bot @gitlab-org/maintainers/remote-development/backend @gl-quality/qe-maintainers
-[Create::IDE - Remote Development Frontend] @gitlab-org/maintainers/remote-development/frontend
+[Create::IDE - Remote Development Frontend] @gitlab-bot @gitlab-org/maintainers/remote-development/frontend
/ee/app/assets/remote_development/
/ee/app/assets/**/remote_development/
/ee/app/views/remote_development/
diff --git a/app/assets/javascripts/ci/job_details/components/job_header.vue b/app/assets/javascripts/ci/job_details/components/job_header.vue
index 7f4dea05464..13f3eebd447 100644
--- a/app/assets/javascripts/ci/job_details/components/job_header.vue
+++ b/app/assets/javascripts/ci/job_details/components/job_header.vue
@@ -7,13 +7,6 @@ import { __, sprintf } from '~/locale';
import CiBadgeLink from '~/vue_shared/components/ci_badge_link.vue';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-/**
- * Renders header component for job and pipeline page based on UI mockups
- *
- * Used in:
- * - job show page
- * - pipeline show page
- */
export default {
components: {
CiBadgeLink,
@@ -33,33 +26,21 @@ export default {
type: Object,
required: true,
},
- itemName: {
+ name: {
type: String,
required: true,
},
- itemId: {
- type: String,
- required: false,
- default: '',
- },
time: {
type: String,
required: true,
},
user: {
type: Object,
- required: false,
- default: () => ({}),
- },
- hasSidebarButton: {
- type: Boolean,
- required: false,
- default: false,
+ required: true,
},
shouldRenderTriggeredLabel: {
type: Boolean,
- required: false,
- default: true,
+ required: true,
},
},
@@ -92,13 +73,6 @@ export default {
message() {
return this.user?.status?.message;
},
- item() {
- if (this.itemId) {
- return `${this.itemName} #${this.itemId}`;
- }
-
- return this.itemName;
- },
userId() {
return isGid(this.user?.id) ? getIdFromGraphQLId(this.user?.id) : this.user?.id;
},
@@ -121,7 +95,7 @@ export default {
<section class="header-main-content gl-mr-3">
<ci-badge-link class="gl-mr-3" :status="status" />
- <strong data-testid="job-header-item-text">{{ item }}</strong>
+ <strong data-testid="job-name">{{ name }}</strong>
<template v-if="shouldRenderTriggeredLabel">{{ __('started') }}</template>
<template v-else>{{ __('created') }}</template>
@@ -165,7 +139,6 @@ export default {
<slot></slot>
</section>
<gl-button
- v-if="hasSidebarButton"
class="gl-md-display-none gl-ml-auto gl-align-self-start js-sidebar-build-toggle"
icon="chevron-double-lg-left"
:aria-label="__('Toggle sidebar')"
diff --git a/app/assets/javascripts/ci/job_details/job_app.vue b/app/assets/javascripts/ci/job_details/job_app.vue
index 474190fe50e..5137ebfeaa8 100644
--- a/app/assets/javascripts/ci/job_details/job_app.vue
+++ b/app/assets/javascripts/ci/job_details/job_app.vue
@@ -129,7 +129,7 @@ export default {
return Boolean(this.job.retry_path);
},
- itemName() {
+ jobName() {
return sprintf(__('Job %{jobName}'), { jobName: this.job.name });
},
},
@@ -229,9 +229,8 @@ export default {
:status="job.status"
:time="headerTime"
:user="job.user"
- :has-sidebar-button="true"
:should-render-triggered-label="shouldRenderTriggeredLabel"
- :item-name="itemName"
+ :name="jobName"
@clickedSidebarButton="toggleSidebar"
/>
</div>
diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb
index 0fe31d74ae8..5479154f667 100644
--- a/app/controllers/concerns/issuable_collections.rb
+++ b/app/controllers/concerns/issuable_collections.rb
@@ -23,7 +23,7 @@ module IssuableCollections
end
def set_pagination
- row_count = finder.row_count
+ row_count = request.format.atom? ? -1 : finder.row_count
@issuables = @issuables.page(params[:page])
@issuables = per_page_for_relative_position if params[:sort] == 'relative_position'
diff --git a/app/graphql/types/ci/job_trace_type.rb b/app/graphql/types/ci/job_trace_type.rb
index b959d37f327..405c640115d 100644
--- a/app/graphql/types/ci/job_trace_type.rb
+++ b/app/graphql/types/ci/job_trace_type.rb
@@ -5,17 +5,24 @@ module Types
module Ci
class JobTraceType < BaseObject
graphql_name 'CiJobTrace'
+ MAX_SIZE_KB = 16
+ MAX_SIZE_B = MAX_SIZE_KB * 1024
field :html_summary, GraphQL::Types::String, null: false,
alpha: { milestone: '15.11' },
- description: 'HTML summary that contains the tail lines of the trace.' do
+ description: 'HTML summary that contains the tail lines of the trace. ' \
+ "Returns at most #{MAX_SIZE_KB}KB of raw bytes from the trace. " \
+ 'The returned string might start with an unexpected invalid UTF-8 code point due to truncation.' do
argument :last_lines, Integer,
required: false, default_value: 10,
description: 'Number of tail lines to return, up to a maximum of 100 lines.'
end
def html_summary(last_lines:)
- object.html(last_lines: last_lines.clamp(1, 100)).html_safe
+ object.html(
+ last_lines: last_lines.clamp(1, 100),
+ max_size: Feature.enabled?(:graphql_job_trace_html_summary_max_size) ? MAX_SIZE_B : nil
+ ).html_safe
end
end
end
diff --git a/app/models/bulk_imports/entity.rb b/app/models/bulk_imports/entity.rb
index d81286cd2d2..437118c36e8 100644
--- a/app/models/bulk_imports/entity.rb
+++ b/app/models/bulk_imports/entity.rb
@@ -196,6 +196,10 @@ class BulkImports::Entity < ApplicationRecord
update!(has_failures: true)
end
+ def source_version
+ @source_version ||= bulk_import.source_version_info
+ end
+
private
def validate_parent_is_a_group
diff --git a/app/models/pages/lookup_path.rb b/app/models/pages/lookup_path.rb
index 2ffb2e84cbf..e8becc833ca 100644
--- a/app/models/pages/lookup_path.rb
+++ b/app/models/pages/lookup_path.rb
@@ -35,7 +35,7 @@ module Pages
{
type: 'zip',
path: deployment.file.url_or_file_path(
- expire_at: ::Gitlab::Pages::CacheControl::DEPLOYMENT_EXPIRATION.from_now
+ expire_at: ::Gitlab::Pages::DEPLOYMENT_EXPIRATION.from_now
),
global_id: global_id,
sha256: deployment.file_sha256,
diff --git a/app/models/pages/virtual_domain.rb b/app/models/pages/virtual_domain.rb
index aebfbd2b490..0a64e91bf60 100644
--- a/app/models/pages/virtual_domain.rb
+++ b/app/models/pages/virtual_domain.rb
@@ -2,9 +2,8 @@
module Pages
class VirtualDomain
- def initialize(projects:, cache: nil, trim_prefix: nil, domain: nil)
+ def initialize(projects:, trim_prefix: nil, domain: nil)
@projects = projects
- @cache = cache
@trim_prefix = trim_prefix
@domain = domain
end
@@ -25,14 +24,9 @@ module Pages
.reverse
end
- # cache_key is required by #present_cached in ::API::Internal::Pages
- def cache_key
- @cache_key ||= cache&.cache_key
- end
-
private
- attr_reader :projects, :trim_prefix, :domain, :cache
+ attr_reader :projects, :trim_prefix, :domain
def lookup_paths_for(project)
Pages::LookupPath.new(project, trim_prefix: trim_prefix, domain: domain)
diff --git a/app/services/bulk_imports/create_pipeline_trackers_service.rb b/app/services/bulk_imports/create_pipeline_trackers_service.rb
deleted file mode 100644
index 7fa62e0ce8a..00000000000
--- a/app/services/bulk_imports/create_pipeline_trackers_service.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# frozen_string_literal: true
-
-module BulkImports
- class CreatePipelineTrackersService
- def initialize(entity)
- @entity = entity
- end
-
- def execute!
- entity.class.transaction do
- entity.pipelines.each do |pipeline|
- status = skip_pipeline?(pipeline) ? -2 : 0
-
- entity.trackers.create!(
- stage: pipeline[:stage],
- pipeline_name: pipeline[:pipeline],
- status: status
- )
- end
- end
- end
-
- private
-
- attr_reader :entity
-
- def skip_pipeline?(pipeline)
- return false unless source_version.valid?
-
- minimum_version, maximum_version = pipeline.values_at(:minimum_source_version, :maximum_source_version)
-
- if minimum_version && non_patch_source_version < Gitlab::VersionInfo.parse(minimum_version)
- log_skipped_pipeline(pipeline, minimum_version, maximum_version)
- return true
- end
-
- if maximum_version && non_patch_source_version > Gitlab::VersionInfo.parse(maximum_version)
- log_skipped_pipeline(pipeline, minimum_version, maximum_version)
- return true
- end
-
- false
- end
-
- def source_version
- @source_version ||= entity.bulk_import.source_version_info
- end
-
- def non_patch_source_version
- source_version.without_patch
- end
-
- def log_skipped_pipeline(pipeline, minimum_version, maximum_version)
- logger.info(
- message: 'Pipeline skipped as source instance version not compatible with pipeline',
- bulk_import_entity_id: entity.id,
- bulk_import_id: entity.bulk_import_id,
- bulk_import_entity_type: entity.source_type,
- source_full_path: entity.source_full_path,
- pipeline_name: pipeline[:pipeline],
- minimum_source_version: minimum_version,
- maximum_source_version: maximum_version,
- source_version: source_version.to_s,
- importer: 'gitlab_migration'
- )
- end
-
- def logger
- @logger ||= Gitlab::Import::Logger.build
- end
- end
-end
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 8bc33fb46be..6ef7447b9da 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -3369,15 +3369,6 @@
:weight: 1
:idempotent: false
:tags: []
-- :name: pages_invalidate_domain_cache
- :worker_name: Pages::InvalidateDomainCacheWorker
- :feature_category: :pages
- :has_external_dependencies: false
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
- :name: post_receive
:worker_name: PostReceive
:feature_category: :source_code_management
diff --git a/app/workers/bulk_import_worker.rb b/app/workers/bulk_import_worker.rb
index 6bce13c5ff0..83b881ee525 100644
--- a/app/workers/bulk_import_worker.rb
+++ b/app/workers/bulk_import_worker.rb
@@ -22,7 +22,7 @@ class BulkImportWorker # rubocop:disable Scalability/IdempotentWorker
@bulk_import.start! if @bulk_import.created?
created_entities.first(next_batch_size).each do |entity|
- BulkImports::CreatePipelineTrackersService.new(entity).execute!
+ create_tracker(entity)
entity.start!
@@ -51,7 +51,7 @@ class BulkImportWorker # rubocop:disable Scalability/IdempotentWorker
end
def all_entities_failed?
- entities.all? { |entity| entity.failed? }
+ entities.all?(&:failed?)
end
# A new BulkImportWorker job is enqueued to either
@@ -72,4 +72,55 @@ class BulkImportWorker # rubocop:disable Scalability/IdempotentWorker
def next_batch_size
[DEFAULT_BATCH_SIZE - started_entities.count, 0].max
end
+
+ def create_tracker(entity)
+ entity.class.transaction do
+ entity.pipelines.each do |pipeline|
+ status = skip_pipeline?(pipeline, entity) ? :skipped : :created
+
+ entity.trackers.create!(
+ stage: pipeline[:stage],
+ pipeline_name: pipeline[:pipeline],
+ status: BulkImports::Tracker.state_machine.states[status].value
+ )
+ end
+ end
+ end
+
+ def skip_pipeline?(pipeline, entity)
+ return false unless entity.source_version.valid?
+
+ minimum_version, maximum_version = pipeline.values_at(:minimum_source_version, :maximum_source_version)
+
+ if source_version_out_of_range?(minimum_version, maximum_version, entity.source_version.without_patch)
+ log_skipped_pipeline(pipeline, entity, minimum_version, maximum_version)
+ return true
+ end
+
+ false
+ end
+
+ def source_version_out_of_range?(minimum_version, maximum_version, non_patch_source_version)
+ (minimum_version && non_patch_source_version < Gitlab::VersionInfo.parse(minimum_version)) ||
+ (maximum_version && non_patch_source_version > Gitlab::VersionInfo.parse(maximum_version))
+ end
+
+ def log_skipped_pipeline(pipeline, entity, minimum_version, maximum_version)
+ logger.info(
+ message: 'Pipeline skipped as source instance version not compatible with pipeline',
+ bulk_import_entity_id: entity.id,
+ bulk_import_id: entity.bulk_import_id,
+ bulk_import_entity_type: entity.source_type,
+ source_full_path: entity.source_full_path,
+ pipeline_name: pipeline[:pipeline],
+ minimum_source_version: minimum_version,
+ maximum_source_version: maximum_version,
+ source_version: entity.source_version.to_s,
+ importer: 'gitlab_migration'
+ )
+ end
+
+ def logger
+ @logger ||= Gitlab::Import::Logger.build
+ end
end
diff --git a/app/workers/pages/invalidate_domain_cache_worker.rb b/app/workers/pages/invalidate_domain_cache_worker.rb
deleted file mode 100644
index 1700b681b94..00000000000
--- a/app/workers/pages/invalidate_domain_cache_worker.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-module Pages
- class InvalidateDomainCacheWorker
- include Gitlab::EventStore::Subscriber
-
- idempotent!
-
- feature_category :pages
-
- def handle_event(event)
- domain_ids(event).each do |domain_id|
- ::Gitlab::Pages::CacheControl
- .for_domain(domain_id)
- .clear_cache
- end
-
- event.data.values_at(
- :root_namespace_id,
- :old_root_namespace_id,
- :new_root_namespace_id
- ).compact.uniq.each do |namespace_id|
- ::Gitlab::Pages::CacheControl
- .for_namespace(namespace_id)
- .clear_cache
- end
- end
-
- def domain_ids(event)
- ids = PagesDomain.ids_for_project(event.data[:project_id])
-
- ids << event.data[:domain_id] if event.data[:domain_id]
-
- ids
- end
- end
-end
diff --git a/config/feature_flags/development/api_keyset_pagination_multi_order.yml b/config/feature_flags/development/api_keyset_pagination_multi_order.yml
new file mode 100644
index 00000000000..6fa174e9814
--- /dev/null
+++ b/config/feature_flags/development/api_keyset_pagination_multi_order.yml
@@ -0,0 +1,8 @@
+---
+name: api_keyset_pagination_multi_order
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/130019
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/422999
+milestone: '16.5'
+type: development
+group: group::authentication and authorization
+default_enabled: false
diff --git a/config/feature_flags/development/cache_pages_domain_api.yml b/config/feature_flags/development/graphql_job_trace_html_summary_max_size.yml
index 409497aa22d..88e99afddf3 100644
--- a/config/feature_flags/development/cache_pages_domain_api.yml
+++ b/config/feature_flags/development/graphql_job_trace_html_summary_max_size.yml
@@ -1,8 +1,7 @@
----
-name: cache_pages_domain_api
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88956
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/364127
-milestone: '15.2'
+name: graphql_job_trace_html_summary_max_size
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/130984
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/425196
+milestone: '16.5'
+group: group::pipeline execution
type: development
-group: group::editor
default_enabled: false
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 4957e5f4979..d14c20426df 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -481,8 +481,6 @@
- 1
- - pages_domain_verification
- 1
-- - pages_invalidate_domain_cache
- - 1
- - personal_access_tokens
- 1
- - pipeline_background
diff --git a/doc/administration/backup_restore/restore_gitlab.md b/doc/administration/backup_restore/restore_gitlab.md
index d641d50b33d..c7439a88661 100644
--- a/doc/administration/backup_restore/restore_gitlab.md
+++ b/doc/administration/backup_restore/restore_gitlab.md
@@ -450,3 +450,19 @@ For more information, see:
- [Having different owners](https://www.postgresql.org/message-id/2039.1177339749@sss.pgh.pa.us).
- Stack Overflow: [Resulting errors](https://stackoverflow.com/questions/4368789/error-must-be-owner-of-language-plpgsql).
+
+### Restoring fails due to Git server hook
+
+While restoring from backup, you can encounter an error when the following are true:
+
+- A Git Server Hook (`custom_hook`) is configured using the method for [GitLab version 15.10 and earlier](../server_hooks.md)
+- Your GitLab version is on version 15.11 and later
+- You created symlinks to a directory outside of the GitLab-managed locations
+
+The error looks like:
+
+```plaintext
+{"level":"fatal","msg":"restore: pipeline: 1 failures encountered:\n - @hashed/path/to/hashed_repository.git (path/to_project): manager: restore custom hooks, \"@hashed/path/to/hashed_repository/<BackupTimestamp>_<GitLabVersion>-ee/001.custom_hooks.tar\": rpc error: code = Internal desc = setting custom hooks: generating prepared vote: walking directory: copying file to hash: read /mnt/gitlab-app/git-data/repositories/+gitaly/tmp/default-repositories.old.<timestamp>.<temporaryfolder>/custom_hooks/compliance-triggers.d: is a directory\n","pid":3256017,"time":"2023-08-10T20:09:44.395Z"}
+```
+
+To resolve this, you can update the Git [server hooks](../server_hooks.md) for GitLab version 15.11 and later, and create a new backup.
diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md
index e8c45df08c9..cdb70ca715b 100644
--- a/doc/administration/raketasks/maintenance.md
+++ b/doc/administration/raketasks/maintenance.md
@@ -176,13 +176,15 @@ Running? ... yes
Checking Sidekiq ... Finished
-Checking GitLab ...
+Checking GitLab App...
Database config exists? ... yes
Database is SQLite ... no
All migrations up? ... yes
GitLab config exists? ... yes
-GitLab config outdated? ... no
+GitLab config up to date? ... no
+Cable config exists? ... yes
+Resque config exists? ... yes
Log directory writable? ... yes
Tmp directory writable? ... yes
Init script exists? ... yes
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index bbf780907fe..0f9cdf7860c 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -14389,7 +14389,7 @@ CI/CD variables for a GitLab instance.
##### `CiJobTrace.htmlSummary`
-HTML summary that contains the tail lines of the trace.
+HTML summary that contains the tail lines of the trace. Returns at most 16KB of raw bytes from the trace. The returned string might start with an unexpected invalid UTF-8 code point due to truncation.
WARNING:
**Introduced** in 15.11.
diff --git a/doc/api/rest/index.md b/doc/api/rest/index.md
index 15bfbef78f1..17da691b720 100644
--- a/doc/api/rest/index.md
+++ b/doc/api/rest/index.md
@@ -540,6 +540,7 @@ options:
| [Project jobs](../jobs.md#list-project-jobs) | `order_by=id`, `sort=desc` only | Authenticated users only. |
| [Project audit events](../audit_events.md#retrieve-all-project-audit-events) | `order_by=id`, `sort=desc` only | Authenticated users only. |
| [Projects](../projects.md) | `order_by=id` only | Authenticated and unauthenticated users. |
+| [Users](../users.md) | `order_by=id`, `order_by=name`, `order_by=username` | Authenticated and unauthenticated users. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/419556) in GitLab 15.4 [with a flag](../../user/feature_flags.md)) named `api_keyset_pagination_multi_order`. Disabled by default. |
### Pagination response headers
diff --git a/doc/api/users.md b/doc/api/users.md
index e5e8f7be759..0652742c557 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -58,6 +58,8 @@ GET /users
]
```
+This endpoint supports [keyset pagination](rest/index.md#keyset-based-pagination). Keyset pagination [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/419556) in GitLab 16.5 [with a flag](../user/feature_flags.md) named `api_keyset_pagination_multi_order`. Disabled by default.
+
You can also use `?search=` to search for users by name, username, or public email. For example, `/users?search=John`. When you search for a:
- Public email, you must use the full email address to get an exact match. A search might return a partial match. For example, if you search for the email `on@example.com`, the search can return both `on@example.com` and `jon@example.com`.
diff --git a/doc/ci/review_apps/img/enable_review_app_v16.png b/doc/ci/review_apps/img/enable_review_app_v16.png
new file mode 100644
index 00000000000..00e305d6a6b
--- /dev/null
+++ b/doc/ci/review_apps/img/enable_review_app_v16.png
Binary files differ
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index f6607d0080f..f831c53c024 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -78,12 +78,12 @@ To use the review apps template:
1. On the left sidebar, select **Search or go to** and
find the project you want to create a review app job for.
-1. Select **Build > Environments**.
+1. Select **Operate > Environments**.
1. Select **Enable review apps**.
1. Copy the provided code snippet and paste it into your
`.gitlab-ci.yml` file:
- ![enable review apps modal](img/enable_review_app_v12_8.png)
+ ![enable review apps modal](img/enable_review_app_v16.png)
You can edit this template as needed.
diff --git a/lib/api/internal/pages.rb b/lib/api/internal/pages.rb
index 5664a3df589..971b76279a1 100644
--- a/lib/api/internal/pages.rb
+++ b/lib/api/internal/pages.rb
@@ -36,16 +36,7 @@ module API
virtual_domain = ::Gitlab::Pages::VirtualHostFinder.new(params[:host]).execute
no_content! unless virtual_domain
- if virtual_domain.cache_key.present?
- # Cache context is not added to make it easier to expire the cache with
- # Gitlab::Pages::CacheControl
- present_cached virtual_domain,
- cache_context: nil,
- with: Entities::Internal::Pages::VirtualDomain,
- expires_in: ::Gitlab::Pages::CacheControl::EXPIRE
- else
- present virtual_domain, with: Entities::Internal::Pages::VirtualDomain
- end
+ present virtual_domain, with: Entities::Internal::Pages::VirtualDomain
end
end
end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index f23865c6d90..a01ace3a9c3 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -141,7 +141,11 @@ module API
users = users.preload(:user_detail)
- present paginate(users), options
+ if Feature.enabled?(:api_keyset_pagination_multi_order)
+ present paginate_with_strategies(users), options
+ else
+ present paginate(users), options
+ end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/ci/trace.rb b/lib/gitlab/ci/trace.rb
index 494ba75a57d..f4ba9100812 100644
--- a/lib/gitlab/ci/trace.rb
+++ b/lib/gitlab/ci/trace.rb
@@ -30,9 +30,9 @@ module Gitlab
@job = job
end
- def html(last_lines: nil)
+ def html(last_lines: nil, max_size: nil)
read do |stream|
- stream.html(last_lines: last_lines)
+ stream.html(last_lines: last_lines, max_size: max_size)
end
end
diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb
index dd435ba05b7..ef494a79d9a 100644
--- a/lib/gitlab/ci/trace/stream.rb
+++ b/lib/gitlab/ci/trace/stream.rb
@@ -53,18 +53,20 @@ module Gitlab
append(data, 0)
end
- def raw(last_lines: nil)
+ def raw(last_lines: nil, max_size: nil)
return unless valid?
- if last_lines.to_i > 0
+ if max_size.to_i > 0
+ read_last_lines_with_max_size(last_lines, max_size)
+ elsif last_lines.to_i > 0
read_last_lines(last_lines)
else
stream.read
end.force_encoding(Encoding.default_external)
end
- def html(last_lines: nil)
- text = raw(last_lines: last_lines)
+ def html(last_lines: nil, max_size: nil)
+ text = raw(last_lines: last_lines, max_size: max_size)
buffer = StringIO.new(text)
::Gitlab::Ci::Ansi2html.convert(buffer).html
end
@@ -117,6 +119,37 @@ module Gitlab
to_enum(:reverse_line).first(limit).reverse.join
end
+ def read_last_lines_with_max_size(limit, max_size)
+ linesleft = limit
+ result = ''
+
+ reverse_line_with_max_size(max_size) do |line|
+ result = line + result
+ unless linesleft.nil?
+ linesleft -= 1
+ break if linesleft <= 0
+ end
+ end
+
+ result
+ end
+
+ def reverse_line_with_max_size(max_size)
+ stream.seek(0, IO::SEEK_END)
+ debris = ''
+ sizeleft = max_size
+
+ until sizeleft <= 0 || (buf = read_backward([BUFFER_SIZE, sizeleft].min)).empty?
+ sizeleft -= buf.bytesize
+ debris, *lines = (buf + debris).each_line.to_a
+ lines.reverse_each do |line|
+ yield(line.force_encoding(Encoding.default_external))
+ end
+ end
+
+ yield(debris.force_encoding(Encoding.default_external)) unless debris.empty?
+ end
+
def reverse_line
stream.seek(0, IO::SEEK_END)
debris = ''
diff --git a/lib/gitlab/database/tables_truncate.rb b/lib/gitlab/database/tables_truncate.rb
index 7ae1981fa2b..f91146fff3d 100644
--- a/lib/gitlab/database/tables_truncate.rb
+++ b/lib/gitlab/database/tables_truncate.rb
@@ -5,7 +5,7 @@ module Gitlab
class TablesTruncate
GITLAB_SCHEMAS_TO_IGNORE = %i[gitlab_geo gitlab_embedding].freeze
- def initialize(database_name:, min_batch_size:, logger: nil, until_table: nil, dry_run: false)
+ def initialize(database_name:, min_batch_size: 5, logger: nil, until_table: nil, dry_run: false)
@database_name = database_name
@min_batch_size = min_batch_size
@logger = logger
@@ -19,19 +19,6 @@ module Gitlab
logger&.info "DRY RUN:" if dry_run
- schemas_for_connection = Gitlab::Database.gitlab_schemas_for_connection(connection)
- tables_to_truncate = Gitlab::Database::GitlabSchema.tables_to_schema.reject do |_, schema_name|
- GITLAB_SCHEMAS_TO_IGNORE.union(schemas_for_connection).include?(schema_name)
- end.keys
-
- Gitlab::Database::SharedModel.using_connection(connection) do
- Postgresql::DetachedPartition.find_each do |detached_partition|
- next if GITLAB_SCHEMAS_TO_IGNORE.union(schemas_for_connection).include?(detached_partition.table_schema)
-
- tables_to_truncate << detached_partition.fully_qualified_table_name
- end
- end
-
tables_sorted = Gitlab::Database::TablesSortedByForeignKeys.new(connection, tables_to_truncate).execute
# Checking if all the tables have the write-lock triggers
# to make sure we are deleting the right tables on the right database.
@@ -63,10 +50,41 @@ module Gitlab
truncate_tables_in_batches(tables_sorted)
end
+ def needs_truncation?
+ return false if single_database_setup?
+
+ sql = tables_to_truncate.map { |table_name| "(SELECT EXISTS( SELECT * FROM #{table_name} ))" }.join("\nUNION\n")
+
+ result = with_suppressed_query_analyzers do
+ connection.execute(sql).to_a
+ end
+
+ result.to_a.any? { |row| row['exists'] == true }
+ end
+
private
attr_accessor :database_name, :min_batch_size, :logger, :dry_run, :until_table
+ def tables_to_truncate
+ @tables_to_truncate ||= begin
+ schemas_for_connection = Gitlab::Database.gitlab_schemas_for_connection(connection)
+ tables = Gitlab::Database::GitlabSchema.tables_to_schema.reject do |_, schema_name|
+ GITLAB_SCHEMAS_TO_IGNORE.union(schemas_for_connection).include?(schema_name)
+ end.keys
+
+ Gitlab::Database::SharedModel.using_connection(connection) do
+ Postgresql::DetachedPartition.find_each do |detached_partition|
+ next if GITLAB_SCHEMAS_TO_IGNORE.union(schemas_for_connection).include?(detached_partition.table_schema)
+
+ tables << detached_partition.fully_qualified_table_name
+ end
+ end
+
+ tables
+ end
+ end
+
def connection
@connection ||= Gitlab::Database.database_base_models[database_name].connection
end
@@ -133,6 +151,12 @@ module Gitlab
ci_base_model = Gitlab::Database.database_base_models[:ci]
!!Gitlab::Database.db_config_share_with(ci_base_model.connection_db_config)
end
+
+ def with_suppressed_query_analyzers(&block)
+ Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection.with_suppressed do
+ Gitlab::Database::QueryAnalyzers::Ci::PartitioningRoutingAnalyzer.with_suppressed(&block)
+ end
+ end
end
end
end
diff --git a/lib/gitlab/event_store.rb b/lib/gitlab/event_store.rb
index 474aac8073e..1e397b52ddf 100644
--- a/lib/gitlab/event_store.rb
+++ b/lib/gitlab/event_store.rb
@@ -36,26 +36,6 @@ module Gitlab
store.subscribe ::MergeRequests::UpdateHeadPipelineWorker, to: ::Ci::PipelineCreatedEvent
store.subscribe ::Namespaces::UpdateRootStatisticsWorker, to: ::Projects::ProjectDeletedEvent
- store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Pages::PageDeployedEvent
- store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Pages::PageDeletedEvent
- store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Projects::ProjectDeletedEvent
- store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Projects::ProjectCreatedEvent
- store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Projects::ProjectPathChangedEvent
- store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Projects::ProjectArchivedEvent
- store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Projects::ProjectTransferedEvent
- store.subscribe ::Pages::InvalidateDomainCacheWorker,
- to: ::Projects::ProjectAttributesChangedEvent,
- if: -> (event) { event.pages_related? }
- store.subscribe ::Pages::InvalidateDomainCacheWorker,
- to: ::Projects::ProjectFeaturesChangedEvent,
- if: -> (event) { event.pages_related? }
- store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Groups::GroupTransferedEvent
- store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Groups::GroupPathChangedEvent
- store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Groups::GroupDeletedEvent
- store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::PagesDomains::PagesDomainDeletedEvent
- store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::PagesDomains::PagesDomainUpdatedEvent
- store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::PagesDomains::PagesDomainCreatedEvent
-
store.subscribe ::MergeRequests::CreateApprovalEventWorker, to: ::MergeRequests::ApprovedEvent
store.subscribe ::MergeRequests::CreateApprovalNoteWorker, to: ::MergeRequests::ApprovedEvent
store.subscribe ::MergeRequests::ResolveTodosAfterApprovalWorker, to: ::MergeRequests::ApprovedEvent
diff --git a/lib/gitlab/pages.rb b/lib/gitlab/pages.rb
index 700a39c6b41..defe054d631 100644
--- a/lib/gitlab/pages.rb
+++ b/lib/gitlab/pages.rb
@@ -5,6 +5,7 @@ module Gitlab
VERSION = File.read(Rails.root.join("GITLAB_PAGES_VERSION")).strip.freeze
INTERNAL_API_REQUEST_HEADER = 'Gitlab-Pages-Api-Request'
MAX_SIZE = 1.terabyte
+ DEPLOYMENT_EXPIRATION = 24.hours
include JwtAuthenticatable
diff --git a/lib/gitlab/pages/virtual_host_finder.rb b/lib/gitlab/pages/virtual_host_finder.rb
index 88ee0e44c00..e9ac86f0d47 100644
--- a/lib/gitlab/pages/virtual_host_finder.rb
+++ b/lib/gitlab/pages/virtual_host_finder.rb
@@ -38,15 +38,9 @@ module Gitlab
return if namespace.blank?
- cache = if Feature.enabled?(:cache_pages_domain_api, namespace)
- ::Gitlab::Pages::CacheControl.for_namespace(namespace.id)
- end
-
::Pages::VirtualDomain.new(
trim_prefix: namespace.full_path,
- projects: namespace.all_projects_with_pages,
- cache: cache
- )
+ projects: namespace.all_projects_with_pages)
end
def by_custom_domain(host)
@@ -54,15 +48,7 @@ module Gitlab
return unless domain&.pages_deployed?
- cache = if Feature.enabled?(:cache_pages_domain_api, domain.project.root_namespace)
- ::Gitlab::Pages::CacheControl.for_domain(domain.id)
- end
-
- ::Pages::VirtualDomain.new(
- projects: [domain.project],
- domain: domain,
- cache: cache
- )
+ ::Pages::VirtualDomain.new(projects: [domain.project], domain: domain)
end
end
end
diff --git a/lib/gitlab/pagination/cursor_based_keyset.rb b/lib/gitlab/pagination/cursor_based_keyset.rb
index ee8259cc671..592f635c14e 100644
--- a/lib/gitlab/pagination/cursor_based_keyset.rb
+++ b/lib/gitlab/pagination/cursor_based_keyset.rb
@@ -10,6 +10,20 @@ module Gitlab
::Packages::BuildInfo => { id: :desc }
}.freeze
+ SUPPORTED_MULTI_ORDERING = {
+ Group => { name: [:asc] },
+ AuditEvent => { id: [:desc] },
+ User => {
+ id: [:asc, :desc],
+ name: [:asc, :desc],
+ username: [:asc, :desc],
+ created_at: [:asc, :desc],
+ updated_at: [:asc, :desc]
+ },
+ ::Ci::Build => { id: [:desc] },
+ ::Packages::BuildInfo => { id: [:desc] }
+ }.freeze
+
# Relation types that are enforced in this list
# enforce the use of keyset pagination, thus erroring out requests
# made with offset pagination above a certain limit.
@@ -19,7 +33,11 @@ module Gitlab
ENFORCED_TYPES = [Group].freeze
def self.available_for_type?(relation)
- SUPPORTED_ORDERING.key?(relation.klass)
+ if Feature.enabled?(:api_keyset_pagination_multi_order)
+ SUPPORTED_MULTI_ORDERING.key?(relation.klass)
+ else
+ SUPPORTED_ORDERING.key?(relation.klass)
+ end
end
def self.available?(cursor_based_request_context, relation)
@@ -32,9 +50,16 @@ module Gitlab
end
def self.order_satisfied?(relation, cursor_based_request_context)
- order_by_from_request = cursor_based_request_context.order_by
+ if Feature.enabled?(:api_keyset_pagination_multi_order)
+ order_by_from_request = cursor_based_request_context.order
+ sort_from_request = cursor_based_request_context.sort
+
+ SUPPORTED_MULTI_ORDERING[relation.klass][order_by_from_request]&.include?(sort_from_request)
+ else
+ order_by_from_request = cursor_based_request_context.order_by
- SUPPORTED_ORDERING[relation.klass] == order_by_from_request
+ SUPPORTED_ORDERING[relation.klass] == order_by_from_request
+ end
end
private_class_method :order_satisfied?
end
diff --git a/lib/gitlab/pagination/keyset/cursor_based_request_context.rb b/lib/gitlab/pagination/keyset/cursor_based_request_context.rb
index 41b90846345..f90574c86ab 100644
--- a/lib/gitlab/pagination/keyset/cursor_based_request_context.rb
+++ b/lib/gitlab/pagination/keyset/cursor_based_request_context.rb
@@ -32,6 +32,14 @@ module Gitlab
def order_by
{ (params[:order_by]&.to_sym || DEFAULT_SORT_COLUMN) => (params[:sort]&.to_sym || DEFAULT_SORT_DIRECTION) }
end
+
+ def order
+ params[:order_by]&.to_sym || DEFAULT_SORT_COLUMN
+ end
+
+ def sort
+ params[:sort]&.to_sym || DEFAULT_SORT_DIRECTION
+ end
end
end
end
diff --git a/lib/system_check/app/table_truncate_check.rb b/lib/system_check/app/table_truncate_check.rb
new file mode 100644
index 00000000000..57b5950c21d
--- /dev/null
+++ b/lib/system_check/app/table_truncate_check.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module SystemCheck
+ module App
+ class TableTruncateCheck < SystemCheck::BaseCheck
+ set_name 'Tables are truncated?'
+
+ def skip?
+ Gitlab::Database.database_mode != Gitlab::Database::MODE_MULTIPLE_DATABASES
+ end
+
+ def check?
+ @rake_tasks = []
+ Gitlab::Database.database_base_models_with_gitlab_shared.keys.each_with_object({}) do |database_name, _h|
+ if Gitlab::Database::TablesTruncate.new(database_name: database_name).needs_truncation?
+ @rake_tasks << "gitlab:db:truncate_legacy_tables:#{database_name}"
+ end
+ end
+
+ @rake_tasks.empty?
+ end
+
+ def show_error
+ try_fixing_it(
+ sudo_gitlab("bundle exec rake #{@rake_tasks.join(' ')}")
+ )
+ for_more_information(
+ "doc/development/database/multiple_databases.md in section 'Truncating tables'"
+ )
+ fix_and_rerun
+ end
+ end
+ end
+end
diff --git a/lib/system_check/rake_task/app_task.rb b/lib/system_check/rake_task/app_task.rb
index 20332d4b24b..8e711138856 100644
--- a/lib/system_check/rake_task/app_task.rb
+++ b/lib/system_check/rake_task/app_task.rb
@@ -13,6 +13,7 @@ module SystemCheck
def self.checks
[
SystemCheck::App::DatabaseConfigExistsCheck,
+ SystemCheck::App::TableTruncateCheck,
SystemCheck::App::MigrationsAreUpCheck,
SystemCheck::App::OrphanedGroupMembersCheck,
SystemCheck::App::GitlabConfigExistsCheck,
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 9957b040482..9d495689696 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -12367,6 +12367,9 @@ msgstr ""
msgid "ComplianceStandardsAdherence|The following features help satisfy this requirement."
msgstr ""
+msgid "ComplianceStandardsAdherence|Unable to load the standards adherence report. Refresh the page and try again."
+msgstr ""
+
msgid "ComplianceStandardsAdherence|Update approval settings in the project's merge request settings to satisfy this requirement."
msgstr ""
diff --git a/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb
deleted file mode 100644
index 7e73d09a148..00000000000
--- a/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Verify', :runner, product_group: :pipeline_execution do
- describe 'Code coverage statistics' do
- let(:executor) { "qa-runner-#{Time.now.to_i}" }
- let(:runner) { create(:project_runner, name: executor, tags: ['e2e-test']) }
-
- let(:merge_request) do
- Resource::MergeRequest.fabricate_via_api! do |mr|
- mr.project = runner.project
- mr.file_name = '.gitlab-ci.yml'
- mr.file_content = <<~EOF
- test:
- tags: [e2e-test]
- coverage: '/\\d+\\.\\d+% covered/'
- script:
- - echo '66.67% covered'
- EOF
- end
- end
-
- before do
- Flow::Login.sign_in
- end
-
- after do
- runner.remove_via_api!
- end
-
- it 'creates an MR with code coverage statistics', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348068' do
- merge_request.visit!
-
- Page::MergeRequest::Show.perform do |mr_widget|
- mr_widget.has_pipeline_status?('passed')
- expect(mr_widget).to have_content('Test coverage 66.67%')
- end
- end
- end
- end
-end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 057146b31dd..d4f04105605 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -120,11 +120,11 @@ RSpec.describe Projects::IssuesController, :request_store, feature_category: :te
allow(Kaminari.config).to receive(:default_per_page).and_return(1)
end
- it 'redirects to last page when out of bounds on non-html requests' do
+ it 'does not redirect when out of bounds on non-html requests' do
get :index, params: params.merge(page: last_page + 1), format: 'atom'
- expect(response).to have_gitlab_http_status(:redirect)
- expect(response).to redirect_to(action: 'index', format: 'atom', page: last_page, state: 'opened')
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(assigns(:issues).size).to eq(0)
end
end
diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
index edaa675c35a..e052d06c158 100644
--- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
@@ -264,8 +264,6 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
before do
forked_project.add_maintainer(user2)
- stub_feature_flags(auto_merge_labels_mr_widget: false)
-
visit project_merge_request_path(project, merge_request)
page.within('.merge-request-tabs') do
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index e64b6a5b672..1db09790e1c 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -958,4 +958,21 @@ RSpec.describe 'Merge request > User sees merge widget', :js, feature_category:
end
end
end
+
+ context 'views MR when pipeline has code coverage enabled' do
+ let!(:pipeline) { create(:ci_pipeline, status: 'success', project: project, ref: merge_request.source_branch) }
+ let!(:build) { create(:ci_build, :success, :coverage, pipeline: pipeline) }
+
+ before do
+ merge_request.update!(head_pipeline: pipeline)
+
+ visit project_merge_request_path(project, merge_request)
+ end
+
+ it 'shows the coverage' do
+ within '.ci-widget' do
+ expect(find_by_testid('pipeline-coverage')).to have_content('Test coverage 99.90% ')
+ end
+ end
+ end
end
diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_sets_to_auto_merge_spec.rb
index ebec8a6d2ea..4dc0c03aedc 100644
--- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
+++ b/spec/features/merge_request/user_sets_to_auto_merge_spec.rb
@@ -2,7 +2,9 @@
require 'spec_helper'
-RSpec.describe 'Merge request > User merges when pipeline succeeds', :js, feature_category: :code_review_workflow do
+RSpec.describe 'Merge request > User sets to auto-merge', :js, feature_category: :code_review_workflow do
+ include ContentEditorHelpers
+
let(:project) { create(:project, :public, :repository) }
let(:user) { project.creator }
let(:merge_request) do
@@ -32,22 +34,23 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js, featur
context 'when there is active pipeline for merge request' do
before do
create(:ci_build, pipeline: pipeline)
- stub_feature_flags(auto_merge_labels_mr_widget: true)
sign_in(user)
visit project_merge_request_path(project, merge_request)
end
- describe 'enabling Merge when pipeline succeeds' do
+ describe 'setting to auto-merge when pipeline succeeds' do
shared_examples 'Set to auto-merge activator' do
- it 'activates the Merge when pipeline succeeds feature', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/410055' do
+ it 'activates auto-merge feature', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/410055' do
+ close_rich_text_promo_popover_if_present
+ expect(page).to have_content 'Set to auto-merge'
click_button "Set to auto-merge"
+ wait_for_requests
expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds"
expect(page).to have_content "Source branch will not be deleted"
expect(page).to have_selector ".js-cancel-auto-merge"
- visit project_merge_request_path(project, merge_request) # Needed to refresh the page
- expect(page).to have_content /enabled an automatic merge when the pipeline for \h{8} succeeds/i
+ expect(page).to have_content(/enabled an automatic merge when the pipeline for \h{8} succeeds/i)
end
end
@@ -57,6 +60,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js, featur
context 'when enabled after it was previously canceled' do
before do
+ close_rich_text_promo_popover_if_present
click_button "Set to auto-merge"
wait_for_requests
@@ -64,14 +68,12 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js, featur
click_button "Cancel auto-merge"
wait_for_requests
-
- expect(page).to have_content 'Set to auto-merge'
end
it_behaves_like 'Set to auto-merge activator'
end
- context 'when it was enabled and then canceled' do
+ context 'when it is enabled and then canceled' do
let(:merge_request) do
create(
:merge_request_with_diffs,
@@ -94,7 +96,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js, featur
end
end
- context 'when merge when pipeline succeeds is enabled' do
+ context 'when there is an active pipeline' do
let(:merge_request) do
create(
:merge_request_with_diffs,
@@ -112,12 +114,13 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js, featur
end
before do
- stub_feature_flags(auto_merge_labels_mr_widget: true)
sign_in user
visit project_merge_request_path(project, merge_request)
end
- it 'allows to cancel the automatic merge', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/410494' do
+ it 'allows to cancel the auto-merge', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/410055' do
+ close_rich_text_promo_popover_if_present
+
click_button "Cancel auto-merge"
expect(page).to have_button "Set to auto-merge"
@@ -128,22 +131,13 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js, featur
end
end
- context 'when pipeline is not active' do
- it 'does not allow to enable merge when pipeline succeeds' do
- stub_feature_flags(auto_merge_labels_mr_widget: false)
-
- visit project_merge_request_path(project, merge_request)
-
- expect(page).not_to have_link 'Merge when pipeline succeeds'
+ context 'when there is no active pipeline' do
+ before do
+ sign_in user
+ visit project_merge_request_path(project, merge_request.reload)
end
- end
-
- context 'when pipeline is not active and auto_merge_labels_mr_widget on' do
- it 'does not allow to enable merge when pipeline succeeds' do
- stub_feature_flags(auto_merge_labels_mr_widget: true)
-
- visit project_merge_request_path(project, merge_request)
+ it 'does not allow to set to auto-merge' do
expect(page).not_to have_link 'Set to auto-merge'
end
end
diff --git a/spec/frontend/ci/job_details/components/job_header_spec.js b/spec/frontend/ci/job_details/components/job_header_spec.js
index 923f463086a..6fc55732353 100644
--- a/spec/frontend/ci/job_details/components/job_header_spec.js
+++ b/spec/frontend/ci/job_details/components/job_header_spec.js
@@ -16,6 +16,7 @@ describe('Header CI Component', () => {
text: 'failed',
details_path: 'path',
},
+ name: 'Job build_job',
time: '2017-05-08T14:57:39.781Z',
user: {
id: 1234,
@@ -25,7 +26,7 @@ describe('Header CI Component', () => {
email: 'foo@bar.com',
avatar_url: 'link',
},
- hasSidebarButton: true,
+ shouldRenderTriggeredLabel: true,
};
const findCiBadgeLink = () => wrapper.findComponent(CiBadgeLink);
@@ -34,7 +35,7 @@ describe('Header CI Component', () => {
const findSidebarToggleBtn = () => wrapper.findComponent(GlButton);
const findStatusTooltip = () => wrapper.findComponent(GlTooltip);
const findActionButtons = () => wrapper.findByTestId('job-header-action-buttons');
- const findHeaderItemText = () => wrapper.findByTestId('job-header-item-text');
+ const findJobName = () => wrapper.findByTestId('job-name');
const createComponent = (props, slots) => {
wrapper = extendedWrapper(
@@ -50,7 +51,7 @@ describe('Header CI Component', () => {
describe('render', () => {
beforeEach(() => {
- createComponent({ itemName: 'Pipeline' });
+ createComponent();
});
it('should render status badge', () => {
@@ -72,7 +73,7 @@ describe('Header CI Component', () => {
describe('user avatar', () => {
beforeEach(() => {
- createComponent({ itemName: 'Pipeline' });
+ createComponent();
});
it('contains the username', () => {
@@ -93,7 +94,6 @@ describe('Header CI Component', () => {
beforeEach(() => {
createComponent({
- itemName: 'Pipeline',
user: { ...defaultProps.user, status: { message: STATUS_MESSAGE } },
});
});
@@ -108,7 +108,6 @@ describe('Header CI Component', () => {
beforeEach(() => {
createComponent({
- itemName: 'Pipeline',
user: { ...defaultProps.user, id: `gid://gitlab/User/${1}` },
});
});
@@ -125,29 +124,19 @@ describe('Header CI Component', () => {
});
});
- describe('with item id', () => {
+ describe('job name', () => {
beforeEach(() => {
- createComponent({ itemName: 'Pipeline', itemId: '123' });
+ createComponent();
});
- it('should render item name and id', () => {
- expect(findHeaderItemText().text()).toBe('Pipeline #123');
- });
- });
-
- describe('without item id', () => {
- beforeEach(() => {
- createComponent({ itemName: 'Job build_job' });
- });
-
- it('should render item name', () => {
- expect(findHeaderItemText().text()).toBe('Job build_job');
+ it('should render the job name', () => {
+ expect(findJobName().text()).toBe('Job build_job');
});
});
describe('slot', () => {
it('should render header action buttons', () => {
- createComponent({ itemName: 'Job build_job' }, { slots: { default: 'Test Actions' } });
+ createComponent({}, { slots: { default: 'Test Actions' } });
expect(findActionButtons().exists()).toBe(true);
expect(findActionButtons().text()).toBe('Test Actions');
@@ -156,7 +145,7 @@ describe('Header CI Component', () => {
describe('shouldRenderTriggeredLabel', () => {
it('should render created keyword when the shouldRenderTriggeredLabel is false', () => {
- createComponent({ shouldRenderTriggeredLabel: false, itemName: 'Job build_job' });
+ createComponent({ shouldRenderTriggeredLabel: false });
expect(wrapper.text()).toContain('created');
expect(wrapper.text()).not.toContain('started');
diff --git a/spec/graphql/types/ci/job_trace_type_spec.rb b/spec/graphql/types/ci/job_trace_type_spec.rb
index 5f4f3097ace..69123445b8b 100644
--- a/spec/graphql/types/ci/job_trace_type_spec.rb
+++ b/spec/graphql/types/ci/job_trace_type_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe GitlabSchema.types['CiJobTrace'], feature_category: :continuous_i
it 'shows the correct trace contents' do
expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
- expect(trace).to receive(:html).with(last_lines: 10).and_call_original
+ expect(trace).to receive(:html).with(last_lines: 10, max_size: 16384).and_call_original
end
is_expected.to eq('<span>BUILD TRACE</span>')
@@ -48,7 +48,7 @@ RSpec.describe GitlabSchema.types['CiJobTrace'], feature_category: :continuous_i
it 'shows the last 10 lines of trace contents' do
expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
- expect(trace).to receive(:html).with(last_lines: 10).and_call_original
+ expect(trace).to receive(:html).with(last_lines: 10, max_size: 16384).and_call_original
end
is_expected.to eq expected_html_trace_contents(10)
@@ -60,7 +60,7 @@ RSpec.describe GitlabSchema.types['CiJobTrace'], feature_category: :continuous_i
it 'shows the last line of trace contents' do
expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
- expect(trace).to receive(:html).with(last_lines: 1).and_call_original
+ expect(trace).to receive(:html).with(last_lines: 1, max_size: 16384).and_call_original
end
is_expected.to eq expected_html_trace_contents(1)
@@ -72,7 +72,7 @@ RSpec.describe GitlabSchema.types['CiJobTrace'], feature_category: :continuous_i
it 'shows the correct trace contents' do
expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
- expect(trace).to receive(:html).with(last_lines: 10).and_call_original
+ expect(trace).to receive(:html).with(last_lines: 10, max_size: 16384).and_call_original
end
is_expected.to eq expected_html_trace_contents(10)
@@ -84,12 +84,116 @@ RSpec.describe GitlabSchema.types['CiJobTrace'], feature_category: :continuous_i
it 'shows the last 100 lines of trace contents' do
expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
- expect(trace).to receive(:html).with(last_lines: 100).and_call_original
+ expect(trace).to receive(:html).with(last_lines: 100, max_size: 16384).and_call_original
end
is_expected.to eq expected_html_trace_contents(100)
end
end
end
+
+ context 'when trace contains long lines' do
+ before do
+ # Creates lines of "aaaaaaaa...aaaaaaaa"
+ job.trace.set((1..20).map { (1..1024).map { "a" }.join("") }.join("\n"))
+ end
+
+ context 'when last_lines is lower than 16KB' do
+ let(:args) { {} }
+
+ it 'shows the whole lines' do
+ expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
+ expect(trace).to receive(:html).with(last_lines: 10, max_size: 16384).and_call_original
+ end
+
+ is_expected.to eq "<span>#{(1..10).map { (1..1024).map { 'a' }.join('') }.join('<br/>')}</span>"
+ end
+ end
+
+ context 'when last_lines is higher than 16KB' do
+ let(:args) { { last_lines: 20 } }
+
+ it 'shows only the latest byte' do
+ expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
+ expect(trace).to receive(:html).with(last_lines: 20, max_size: 16384).and_call_original
+ end
+
+ is_expected.to eq "<span>#{(1..1009).map { 'a' }.join('')}<br/>" \
+ "#{(1..15).map { (1..1024).map { 'a' }.join('') }.join('<br/>')}</span>"
+ end
+ end
+
+ context 'when FF graphql_job_trace_html_summary_max_size is disabled' do
+ before do
+ stub_feature_flags(graphql_job_trace_html_summary_max_size: false)
+ end
+
+ let(:args) { { last_lines: 20 } }
+
+ it 'does not limit the read size from the raw trace' do
+ expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
+ expect(trace).to receive(:html).with(last_lines: 20, max_size: nil).and_call_original
+ end
+
+ is_expected.to eq "<span>#{(1..20).map { (1..1024).map { 'a' }.join('') }.join('<br/>')}</span>"
+ end
+ end
+
+ context 'when trace is cut in middle of a line' do
+ let(:args) { {} }
+
+ before do
+ stub_const('Types::Ci::JobTraceType::MAX_SIZE_B', 1536)
+ end
+
+ it 'shows only the latest byte' do
+ expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
+ expect(trace).to receive(:html).with(last_lines: 10, max_size: 1536).and_call_original
+ end
+
+ is_expected.to eq "<span>#{(1..511).map { 'a' }.join('')}<br/>#{(1..1024).map { 'a' }.join('')}</span>"
+ end
+ end
+
+ context 'when trace is cut at end of a line' do
+ let(:args) { {} }
+
+ before do
+ stub_const('Types::Ci::JobTraceType::MAX_SIZE_B', 2050)
+ end
+
+ it 'shows only the latest byte' do
+ expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
+ expect(trace).to receive(:html).with(last_lines: 10, max_size: 2050).and_call_original
+ end
+
+ is_expected.to eq "<span><br/>#{(1..2).map { (1..1024).map { 'a' }.join('') }.join('<br/>')}</span>"
+ end
+ end
+ end
+
+ context 'when trace contains multi-bytes UTF-8' do
+ before do
+ # Creates lines of 4 pound symbol, pound symbol is 2 byte wise in UTF-8
+ # Append an "a" (1 byte character) at the end to cut in the middle of UTF-8
+ job.trace.set((1..20).map { (1..4).map { "£" }.join("") }.join("\n"))
+ end
+
+ context 'when cut in the middle of a codepoint' do
+ before do
+ stub_const('Types::Ci::JobTraceType::MAX_SIZE_B', 5)
+ end
+
+ let(:args) { {} }
+
+ it 'shows a single "invalid utf-8" symbol' do
+ expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
+ expect(trace).to receive(:html).with(last_lines: 10, max_size: 5).and_call_original
+ end
+
+ is_expected.to eq "<span>�££</span>"
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/trace/stream_spec.rb b/spec/lib/gitlab/ci/trace/stream_spec.rb
index d65b6fb41f6..9439d29aa11 100644
--- a/spec/lib/gitlab/ci/trace/stream_spec.rb
+++ b/spec/lib/gitlab/ci/trace/stream_spec.rb
@@ -243,6 +243,56 @@ RSpec.describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do
expect(result.encoding).to eq(Encoding.default_external)
end
end
+
+ context 'limit max size' do
+ before do
+ # specifying BUFFER_SIZE forces to seek backwards
+ allow(described_class).to receive(:BUFFER_SIZE)
+ .and_return(2)
+ end
+
+ it 'returns every lines with respect of the size' do
+ all_lines = lines.join
+ max_size = all_lines.bytesize.div(2)
+ result = stream.raw(max_size: max_size)
+
+ expect(result.bytes).to eq(all_lines.bytes[-max_size..])
+ expect(result.lines.count).to be > 1
+ expect(result.encoding).to eq(Encoding.default_external)
+ end
+
+ it 'returns everything if trying to get too many bytes' do
+ all_lines = lines.join
+ result = stream.raw(max_size: all_lines.bytesize * 2)
+
+ expect(result).to eq(all_lines)
+ expect(result.encoding).to eq(Encoding.default_external)
+ end
+ end
+
+ context 'limit max lines and max size' do
+ before do
+ # specifying BUFFER_SIZE forces to seek backwards
+ allow(described_class).to receive(:BUFFER_SIZE)
+ .and_return(2)
+ end
+
+ it 'returns max lines if max size is greater' do
+ result = stream.raw(last_lines: 2, max_size: lines.join.bytesize * 2)
+
+ expect(result).to eq(lines.last(2).join)
+ expect(result.encoding).to eq(Encoding.default_external)
+ end
+
+ it 'returns max size if max lines is greater' do
+ all_lines = lines.join
+ max_size = all_lines.bytesize.div(2)
+ result = stream.raw(last_lines: lines.size * 2, max_size: max_size)
+
+ expect(result.bytes).to eq(all_lines.bytes[-max_size..])
+ expect(result.encoding).to eq(Encoding.default_external)
+ end
+ end
end
let(:path) { __FILE__ }
diff --git a/spec/lib/gitlab/database/tables_truncate_spec.rb b/spec/lib/gitlab/database/tables_truncate_spec.rb
index 04bec50088d..e41c7d34378 100644
--- a/spec/lib/gitlab/database/tables_truncate_spec.rb
+++ b/spec/lib/gitlab/database/tables_truncate_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
let(:min_batch_size) { 1 }
let(:main_connection) { ApplicationRecord.connection }
let(:ci_connection) { Ci::ApplicationRecord.connection }
+ let(:logger) { instance_double(Logger) }
# Main Database
let(:main_db_main_item_model) { table("_test_gitlab_main_items", database: "main") }
@@ -32,8 +33,123 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
table("gitlab_partitions_dynamic._test_gitlab_hook_logs_202201", database: "ci")
end
+ before do
+ skip_if_shared_database(:ci)
+
+ # Creating some test tables on the main database
+ main_tables_sql = <<~SQL
+ CREATE TABLE _test_gitlab_main_items (id serial NOT NULL PRIMARY KEY);
+
+ CREATE TABLE _test_gitlab_main_references (
+ id serial NOT NULL PRIMARY KEY,
+ item_id BIGINT NOT NULL,
+ CONSTRAINT fk_constrained_1 FOREIGN KEY(item_id) REFERENCES _test_gitlab_main_items(id)
+ );
+
+ CREATE TABLE _test_gitlab_hook_logs (
+ id bigserial not null,
+ created_at timestamptz not null,
+ item_id BIGINT NOT NULL,
+ PRIMARY KEY (id, created_at),
+ CONSTRAINT fk_constrained_1 FOREIGN KEY(item_id) REFERENCES _test_gitlab_main_items(id)
+ ) PARTITION BY RANGE(created_at);
+
+ CREATE TABLE gitlab_partitions_dynamic._test_gitlab_hook_logs_202201
+ PARTITION OF _test_gitlab_hook_logs
+ FOR VALUES FROM ('20220101') TO ('20220131');
+
+ CREATE TABLE gitlab_partitions_dynamic._test_gitlab_hook_logs_202202
+ PARTITION OF _test_gitlab_hook_logs
+ FOR VALUES FROM ('20220201') TO ('20220228');
+
+ ALTER TABLE _test_gitlab_hook_logs DETACH PARTITION gitlab_partitions_dynamic._test_gitlab_hook_logs_202201;
+ SQL
+
+ execute_on_each_database(main_tables_sql)
+
+ ci_tables_sql = <<~SQL
+ CREATE TABLE _test_gitlab_ci_items (id serial NOT NULL PRIMARY KEY);
+
+ CREATE TABLE _test_gitlab_ci_references (
+ id serial NOT NULL PRIMARY KEY,
+ item_id BIGINT NOT NULL,
+ CONSTRAINT fk_constrained_1 FOREIGN KEY(item_id) REFERENCES _test_gitlab_ci_items(id)
+ );
+ SQL
+
+ execute_on_each_database(ci_tables_sql)
+
+ internal_tables_sql = <<~SQL
+ CREATE TABLE _test_gitlab_shared_items (id serial NOT NULL PRIMARY KEY);
+ SQL
+
+ execute_on_each_database(internal_tables_sql)
+
+ # Filling the tables
+ 5.times do |i|
+ # Main Database
+ main_db_main_item_model.create!(id: i)
+ main_db_main_reference_model.create!(item_id: i)
+ main_db_ci_item_model.create!(id: i)
+ main_db_ci_reference_model.create!(item_id: i)
+ main_db_shared_item_model.create!(id: i)
+ main_db_partitioned_item.create!(item_id: i, created_at: '2022-02-02 02:00')
+ main_db_partitioned_item_detached.create!(item_id: i, created_at: '2022-01-01 01:00')
+ # CI Database
+ ci_db_main_item_model.create!(id: i)
+ ci_db_main_reference_model.create!(item_id: i)
+ ci_db_ci_item_model.create!(id: i)
+ ci_db_ci_reference_model.create!(item_id: i)
+ ci_db_shared_item_model.create!(id: i)
+ ci_db_partitioned_item.create!(item_id: i, created_at: '2022-02-02 02:00')
+ ci_db_partitioned_item_detached.create!(item_id: i, created_at: '2022-01-01 01:00')
+ end
+
+ Gitlab::Database::SharedModel.using_connection(main_connection) do
+ Postgresql::DetachedPartition.create!(
+ table_name: '_test_gitlab_hook_logs_202201',
+ drop_after: Time.current
+ )
+ end
+
+ Gitlab::Database::SharedModel.using_connection(ci_connection) do
+ Postgresql::DetachedPartition.create!(
+ table_name: '_test_gitlab_hook_logs_202201',
+ drop_after: Time.current
+ )
+ end
+
+ allow(Gitlab::Database::GitlabSchema).to receive(:tables_to_schema).and_return(
+ {
+ "_test_gitlab_main_items" => :gitlab_main,
+ "_test_gitlab_main_references" => :gitlab_main,
+ "_test_gitlab_hook_logs" => :gitlab_main,
+ "_test_gitlab_ci_items" => :gitlab_ci,
+ "_test_gitlab_ci_references" => :gitlab_ci,
+ "_test_gitlab_shared_items" => :gitlab_shared,
+ "_test_gitlab_geo_items" => :gitlab_geo
+ }
+ )
+
+ allow(Gitlab::Database::GitlabSchema).to receive(:views_and_tables_to_schema).and_return(
+ {
+ "_test_gitlab_main_items" => :gitlab_main,
+ "_test_gitlab_main_references" => :gitlab_main,
+ "_test_gitlab_hook_logs" => :gitlab_main,
+ "_test_gitlab_ci_items" => :gitlab_ci,
+ "_test_gitlab_ci_references" => :gitlab_ci,
+ "_test_gitlab_shared_items" => :gitlab_shared,
+ "_test_gitlab_geo_items" => :gitlab_geo,
+ "detached_partitions" => :gitlab_shared,
+ "postgres_foreign_keys" => :gitlab_shared,
+ "postgres_partitions" => :gitlab_shared
+ }
+ )
+
+ allow(logger).to receive(:info).with(any_args)
+ end
+
shared_examples 'truncating legacy tables on a database' do
- let(:logger) { instance_double(Logger) }
let(:dry_run) { false }
let(:until_table) { nil }
@@ -47,122 +163,6 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
).execute
end
- before do
- skip_if_shared_database(:ci)
-
- # Creating some test tables on the main database
- main_tables_sql = <<~SQL
- CREATE TABLE _test_gitlab_main_items (id serial NOT NULL PRIMARY KEY);
-
- CREATE TABLE _test_gitlab_main_references (
- id serial NOT NULL PRIMARY KEY,
- item_id BIGINT NOT NULL,
- CONSTRAINT fk_constrained_1 FOREIGN KEY(item_id) REFERENCES _test_gitlab_main_items(id)
- );
-
- CREATE TABLE _test_gitlab_hook_logs (
- id bigserial not null,
- created_at timestamptz not null,
- item_id BIGINT NOT NULL,
- PRIMARY KEY (id, created_at),
- CONSTRAINT fk_constrained_1 FOREIGN KEY(item_id) REFERENCES _test_gitlab_main_items(id)
- ) PARTITION BY RANGE(created_at);
-
- CREATE TABLE gitlab_partitions_dynamic._test_gitlab_hook_logs_202201
- PARTITION OF _test_gitlab_hook_logs
- FOR VALUES FROM ('20220101') TO ('20220131');
-
- CREATE TABLE gitlab_partitions_dynamic._test_gitlab_hook_logs_202202
- PARTITION OF _test_gitlab_hook_logs
- FOR VALUES FROM ('20220201') TO ('20220228');
-
- ALTER TABLE _test_gitlab_hook_logs DETACH PARTITION gitlab_partitions_dynamic._test_gitlab_hook_logs_202201;
- SQL
-
- execute_on_each_database(main_tables_sql)
-
- ci_tables_sql = <<~SQL
- CREATE TABLE _test_gitlab_ci_items (id serial NOT NULL PRIMARY KEY);
-
- CREATE TABLE _test_gitlab_ci_references (
- id serial NOT NULL PRIMARY KEY,
- item_id BIGINT NOT NULL,
- CONSTRAINT fk_constrained_1 FOREIGN KEY(item_id) REFERENCES _test_gitlab_ci_items(id)
- );
- SQL
-
- execute_on_each_database(ci_tables_sql)
-
- internal_tables_sql = <<~SQL
- CREATE TABLE _test_gitlab_shared_items (id serial NOT NULL PRIMARY KEY);
- SQL
-
- execute_on_each_database(internal_tables_sql)
-
- # Filling the tables
- 5.times do |i|
- # Main Database
- main_db_main_item_model.create!(id: i)
- main_db_main_reference_model.create!(item_id: i)
- main_db_ci_item_model.create!(id: i)
- main_db_ci_reference_model.create!(item_id: i)
- main_db_shared_item_model.create!(id: i)
- main_db_partitioned_item.create!(item_id: i, created_at: '2022-02-02 02:00')
- main_db_partitioned_item_detached.create!(item_id: i, created_at: '2022-01-01 01:00')
- # CI Database
- ci_db_main_item_model.create!(id: i)
- ci_db_main_reference_model.create!(item_id: i)
- ci_db_ci_item_model.create!(id: i)
- ci_db_ci_reference_model.create!(item_id: i)
- ci_db_shared_item_model.create!(id: i)
- ci_db_partitioned_item.create!(item_id: i, created_at: '2022-02-02 02:00')
- ci_db_partitioned_item_detached.create!(item_id: i, created_at: '2022-01-01 01:00')
- end
-
- Gitlab::Database::SharedModel.using_connection(main_connection) do
- Postgresql::DetachedPartition.create!(
- table_name: '_test_gitlab_hook_logs_202201',
- drop_after: Time.current
- )
- end
-
- Gitlab::Database::SharedModel.using_connection(ci_connection) do
- Postgresql::DetachedPartition.create!(
- table_name: '_test_gitlab_hook_logs_202201',
- drop_after: Time.current
- )
- end
-
- allow(Gitlab::Database::GitlabSchema).to receive(:tables_to_schema).and_return(
- {
- "_test_gitlab_main_items" => :gitlab_main,
- "_test_gitlab_main_references" => :gitlab_main,
- "_test_gitlab_hook_logs" => :gitlab_main,
- "_test_gitlab_ci_items" => :gitlab_ci,
- "_test_gitlab_ci_references" => :gitlab_ci,
- "_test_gitlab_shared_items" => :gitlab_shared,
- "_test_gitlab_geo_items" => :gitlab_geo
- }
- )
-
- allow(Gitlab::Database::GitlabSchema).to receive(:views_and_tables_to_schema).and_return(
- {
- "_test_gitlab_main_items" => :gitlab_main,
- "_test_gitlab_main_references" => :gitlab_main,
- "_test_gitlab_hook_logs" => :gitlab_main,
- "_test_gitlab_ci_items" => :gitlab_ci,
- "_test_gitlab_ci_references" => :gitlab_ci,
- "_test_gitlab_shared_items" => :gitlab_shared,
- "_test_gitlab_geo_items" => :gitlab_geo,
- "detached_partitions" => :gitlab_shared,
- "postgres_foreign_keys" => :gitlab_shared,
- "postgres_partitions" => :gitlab_shared
- }
- )
-
- allow(logger).to receive(:info).with(any_args)
- end
-
context 'when the truncated tables are not locked for writes' do
it 'raises an error that the tables are not locked for writes' do
error_message = /is not locked for writes. Run the rake task gitlab:db:lock_writes first/
@@ -348,6 +348,50 @@ RSpec.describe Gitlab::Database::TablesTruncate, :reestablished_active_record_ba
end
end
+ describe '#needs_truncation?' do
+ let(:database_name) { 'ci' }
+
+ subject { described_class.new(database_name: database_name).needs_truncation? }
+
+ context 'when running in a single database mode' do
+ before do
+ skip_if_multiple_databases_are_setup(:ci)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when running in a multiple database mode' do
+ before do
+ skip_if_shared_database(:ci)
+ end
+
+ context 'with main data in ci database' do
+ it { is_expected.to eq(true) }
+ end
+
+ context 'with no main data in ci datatabase' do
+ before do
+ # Remove 'main' data in ci database
+ ci_connection.truncate_tables([:_test_gitlab_main_items, :_test_gitlab_main_references])
+ end
+
+ it { is_expected.to eq(false) }
+
+ it 'supresses some QueryAnalyzers' do
+ expect(
+ Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection
+ ).to receive(:with_suppressed).and_call_original
+ expect(
+ Gitlab::Database::QueryAnalyzers::Ci::PartitioningRoutingAnalyzer
+ ).to receive(:with_suppressed).and_call_original
+
+ subject
+ end
+ end
+ end
+ end
+
def geo_configured?
!!ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: 'geo')
end
diff --git a/spec/lib/gitlab/pages/cache_control_spec.rb b/spec/lib/gitlab/pages/cache_control_spec.rb
deleted file mode 100644
index 72240f52580..00000000000
--- a/spec/lib/gitlab/pages/cache_control_spec.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Pages::CacheControl, feature_category: :pages do
- RSpec.shared_examples 'cache_control' do |type|
- it { expect(subject.cache_key).to match(/pages_domain_for_#{type}_1_*/) }
-
- describe '#clear_cache', :use_clean_rails_redis_caching do
- before do
- Rails.cache.write("pages_domain_for_#{type}_1", ['settings-hash'])
- Rails.cache.write("pages_domain_for_#{type}_1_settings-hash", 'payload')
- end
-
- it 'clears the cache' do
- cached_keys = [
- "pages_domain_for_#{type}_1_settings-hash",
- "pages_domain_for_#{type}_1"
- ]
-
- expect(::Gitlab::AppLogger)
- .to receive(:info)
- .with(
- message: 'clear pages cache',
- pages_keys: cached_keys,
- pages_type: type,
- pages_id: 1
- )
-
- expect(Rails.cache)
- .to receive(:delete_multi)
- .with(cached_keys)
-
- subject.clear_cache
- end
- end
- end
-
- describe '.for_namespace' do
- subject(:cache_control) { described_class.for_namespace(1) }
-
- it_behaves_like 'cache_control', :namespace
- end
-
- describe '.for_domain' do
- subject(:cache_control) { described_class.for_domain(1) }
-
- it_behaves_like 'cache_control', :domain
- end
-
- describe '#cache_key' do
- it 'does not change the pages config' do
- expect { described_class.new(type: :domain, id: 1).cache_key }
- .not_to change(Gitlab.config, :pages)
- end
-
- it 'is based on pages settings' do
- access_control = Gitlab.config.pages.access_control
- cache_key = described_class.new(type: :domain, id: 1).cache_key
-
- stub_config(pages: { access_control: !access_control })
-
- expect(described_class.new(type: :domain, id: 1).cache_key).not_to eq(cache_key)
- end
-
- it 'is based on the force_pages_access_control settings' do
- force_pages_access_control = ::Gitlab::CurrentSettings.force_pages_access_control
- cache_key = described_class.new(type: :domain, id: 1).cache_key
-
- ::Gitlab::CurrentSettings.force_pages_access_control = !force_pages_access_control
-
- expect(described_class.new(type: :domain, id: 1).cache_key).not_to eq(cache_key)
- end
-
- it 'caches the application settings hash' do
- expect(Rails.cache)
- .to receive(:write)
- .with('pages_domain_for_domain_1', kind_of(Set))
-
- described_class.new(type: :domain, id: 1).cache_key
- end
- end
-
- it 'fails with invalid type' do
- expect { described_class.new(type: :unknown, id: nil) }
- .to raise_error(ArgumentError, 'type must be :namespace or :domain')
- end
-end
diff --git a/spec/lib/gitlab/pages/virtual_host_finder_spec.rb b/spec/lib/gitlab/pages/virtual_host_finder_spec.rb
index 49eee772f8d..8c34968bbfc 100644
--- a/spec/lib/gitlab/pages/virtual_host_finder_spec.rb
+++ b/spec/lib/gitlab/pages/virtual_host_finder_spec.rb
@@ -40,23 +40,9 @@ RSpec.describe Gitlab::Pages::VirtualHostFinder, feature_category: :pages do
it 'returns the virual domain when there are pages deployed for the project' do
expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
- expect(virtual_domain.cache_key).to match(/pages_domain_for_domain_#{pages_domain.id}_/)
expect(virtual_domain.lookup_paths.length).to eq(1)
expect(virtual_domain.lookup_paths.first.project_id).to eq(project.id)
end
-
- context 'when :cache_pages_domain_api is disabled' do
- before do
- stub_feature_flags(cache_pages_domain_api: false)
- end
-
- it 'returns the virual domain when there are pages deployed for the project' do
- expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
- expect(virtual_domain.cache_key).to be_nil
- expect(virtual_domain.lookup_paths.length).to eq(1)
- expect(virtual_domain.lookup_paths.first.project_id).to eq(project.id)
- end
- end
end
end
@@ -76,23 +62,8 @@ RSpec.describe Gitlab::Pages::VirtualHostFinder, feature_category: :pages do
virtual_domain = described_class.new("#{project.namespace.path}.example.com").execute
expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
- expect(virtual_domain.cache_key).to match(/pages_domain_for_namespace_#{project.namespace.id}_/)
expect(virtual_domain.lookup_paths.length).to eq(0)
end
-
- context 'when :cache_pages_domain_api is disabled' do
- before do
- stub_feature_flags(cache_pages_domain_api: false)
- end
-
- it 'returns the virual domain with no lookup_paths' do
- virtual_domain = described_class.new("#{project.namespace.path}.example.com".downcase).execute
-
- expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
- expect(virtual_domain.cache_key).to be_nil
- expect(virtual_domain.lookup_paths.length).to eq(0)
- end
- end
end
context 'when there are pages deployed for the project' do
@@ -111,7 +82,6 @@ RSpec.describe Gitlab::Pages::VirtualHostFinder, feature_category: :pages do
virtual_domain = described_class.new("#{project.namespace.path}.example.com").execute
expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
- expect(virtual_domain.cache_key).to match(/pages_domain_for_namespace_#{project.namespace.id}_/)
expect(virtual_domain.lookup_paths.length).to eq(1)
expect(virtual_domain.lookup_paths.first.project_id).to eq(project.id)
end
@@ -120,25 +90,9 @@ RSpec.describe Gitlab::Pages::VirtualHostFinder, feature_category: :pages do
virtual_domain = described_class.new("#{project.namespace.path}.Example.com").execute
expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
- expect(virtual_domain.cache_key).to match(/pages_domain_for_namespace_#{project.namespace.id}_/)
expect(virtual_domain.lookup_paths.length).to eq(1)
expect(virtual_domain.lookup_paths.first.project_id).to eq(project.id)
end
-
- context 'when :cache_pages_domain_api is disabled' do
- before_all do
- stub_feature_flags(cache_pages_domain_api: false)
- end
-
- it 'returns the virual domain when there are pages deployed for the project' do
- virtual_domain = described_class.new("#{project.namespace.path}.example.com").execute
-
- expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
- expect(virtual_domain.cache_key).to be_nil
- expect(virtual_domain.lookup_paths.length).to eq(1)
- expect(virtual_domain.lookup_paths.first.project_id).to eq(project.id)
- end
- end
end
end
@@ -187,18 +141,6 @@ RSpec.describe Gitlab::Pages::VirtualHostFinder, feature_category: :pages do
expect(virtual_domain.lookup_paths.first.project_id).to eq(project.id)
end
end
-
- context 'when :cache_pages_domain_api is disabled' do
- before do
- stub_feature_flags(cache_pages_domain_api: false)
- end
-
- it 'returns the virual domain when there are pages deployed for the project' do
- expect(virtual_domain).to be_an_instance_of(Pages::VirtualDomain)
- expect(virtual_domain.lookup_paths.length).to eq(1)
- expect(virtual_domain.lookup_paths.first.project_id).to eq(project.id)
- end
- end
end
end
diff --git a/spec/lib/gitlab/pagination/cursor_based_keyset_spec.rb b/spec/lib/gitlab/pagination/cursor_based_keyset_spec.rb
index 7cee65c13f7..4128f745ce7 100644
--- a/spec/lib/gitlab/pagination/cursor_based_keyset_spec.rb
+++ b/spec/lib/gitlab/pagination/cursor_based_keyset_spec.rb
@@ -6,20 +6,52 @@ RSpec.describe Gitlab::Pagination::CursorBasedKeyset do
subject { described_class }
describe '.available_for_type?' do
- it 'returns true for Group' do
- expect(subject.available_for_type?(Group.all)).to be_truthy
- end
+ context 'with api_keyset_pagination_multi_order FF disabled' do
+ before do
+ stub_feature_flags(api_keyset_pagination_multi_order: false)
+ end
- it 'returns true for Ci::Build' do
- expect(subject.available_for_type?(Ci::Build.all)).to be_truthy
- end
+ it 'returns true for Group' do
+ expect(subject.available_for_type?(Group.all)).to be_truthy
+ end
- it 'returns true for Packages::BuildInfo' do
- expect(subject.available_for_type?(Packages::BuildInfo.all)).to be_truthy
+ it 'returns true for Ci::Build' do
+ expect(subject.available_for_type?(Ci::Build.all)).to be_truthy
+ end
+
+ it 'returns true for Packages::BuildInfo' do
+ expect(subject.available_for_type?(Packages::BuildInfo.all)).to be_truthy
+ end
+
+ it 'return false for User' do
+ expect(subject.available_for_type?(User.all)).to be_falsey
+ end
end
- it 'return false for other types of relations' do
- expect(subject.available_for_type?(User.all)).to be_falsey
+ context 'with api_keyset_pagination_multi_order FF enabled' do
+ before do
+ stub_feature_flags(api_keyset_pagination_multi_order: true)
+ end
+
+ it 'returns true for Group' do
+ expect(subject.available_for_type?(Group.all)).to be_truthy
+ end
+
+ it 'returns true for Ci::Build' do
+ expect(subject.available_for_type?(Ci::Build.all)).to be_truthy
+ end
+
+ it 'returns true for Packages::BuildInfo' do
+ expect(subject.available_for_type?(Packages::BuildInfo.all)).to be_truthy
+ end
+
+ it 'returns true for User' do
+ expect(subject.available_for_type?(User.all)).to be_truthy
+ end
+
+ it 'return false for other types of relations' do
+ expect(subject.available_for_type?(Issue.all)).to be_falsey
+ end
end
end
@@ -58,7 +90,7 @@ RSpec.describe Gitlab::Pagination::CursorBasedKeyset do
end
it 'return false for other types of relations' do
- expect(subject.available?(cursor_based_request_context, User.all)).to be_falsey
+ expect(subject.available?(cursor_based_request_context, Issue.all)).to be_falsey
expect(subject.available?(cursor_based_request_context, Ci::Build.all)).to be_falsey
expect(subject.available?(cursor_based_request_context, Packages::BuildInfo.all)).to be_falsey
end
@@ -68,16 +100,48 @@ RSpec.describe Gitlab::Pagination::CursorBasedKeyset do
let(:order_by) { :id }
let(:sort) { :desc }
- it 'returns true for Ci::Build' do
- expect(subject.available?(cursor_based_request_context, Ci::Build.all)).to be_truthy
- end
+ context 'with api_keyset_pagination_multi_order FF disabled' do
+ before do
+ stub_feature_flags(api_keyset_pagination_multi_order: false)
+ end
+
+ it 'returns true for Ci::Build' do
+ expect(subject.available?(cursor_based_request_context, Ci::Build.all)).to be_truthy
+ end
+
+ it 'returns true for AuditEvent' do
+ expect(subject.available?(cursor_based_request_context, AuditEvent.all)).to be_truthy
+ end
- it 'returns true for AuditEvent' do
- expect(subject.available?(cursor_based_request_context, AuditEvent.all)).to be_truthy
+ it 'returns true for Packages::BuildInfo' do
+ expect(subject.available?(cursor_based_request_context, Packages::BuildInfo.all)).to be_truthy
+ end
+
+ it 'returns false for User' do
+ expect(subject.available?(cursor_based_request_context, User.all)).to be_falsey
+ end
end
- it 'returns true for Packages::BuildInfo' do
- expect(subject.available?(cursor_based_request_context, Packages::BuildInfo.all)).to be_truthy
+ context 'with api_keyset_pagination_multi_order FF enabled' do
+ before do
+ stub_feature_flags(api_keyset_pagination_multi_order: true)
+ end
+
+ it 'returns true for Ci::Build' do
+ expect(subject.available?(cursor_based_request_context, Ci::Build.all)).to be_truthy
+ end
+
+ it 'returns true for AuditEvent' do
+ expect(subject.available?(cursor_based_request_context, AuditEvent.all)).to be_truthy
+ end
+
+ it 'returns true for Packages::BuildInfo' do
+ expect(subject.available?(cursor_based_request_context, Packages::BuildInfo.all)).to be_truthy
+ end
+
+ it 'returns true for User' do
+ expect(subject.available?(cursor_based_request_context, User.all)).to be_truthy
+ end
end
end
@@ -90,7 +154,7 @@ RSpec.describe Gitlab::Pagination::CursorBasedKeyset do
end
it 'return false for other types of relations' do
- expect(subject.available?(cursor_based_request_context, User.all)).to be_falsey
+ expect(subject.available?(cursor_based_request_context, Issue.all)).to be_falsey
end
end
end
diff --git a/spec/lib/system_check/app/table_truncate_check_spec.rb b/spec/lib/system_check/app/table_truncate_check_spec.rb
new file mode 100644
index 00000000000..673365f3e5e
--- /dev/null
+++ b/spec/lib/system_check/app/table_truncate_check_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe SystemCheck::App::TableTruncateCheck, feature_category: :cell do
+ context 'when running on single databases' do
+ before do
+ skip_if_database_exists(:ci)
+ end
+
+ describe '#skip?' do
+ subject { described_class.new.skip? }
+
+ it { is_expected.to eq(true) }
+ end
+ end
+
+ context 'when running on multiple databases' do
+ let(:needs_truncation) { true }
+
+ before do
+ skip_if_shared_database(:ci)
+
+ allow_next_instances_of(Gitlab::Database::TablesTruncate, 2) do |instance|
+ allow(instance).to receive(:needs_truncation?).and_return(needs_truncation)
+ end
+ end
+
+ describe '#skip?' do
+ subject { described_class.new.skip? }
+
+ it { is_expected.to eq(false) }
+ end
+
+ describe '#check?' do
+ subject { described_class.new.check? }
+
+ context 'when TableTruncate returns false' do
+ let(:needs_truncation) { false }
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when TableTruncate returns true' do
+ let(:needs_truncation) { true }
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ describe '#show_error' do
+ let(:needs_truncation) { true }
+ let(:checker) { described_class.new }
+
+ before do
+ checker.check?
+ end
+
+ subject(:show_error) { checker.show_error }
+
+ it 'outputs error information' do
+ expected = %r{
+ Try\sfixing\sit:\s+
+ sudo\s-u\s.+?\s-H\sbundle\sexec\srake\sgitlab:db:truncate_legacy_tables:main\s
+ gitlab:db:truncate_legacy_tables:ci\s+
+ For\smore\sinformation\ssee:\s+
+ doc/development/database/multiple_databases.md\sin\ssection\s'Truncating\stables'\s+
+ Please\sfix\sthe\serror\sabove\sand\srerun\sthe\schecks.\s+
+ }x
+
+ expect { show_error }.to output(expected).to_stdout
+ end
+ end
+ end
+end
diff --git a/spec/models/bulk_imports/entity_spec.rb b/spec/models/bulk_imports/entity_spec.rb
index da1eb12e9b8..3e98ba0973e 100644
--- a/spec/models/bulk_imports/entity_spec.rb
+++ b/spec/models/bulk_imports/entity_spec.rb
@@ -438,4 +438,12 @@ RSpec.describe BulkImports::Entity, type: :model, feature_category: :importers d
end
end
end
+
+ describe '#source_version' do
+ subject { build(:bulk_import_entity, :group_entity) }
+
+ it 'pulls the source version from the associated BulkImport' do
+ expect(subject.source_version).to eq(subject.bulk_import.source_version_info)
+ end
+ end
end
diff --git a/spec/models/pages/virtual_domain_spec.rb b/spec/models/pages/virtual_domain_spec.rb
index 560fe7febd6..02e3fd67f2d 100644
--- a/spec/models/pages/virtual_domain_spec.rb
+++ b/spec/models/pages/virtual_domain_spec.rb
@@ -73,19 +73,4 @@ RSpec.describe Pages::VirtualDomain, feature_category: :pages do
end
end
end
-
- describe '#cache_key' do
- it 'returns the cache key based in the given cache_control' do
- cache_control = instance_double(::Gitlab::Pages::CacheControl, cache_key: 'cache_key')
- virtual_domain = described_class.new(projects: [instance_double(Project)], cache: cache_control)
-
- expect(virtual_domain.cache_key).to eq('cache_key')
- end
-
- it 'returns nil when no cache_control is given' do
- virtual_domain = described_class.new(projects: [instance_double(Project)])
-
- expect(virtual_domain.cache_key).to be_nil
- end
- end
end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index de2a58d106e..5973649a9d7 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe API::Users, :aggregate_failures, feature_category: :user_profile do
include WorkhorseHelpers
+ include KeysetPaginationHelpers
let_it_be(:admin) { create(:admin) }
let_it_be(:user, reload: true) { create(:user, username: 'user.withdot') }
@@ -258,6 +259,48 @@ RSpec.describe API::Users, :aggregate_failures, feature_category: :user_profile
end.not_to exceed_all_query_limit(control_count)
end
end
+
+ context 'when api_keyset_pagination_multi_order FF is enabled' do
+ before do
+ stub_feature_flags(api_keyset_pagination_multi_order: true)
+ end
+
+ it_behaves_like 'an endpoint with keyset pagination', invalid_order: nil do
+ let(:first_record) { user }
+ let(:second_record) { admin }
+ let(:api_call) { api(path, user) }
+ end
+
+ it 'still supports offset pagination when keyset pagination params are not provided' do
+ get api(path, user)
+
+ expect(response).to include_pagination_headers
+ end
+ end
+
+ context 'when api_keyset_pagination_multi_order FF is disabled' do
+ before do
+ stub_feature_flags(api_keyset_pagination_multi_order: false)
+ end
+
+ it 'paginates the records correctly using offset pagination' do
+ get api(path, user), params: { pagination: 'keyset', per_page: 1 }
+
+ params_for_next_page = pagination_params_from_next_url(response)
+ expect(response).to include_pagination_headers
+ expect(params_for_next_page).not_to include('cursor')
+ end
+
+ context 'on making requests with unsupported ordering structure' do
+ it 'does not return error' do
+ get api(path, user),
+ params: { pagination: 'keyset', per_page: 1, order_by: 'created_at', sort: 'asc' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ end
+ end
+ end
end
end
diff --git a/spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb b/spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb
deleted file mode 100644
index 9a74f5ca07a..00000000000
--- a/spec/services/bulk_imports/create_pipeline_trackers_service_spec.rb
+++ /dev/null
@@ -1,176 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BulkImports::CreatePipelineTrackersService, feature_category: :importers do
- describe '#execute!' do
- context 'when entity is group' do
- it 'creates trackers for group entity' do
- bulk_import = create(:bulk_import)
- entity = create(:bulk_import_entity, :group_entity, bulk_import: bulk_import)
-
- described_class.new(entity).execute!
-
- expect(entity.trackers.to_a).to include(
- have_attributes(
- stage: 0, status_name: :created, relation: BulkImports::Groups::Pipelines::GroupPipeline.to_s
- ),
- have_attributes(
- stage: 1, status_name: :created, relation: BulkImports::Groups::Pipelines::GroupAttributesPipeline.to_s
- )
- )
- end
- end
-
- context 'when entity is project' do
- it 'creates trackers for project entity' do
- bulk_import = create(:bulk_import)
- entity = create(:bulk_import_entity, :project_entity, bulk_import: bulk_import)
-
- described_class.new(entity).execute!
-
- expect(entity.trackers.to_a).to include(
- have_attributes(
- stage: 0, status_name: :created, relation: BulkImports::Projects::Pipelines::ProjectPipeline.to_s
- ),
- have_attributes(
- stage: 1, status_name: :created, relation: BulkImports::Projects::Pipelines::RepositoryPipeline.to_s
- )
- )
- end
- end
-
- context 'when tracker configuration has a minimum version defined' do
- before do
- allow_next_instance_of(BulkImports::Groups::Stage) do |stage|
- allow(stage).to receive(:config).and_return(
- {
- pipeline1: { pipeline: 'PipelineClass1', stage: 0 },
- pipeline2: { pipeline: 'PipelineClass2', stage: 1, minimum_source_version: '14.10.0' },
- pipeline3: { pipeline: 'PipelineClass3', stage: 1, minimum_source_version: '15.0.0' },
- pipeline5: { pipeline: 'PipelineClass4', stage: 1, minimum_source_version: '15.1.0' },
- pipeline6: { pipeline: 'PipelineClass5', stage: 1, minimum_source_version: '16.0.0' }
- }
- )
- end
- end
-
- context 'when the source instance version is older than the tracker mininum version' do
- let_it_be(:bulk_import) { create(:bulk_import, source_version: '15.0.0') }
- let_it_be(:entity) { create(:bulk_import_entity, :group_entity, bulk_import: bulk_import) }
-
- it 'creates trackers as skipped if version requirement does not meet' do
- described_class.new(entity).execute!
-
- expect(entity.trackers.collect { |tracker| [tracker.status_name, tracker.relation] }).to contain_exactly(
- [:created, 'PipelineClass1'],
- [:created, 'PipelineClass2'],
- [:created, 'PipelineClass3'],
- [:skipped, 'PipelineClass4'],
- [:skipped, 'PipelineClass5']
- )
- end
-
- it 'logs an info message for the skipped pipelines' do
- expect_next_instance_of(Gitlab::Import::Logger) do |logger|
- expect(logger).to receive(:info).with({
- message: 'Pipeline skipped as source instance version not compatible with pipeline',
- bulk_import_entity_id: entity.id,
- bulk_import_id: entity.bulk_import_id,
- bulk_import_entity_type: entity.source_type,
- source_full_path: entity.source_full_path,
- importer: 'gitlab_migration',
- pipeline_name: 'PipelineClass4',
- minimum_source_version: '15.1.0',
- maximum_source_version: nil,
- source_version: '15.0.0'
- })
-
- expect(logger).to receive(:info).with({
- message: 'Pipeline skipped as source instance version not compatible with pipeline',
- bulk_import_entity_id: entity.id,
- bulk_import_id: entity.bulk_import_id,
- bulk_import_entity_type: entity.source_type,
- source_full_path: entity.source_full_path,
- importer: 'gitlab_migration',
- pipeline_name: 'PipelineClass5',
- minimum_source_version: '16.0.0',
- maximum_source_version: nil,
- source_version: '15.0.0'
- })
- end
-
- described_class.new(entity).execute!
- end
- end
-
- context 'when the source instance version is undefined' do
- it 'creates trackers as created' do
- bulk_import = create(:bulk_import, source_version: nil)
- entity = create(:bulk_import_entity, :group_entity, bulk_import: bulk_import)
-
- described_class.new(entity).execute!
-
- expect(entity.trackers.collect { |tracker| [tracker.status_name, tracker.relation] }).to contain_exactly(
- [:created, 'PipelineClass1'],
- [:created, 'PipelineClass2'],
- [:created, 'PipelineClass3'],
- [:created, 'PipelineClass4'],
- [:created, 'PipelineClass5']
- )
- end
- end
- end
-
- context 'when tracker configuration has a maximum version defined' do
- before do
- allow_next_instance_of(BulkImports::Groups::Stage) do |stage|
- allow(stage).to receive(:config).and_return(
- {
- pipeline1: { pipeline: 'PipelineClass1', stage: 0 },
- pipeline2: { pipeline: 'PipelineClass2', stage: 1, maximum_source_version: '14.10.0' },
- pipeline3: { pipeline: 'PipelineClass3', stage: 1, maximum_source_version: '15.0.0' },
- pipeline5: { pipeline: 'PipelineClass4', stage: 1, maximum_source_version: '15.1.0' },
- pipeline6: { pipeline: 'PipelineClass5', stage: 1, maximum_source_version: '16.0.0' }
- }
- )
- end
- end
-
- context 'when the source instance version is older than the tracker maximum version' do
- it 'creates trackers as skipped if version requirement does not meet' do
- bulk_import = create(:bulk_import, source_version: '15.0.0')
- entity = create(:bulk_import_entity, :group_entity, bulk_import: bulk_import)
-
- described_class.new(entity).execute!
-
- expect(entity.trackers.collect { |tracker| [tracker.status_name, tracker.relation] }).to contain_exactly(
- [:created, 'PipelineClass1'],
- [:skipped, 'PipelineClass2'],
- [:created, 'PipelineClass3'],
- [:created, 'PipelineClass4'],
- [:created, 'PipelineClass5']
- )
- end
- end
-
- context 'when the source instance version is a patch version' do
- it 'creates trackers with the same status as the non-patch source version' do
- bulk_import_1 = create(:bulk_import, source_version: '15.0.1')
- entity_1 = create(:bulk_import_entity, :group_entity, bulk_import: bulk_import_1)
-
- bulk_import_2 = create(:bulk_import, source_version: '15.0.0')
- entity_2 = create(:bulk_import_entity, :group_entity, bulk_import: bulk_import_2)
-
- described_class.new(entity_1).execute!
- described_class.new(entity_2).execute!
-
- trackers_1 = entity_1.trackers.collect { |tracker| [tracker.status_name, tracker.relation] }
- trackers_2 = entity_2.trackers.collect { |tracker| [tracker.status_name, tracker.relation] }
-
- expect(trackers_1).to eq(trackers_2)
- end
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb b/spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb
index 39db3b701d9..fc717fbac20 100644
--- a/spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb
+++ b/spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb
@@ -49,7 +49,8 @@ RSpec.shared_examples "protected branches > access control > CE" do
expect(ProtectedBranch.last.push_access_levels.map(&:access_level)).to include(access_type_id)
end
- it "allows updating protected branches so that #{access_type_name} can merge to them" do
+ it "allows updating protected branches so that #{access_type_name} can merge to them",
+ quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/425080' do
visit project_protected_branches_path(project)
show_add_form
diff --git a/spec/support/shared_examples/requests/api_keyset_pagination_shared_examples.rb b/spec/support/shared_examples/requests/api_keyset_pagination_shared_examples.rb
index 60f77e31ae9..85db36013dd 100644
--- a/spec/support/shared_examples/requests/api_keyset_pagination_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api_keyset_pagination_shared_examples.rb
@@ -40,9 +40,11 @@ RSpec.shared_examples 'an endpoint with keyset pagination' do |invalid_order: 'n
context 'on making requests with unsupported ordering structure' do
let(:additional_params) { { order_by: invalid_order, sort: invalid_sort } }
- it 'returns error', :aggregate_failures do
- is_expected.to have_gitlab_http_status(:method_not_allowed)
- expect(json_response['error']).to eq('Keyset pagination is not yet available for this type of request')
+ if invalid_order
+ it 'returns error', :aggregate_failures do
+ is_expected.to have_gitlab_http_status(:method_not_allowed)
+ expect(json_response['error']).to eq('Keyset pagination is not yet available for this type of request')
+ end
end
end
end
diff --git a/spec/workers/bulk_import_worker_spec.rb b/spec/workers/bulk_import_worker_spec.rb
index ec8550bb3bc..c96e5ace124 100644
--- a/spec/workers/bulk_import_worker_spec.rb
+++ b/spec/workers/bulk_import_worker_spec.rb
@@ -137,5 +137,174 @@ RSpec.describe BulkImportWorker, feature_category: :importers do
end
end
end
+
+ context 'when importing a group' do
+ it 'creates trackers for group entity' do
+ bulk_import = create(:bulk_import)
+ entity = create(:bulk_import_entity, :group_entity, bulk_import: bulk_import)
+
+ subject.perform(bulk_import.id)
+
+ expect(entity.trackers.to_a).to include(
+ have_attributes(
+ stage: 0, status_name: :created, relation: BulkImports::Groups::Pipelines::GroupPipeline.to_s
+ ),
+ have_attributes(
+ stage: 1, status_name: :created, relation: BulkImports::Groups::Pipelines::GroupAttributesPipeline.to_s
+ )
+ )
+ end
+ end
+
+ context 'when importing a project' do
+ it 'creates trackers for project entity' do
+ bulk_import = create(:bulk_import)
+ entity = create(:bulk_import_entity, :project_entity, bulk_import: bulk_import)
+
+ subject.perform(bulk_import.id)
+
+ expect(entity.trackers.to_a).to include(
+ have_attributes(
+ stage: 0, status_name: :created, relation: BulkImports::Projects::Pipelines::ProjectPipeline.to_s
+ ),
+ have_attributes(
+ stage: 1, status_name: :created, relation: BulkImports::Projects::Pipelines::RepositoryPipeline.to_s
+ )
+ )
+ end
+ end
+
+ context 'when tracker configuration has a minimum version defined' do
+ before do
+ allow_next_instance_of(BulkImports::Groups::Stage) do |stage|
+ allow(stage).to receive(:config).and_return(
+ {
+ pipeline1: { pipeline: 'PipelineClass1', stage: 0 },
+ pipeline2: { pipeline: 'PipelineClass2', stage: 1, minimum_source_version: '14.10.0' },
+ pipeline3: { pipeline: 'PipelineClass3', stage: 1, minimum_source_version: '15.0.0' },
+ pipeline5: { pipeline: 'PipelineClass4', stage: 1, minimum_source_version: '15.1.0' },
+ pipeline6: { pipeline: 'PipelineClass5', stage: 1, minimum_source_version: '16.0.0' }
+ }
+ )
+ end
+ end
+
+ context 'when the source instance version is older than the tracker mininum version' do
+ let_it_be(:bulk_import) { create(:bulk_import, source_version: '15.0.0') }
+ let_it_be(:entity) { create(:bulk_import_entity, :group_entity, bulk_import: bulk_import) }
+
+ it 'creates trackers as skipped if version requirement does not meet' do
+ subject.perform(bulk_import.id)
+
+ expect(entity.trackers.collect { |tracker| [tracker.status_name, tracker.relation] }).to contain_exactly(
+ [:created, 'PipelineClass1'],
+ [:created, 'PipelineClass2'],
+ [:created, 'PipelineClass3'],
+ [:skipped, 'PipelineClass4'],
+ [:skipped, 'PipelineClass5']
+ )
+ end
+
+ it 'logs an info message for the skipped pipelines' do
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger).to receive(:info).with({
+ message: 'Pipeline skipped as source instance version not compatible with pipeline',
+ bulk_import_entity_id: entity.id,
+ bulk_import_id: entity.bulk_import_id,
+ bulk_import_entity_type: entity.source_type,
+ source_full_path: entity.source_full_path,
+ importer: 'gitlab_migration',
+ pipeline_name: 'PipelineClass4',
+ minimum_source_version: '15.1.0',
+ maximum_source_version: nil,
+ source_version: '15.0.0'
+ })
+
+ expect(logger).to receive(:info).with({
+ message: 'Pipeline skipped as source instance version not compatible with pipeline',
+ bulk_import_entity_id: entity.id,
+ bulk_import_id: entity.bulk_import_id,
+ bulk_import_entity_type: entity.source_type,
+ source_full_path: entity.source_full_path,
+ importer: 'gitlab_migration',
+ pipeline_name: 'PipelineClass5',
+ minimum_source_version: '16.0.0',
+ maximum_source_version: nil,
+ source_version: '15.0.0'
+ })
+ end
+
+ subject.perform(bulk_import.id)
+ end
+ end
+
+ context 'when the source instance version is undefined' do
+ it 'creates trackers as created' do
+ bulk_import = create(:bulk_import, source_version: nil)
+ entity = create(:bulk_import_entity, :group_entity, bulk_import: bulk_import)
+
+ subject.perform(bulk_import.id)
+
+ expect(entity.trackers.collect { |tracker| [tracker.status_name, tracker.relation] }).to contain_exactly(
+ [:created, 'PipelineClass1'],
+ [:created, 'PipelineClass2'],
+ [:created, 'PipelineClass3'],
+ [:created, 'PipelineClass4'],
+ [:created, 'PipelineClass5']
+ )
+ end
+ end
+ end
+
+ context 'when tracker configuration has a maximum version defined' do
+ before do
+ allow_next_instance_of(BulkImports::Groups::Stage) do |stage|
+ allow(stage).to receive(:config).and_return(
+ {
+ pipeline1: { pipeline: 'PipelineClass1', stage: 0 },
+ pipeline2: { pipeline: 'PipelineClass2', stage: 1, maximum_source_version: '14.10.0' },
+ pipeline3: { pipeline: 'PipelineClass3', stage: 1, maximum_source_version: '15.0.0' },
+ pipeline5: { pipeline: 'PipelineClass4', stage: 1, maximum_source_version: '15.1.0' },
+ pipeline6: { pipeline: 'PipelineClass5', stage: 1, maximum_source_version: '16.0.0' }
+ }
+ )
+ end
+ end
+
+ context 'when the source instance version is older than the tracker maximum version' do
+ it 'creates trackers as skipped if version requirement does not meet' do
+ bulk_import = create(:bulk_import, source_version: '15.0.0')
+ entity = create(:bulk_import_entity, :group_entity, bulk_import: bulk_import)
+
+ subject.perform(bulk_import.id)
+
+ expect(entity.trackers.collect { |tracker| [tracker.status_name, tracker.relation] }).to contain_exactly(
+ [:created, 'PipelineClass1'],
+ [:skipped, 'PipelineClass2'],
+ [:created, 'PipelineClass3'],
+ [:created, 'PipelineClass4'],
+ [:created, 'PipelineClass5']
+ )
+ end
+ end
+
+ context 'when the source instance version is a patch version' do
+ it 'creates trackers with the same status as the non-patch source version' do
+ bulk_import_1 = create(:bulk_import, source_version: '15.0.1')
+ entity_1 = create(:bulk_import_entity, :group_entity, bulk_import: bulk_import_1)
+
+ bulk_import_2 = create(:bulk_import, source_version: '15.0.0')
+ entity_2 = create(:bulk_import_entity, :group_entity, bulk_import: bulk_import_2)
+
+ described_class.perform_inline(bulk_import_1.id)
+ described_class.perform_inline(bulk_import_2.id)
+
+ trackers_1 = entity_1.trackers.collect { |tracker| [tracker.status_name, tracker.relation] }
+ trackers_2 = entity_2.trackers.collect { |tracker| [tracker.status_name, tracker.relation] }
+
+ expect(trackers_1).to eq(trackers_2)
+ end
+ end
+ end
end
end
diff --git a/spec/workers/pages/invalidate_domain_cache_worker_spec.rb b/spec/workers/pages/invalidate_domain_cache_worker_spec.rb
deleted file mode 100644
index b3c81b25a93..00000000000
--- a/spec/workers/pages/invalidate_domain_cache_worker_spec.rb
+++ /dev/null
@@ -1,267 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Pages::InvalidateDomainCacheWorker, feature_category: :pages do
- shared_examples 'clears caches with' do |event_class:, event_data:, caches:|
- include AfterNextHelpers
-
- let(:event) { event_class.new(data: event_data) }
-
- subject { consume_event(subscriber: described_class, event: event) }
-
- it_behaves_like 'subscribes to event'
-
- it 'clears the cache with Gitlab::Pages::CacheControl' do
- caches.each do |cache|
- expect_next(Gitlab::Pages::CacheControl, type: cache[:type], id: cache[:id])
- .to receive(:clear_cache)
- end
-
- subject
- end
- end
-
- context 'when a project have multiple domains' do
- include AfterNextHelpers
-
- let_it_be(:project) { create(:project) }
- let_it_be(:pages_domain) { create(:pages_domain, project: project) }
- let_it_be(:pages_domain2) { create(:pages_domain, project: project) }
-
- let(:event) do
- Pages::PageDeployedEvent.new(
- data: {
- project_id: project.id,
- namespace_id: project.namespace_id,
- root_namespace_id: project.root_ancestor.id
- }
- )
- end
-
- subject { consume_event(subscriber: described_class, event: event) }
-
- it 'clears the cache with Gitlab::Pages::CacheControl' do
- expect_next(Gitlab::Pages::CacheControl, type: :namespace, id: project.namespace_id)
- .to receive(:clear_cache)
- expect_next(Gitlab::Pages::CacheControl, type: :domain, id: pages_domain.id)
- .to receive(:clear_cache)
- expect_next(Gitlab::Pages::CacheControl, type: :domain, id: pages_domain2.id)
- .to receive(:clear_cache)
-
- subject
- end
- end
-
- it_behaves_like 'clears caches with',
- event_class: Pages::PageDeployedEvent,
- event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 },
- caches: [
- { type: :namespace, id: 3 }
- ]
-
- it_behaves_like 'clears caches with',
- event_class: Pages::PageDeletedEvent,
- event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 },
- caches: [
- { type: :namespace, id: 3 }
- ]
-
- it_behaves_like 'clears caches with',
- event_class: Projects::ProjectDeletedEvent,
- event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 },
- caches: [
- { type: :namespace, id: 3 }
- ]
-
- it_behaves_like 'clears caches with',
- event_class: Projects::ProjectCreatedEvent,
- event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 },
- caches: [
- { type: :namespace, id: 3 }
- ]
-
- it_behaves_like 'clears caches with',
- event_class: Projects::ProjectArchivedEvent,
- event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 },
- caches: [
- { type: :namespace, id: 3 }
- ]
-
- it_behaves_like 'clears caches with',
- event_class: Projects::ProjectPathChangedEvent,
- event_data: {
- project_id: 1,
- namespace_id: 2,
- root_namespace_id: 3,
- old_path: 'old_path',
- new_path: 'new_path'
- },
- caches: [
- { type: :namespace, id: 3 }
- ]
-
- it_behaves_like 'clears caches with',
- event_class: Projects::ProjectTransferedEvent,
- event_data: {
- project_id: 1,
- old_namespace_id: 2,
- old_root_namespace_id: 3,
- new_namespace_id: 4,
- new_root_namespace_id: 5
- },
- caches: [
- { type: :namespace, id: 3 },
- { type: :namespace, id: 5 }
- ]
-
- it_behaves_like 'clears caches with',
- event_class: Groups::GroupTransferedEvent,
- event_data: {
- group_id: 1,
- old_root_namespace_id: 3,
- new_root_namespace_id: 5
- },
- caches: [
- { type: :namespace, id: 3 },
- { type: :namespace, id: 5 }
- ]
-
- it_behaves_like 'clears caches with',
- event_class: Groups::GroupPathChangedEvent,
- event_data: {
- group_id: 1,
- root_namespace_id: 2,
- old_path: 'old_path',
- new_path: 'new_path'
- },
- caches: [
- { type: :namespace, id: 2 }
- ]
-
- it_behaves_like 'clears caches with',
- event_class: Groups::GroupDeletedEvent,
- event_data: {
- group_id: 1,
- root_namespace_id: 3
- },
- caches: [
- { type: :namespace, id: 3 }
- ]
-
- it_behaves_like 'clears caches with',
- event_class: PagesDomains::PagesDomainDeletedEvent,
- event_data: {
- project_id: 1,
- namespace_id: 2,
- root_namespace_id: 3,
- domain_id: 4,
- domain: 'somedomain.com'
- },
- caches: [
- { type: :domain, id: 4 },
- { type: :namespace, id: 3 }
- ]
-
- it_behaves_like 'clears caches with',
- event_class: PagesDomains::PagesDomainUpdatedEvent,
- event_data: {
- project_id: 1,
- namespace_id: 2,
- root_namespace_id: 3,
- domain_id: 4,
- domain: 'somedomain.com'
- },
- caches: [
- { type: :domain, id: 4 },
- { type: :namespace, id: 3 }
- ]
-
- it_behaves_like 'clears caches with',
- event_class: PagesDomains::PagesDomainCreatedEvent,
- event_data: {
- project_id: 1,
- namespace_id: 2,
- root_namespace_id: 3,
- domain_id: 4,
- domain: 'somedomain.com'
- },
- caches: [
- { type: :domain, id: 4 },
- { type: :namespace, id: 3 }
- ]
-
- context 'when project attributes change' do
- Projects::ProjectAttributesChangedEvent::PAGES_RELATED_ATTRIBUTES.each do |attribute|
- it_behaves_like 'clears caches with',
- event_class: Projects::ProjectAttributesChangedEvent,
- event_data: {
- project_id: 1,
- namespace_id: 2,
- root_namespace_id: 3,
- domain_id: 4,
- attributes: [attribute]
- },
- caches: [
- { type: :domain, id: 4 },
- { type: :namespace, id: 3 }
- ]
- end
-
- it_behaves_like 'ignores the published event' do
- let(:event) do
- Projects::ProjectAttributesChangedEvent.new(
- data: {
- project_id: 1,
- namespace_id: 2,
- root_namespace_id: 3,
- attributes: ['unknown']
- }
- )
- end
- end
- end
-
- context 'when project features change' do
- it_behaves_like 'clears caches with',
- event_class: Projects::ProjectFeaturesChangedEvent,
- event_data: {
- project_id: 1,
- namespace_id: 2,
- root_namespace_id: 3,
- features: ['pages_access_level']
- },
- caches: [
- { type: :namespace, id: 3 }
- ]
-
- it_behaves_like 'ignores the published event' do
- let(:event) do
- Projects::ProjectFeaturesChangedEvent.new(
- data: {
- project_id: 1,
- namespace_id: 2,
- root_namespace_id: 3,
- features: ['unknown']
- }
- )
- end
- end
- end
-
- context 'when namespace based cache keys are duplicated' do
- # de-dups namespace cache keys
- it_behaves_like 'clears caches with',
- event_class: Projects::ProjectTransferedEvent,
- event_data: {
- project_id: 1,
- old_namespace_id: 2,
- old_root_namespace_id: 5,
- new_namespace_id: 4,
- new_root_namespace_id: 5
- },
- caches: [
- { type: :namespace, id: 5 }
- ]
- end
-end