Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-05-26 15:11:45 +00:00
parent fb43226fd8
commit 458ea72fff
66 changed files with 640 additions and 225 deletions

View File

@ -2694,7 +2694,6 @@ Gitlab/BoundedContexts:
- 'ee/app/models/concerns/epics/metadata_cache_update.rb'
- 'ee/app/models/concerns/filterable_by_test_reports.rb'
- 'ee/app/models/concerns/health_status.rb'
- 'ee/app/models/concerns/singleton_record.rb'
- 'ee/app/models/concerns/identity_verifiable.rb'
- 'ee/app/models/concerns/incident_management/base_pending_escalation.rb'
- 'ee/app/models/concerns/insights_feature.rb'
@ -2705,6 +2704,7 @@ Gitlab/BoundedContexts:
- 'ee/app/models/concerns/product_analytics/schema_validator.rb'
- 'ee/app/models/concerns/product_analytics_helpers.rb'
- 'ee/app/models/concerns/scim_paginatable.rb'
- 'ee/app/models/concerns/singleton_record.rb'
- 'ee/app/models/concerns/visible_approvable.rb'
- 'ee/app/models/concerns/vulnerability_scopes.rb'
- 'ee/app/models/dast/branch.rb'

View File

@ -77,7 +77,6 @@ Gitlab/NoFindInWorkers:
- 'ee/app/workers/create_github_webhook_worker.rb'
- 'ee/app/workers/dependencies/export_worker.rb'
- 'ee/app/workers/elastic/namespace_update_worker.rb'
- 'ee/app/workers/elastic/project_transfer_worker.rb'
- 'ee/app/workers/gitlab/export/segmented_export_finalisation_worker.rb'
- 'ee/app/workers/gitlab/export/segmented_export_worker.rb'
- 'ee/app/workers/group_wikis/git_garbage_collect_worker.rb'

View File

@ -3,8 +3,6 @@ Gitlab/RSpec/AvoidCreateDefaultOrganization:
Details: grace period
Exclude:
- 'ee/spec/finders/ai/code_suggestion_events_finder_spec.rb'
- 'ee/spec/lib/gitlab/auth/smartcard/ldap_certificate_spec.rb'
- 'ee/spec/requests/smartcard_controller_spec.rb'
- 'spec/features/user_settings/personal_access_tokens_spec.rb'
- 'spec/helpers/organizations/organization_helper_spec.rb'
- 'spec/lib/gitlab/current/organization_spec.rb'

View File

@ -65,6 +65,7 @@ Gitlab/RSpec/MisplacedEeSpecFile:
- 'ee/spec/graphql/types/gitlab_subscriptions/member_management/users_queued_for_role_promotion_type_spec.rb'
- 'ee/spec/graphql/types/issue_connection_type_spec.rb'
- 'ee/spec/graphql/types/issue_type_spec.rb'
- 'ee/spec/graphql/types/namespaces/user_level_permissions/group_namespace_user_level_permissions_type_spec.rb'
- 'ee/spec/graphql/types/permission_types/group_spec.rb'
- 'ee/spec/graphql/types/permission_types/namespaces/base_spec.rb'
- 'ee/spec/graphql/types/permission_types/project_spec.rb'

View File

@ -305,7 +305,6 @@ Layout/EmptyLineAfterMagicComment:
- 'lib/gitlab/auth/blocked_user_tracker.rb'
- 'lib/gitlab/auth/otp/fortinet.rb'
- 'lib/gitlab/ci/secure_files/mobile_provision.rb'
- 'lib/gitlab/cleanup/remote_uploads.rb'
- 'lib/gitlab/database/migrations/background_migration_helpers.rb'
- 'lib/gitlab/database/partitioning/detached_partition_dropper.rb'
- 'lib/gitlab/diff/highlight_cache.rb'

View File

@ -387,7 +387,6 @@ Layout/LineEndStringConcatenationIndentation:
- 'qa/qa/scenario/shared_attributes.rb'
- 'qa/qa/service/docker_run/product_analytics/browser_sdk_app.rb'
- 'qa/qa/service/docker_run/product_analytics/dotnet_sdk_app.rb'
- 'qa/qa/specs/features/ee/api/10_govern/compliance_pipeline_spec.rb'
- 'qa/qa/support/system_logs/kibana.rb'
- 'qa/qa/tools/revoke_user_personal_access_tokens.rb'
- 'qa/qa/tools/test_resources_handler.rb'

View File

@ -46,7 +46,6 @@ Layout/LineLength:
- 'app/graphql/types/repository/blob_type.rb'
- 'app/graphql/types/repository_type.rb'
- 'app/graphql/types/snippets/visibility_scopes_enum.rb'
- 'app/graphql/types/todo_action_enum.rb'
- 'app/helpers/application_helper.rb'
- 'app/helpers/application_settings_helper.rb'
- 'app/helpers/award_emoji_helper.rb'
@ -1827,7 +1826,6 @@ Layout/LineLength:
- 'ee/spec/workers/iterations/roll_over_issues_worker_spec.rb'
- 'ee/spec/workers/iterations_update_status_worker_spec.rb'
- 'ee/spec/workers/merge_request_reset_approvals_worker_spec.rb'
- 'ee/spec/workers/new_epic_worker_spec.rb'
- 'ee/spec/workers/repository_import_worker_spec.rb'
- 'ee/spec/workers/security/orchestration_policy_rule_schedule_namespace_worker_spec.rb'
- 'ee/spec/workers/security/orchestration_policy_rule_schedule_worker_spec.rb'
@ -1982,7 +1980,6 @@ Layout/LineLength:
- 'lib/gitlab/auth/ldap/dn.rb'
- 'lib/gitlab/auth/ldap/person.rb'
- 'lib/gitlab/auth/o_auth/user.rb'
- 'lib/gitlab/auth/saml/auth_hash.rb'
- 'lib/gitlab/auth/user_access_denied_reason.rb'
- 'lib/gitlab/background_migration/backfill_issue_search_data.rb'
- 'lib/gitlab/background_migration/backfill_iteration_cadence_id_for_boards.rb'

View File

@ -87,7 +87,6 @@ Lint/EmptyBlock:
- 'spec/lib/gitlab/database/shared_model_spec.rb'
- 'spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb'
- 'spec/lib/gitlab/database/with_lock_retries_spec.rb'
- 'spec/lib/gitlab/database_spec.rb'
- 'spec/lib/gitlab/etag_caching/router/graphql_spec.rb'
- 'spec/lib/gitlab/exclusive_lease_helpers_spec.rb'
- 'spec/lib/gitlab/exclusive_lease_spec.rb'

View File

@ -66,7 +66,6 @@ Lint/UnusedMethodArgument:
- 'app/helpers/environment_helper.rb'
- 'app/helpers/groups/group_members_helper.rb'
- 'app/helpers/groups_helper.rb'
- 'app/helpers/invite_members_helper.rb'
- 'app/helpers/issuables_helper.rb'
- 'app/helpers/issues_helper.rb'
- 'app/helpers/labels_helper.rb'

View File

@ -39,7 +39,6 @@ Performance/MapCompact:
- 'config/initializers/trusted_proxies.rb'
- 'config/initializers/wikicloth_redos_patch.rb'
- 'ee/app/graphql/ee/types/issue_connection_type.rb'
- 'ee/app/graphql/resolvers/geo/registries_resolver.rb'
- 'ee/app/models/app_sec/fuzzing/api/ci_configuration.rb'
- 'ee/app/models/burndown.rb'
- 'ee/app/models/concerns/ee/project_security_scanners_information.rb'

View File

@ -74,19 +74,14 @@ Rails/Date:
- 'ee/spec/models/gitlab_subscription_spec.rb'
- 'ee/spec/models/iteration_spec.rb'
- 'ee/spec/requests/api/group_milestones_spec.rb'
- 'ee/spec/requests/api/group_service_accounts_spec.rb'
- 'ee/spec/requests/api/issues_spec.rb'
- 'ee/spec/requests/api/license_spec.rb'
- 'ee/spec/requests/api/members_spec.rb'
- 'ee/spec/requests/api/namespaces_spec.rb'
- 'ee/spec/requests/api/project_milestones_spec.rb'
- 'ee/spec/requests/custom_roles/manage_group_access_tokens/request_spec.rb'
- 'ee/spec/requests/custom_roles/manage_project_access_tokens/request_spec.rb'
- 'ee/spec/requests/git_http_spec.rb'
- 'ee/spec/requests/gitlab_subscriptions/api/internal/upcoming_reconciliations_spec.rb'
- 'ee/spec/requests/gitlab_subscriptions/api/internal/users_spec.rb'
- 'ee/spec/requests/groups/settings/access_tokens_controller_spec.rb'
- 'ee/spec/requests/projects/settings/access_tokens_controller_spec.rb'
- 'ee/spec/services/app_sec/dast/profile_schedules/audit/update_service_spec.rb'
- 'ee/spec/services/audit_event_service_spec.rb'
- 'ee/spec/services/ci/minutes/additional_packs/create_service_spec.rb'
@ -180,15 +175,11 @@ Rails/Date:
- 'spec/requests/api/graphql/mutations/work_items/update_spec.rb'
- 'spec/requests/api/graphql/work_item_spec.rb'
- 'spec/requests/api/internal/base_spec.rb'
- 'spec/requests/api/personal_access_tokens/self_rotation_spec.rb'
- 'spec/requests/api/personal_access_tokens_spec.rb'
- 'spec/requests/api/project_statistics_spec.rb'
- 'spec/requests/api/resource_access_tokens_spec.rb'
- 'spec/requests/api/users_spec.rb'
- 'spec/requests/git_http_spec.rb'
- 'spec/requests/groups/settings/access_tokens_controller_spec.rb'
- 'spec/requests/jwt_controller_spec.rb'
- 'spec/requests/projects/settings/access_tokens_controller_spec.rb'
- 'spec/requests/verifies_with_email_spec.rb'
- 'spec/serializers/entity_date_helper_spec.rb'
- 'spec/serializers/member_user_entity_spec.rb'

View File

@ -8,7 +8,6 @@ Rails/HelperInstanceVariable:
- 'app/helpers/award_emoji_helper.rb'
- 'app/helpers/blob_helper.rb'
- 'app/helpers/boards_helper.rb'
- 'app/helpers/branches_helper.rb'
- 'app/helpers/breadcrumbs_helper.rb'
- 'app/helpers/ci/builds_helper.rb'
- 'app/helpers/commits_helper.rb'

View File

@ -7,7 +7,6 @@ RSpec/BeEq:
- 'ee/spec/controllers/concerns/ee/routable_actions/sso_enforcement_redirect_spec.rb'
- 'ee/spec/controllers/concerns/routable_actions_spec.rb'
- 'ee/spec/controllers/ee/groups_controller_spec.rb'
- 'ee/spec/controllers/ee/profiles/preferences_controller_spec.rb'
- 'ee/spec/controllers/ee/projects/blob_controller_spec.rb'
- 'ee/spec/controllers/ee/projects/jobs_controller_spec.rb'
- 'ee/spec/controllers/ee/projects/pages_controller_spec.rb'
@ -26,7 +25,6 @@ RSpec/BeEq:
- 'ee/spec/features/admin/admin_emails_spec.rb'
- 'ee/spec/features/admin/admin_settings_spec.rb'
- 'ee/spec/features/admin/users/users_spec.rb'
- 'ee/spec/features/epics/epic_work_item_sync_spec.rb'
- 'ee/spec/features/groups/settings/reporting_spec.rb'
- 'ee/spec/features/issues/user_bulk_edits_issues_spec.rb'
- 'ee/spec/features/projects/new_project_spec.rb'

View File

@ -781,7 +781,6 @@ RSpec/ContextWording:
- 'ee/spec/workers/incident_management/apply_incident_sla_exceeded_label_worker_spec.rb'
- 'ee/spec/workers/incident_management/oncall_rotations/persist_shifts_job_spec.rb'
- 'ee/spec/workers/merge_request_reset_approvals_worker_spec.rb'
- 'ee/spec/workers/new_epic_worker_spec.rb'
- 'ee/spec/workers/personal_access_tokens/groups/policy_worker_spec.rb'
- 'ee/spec/workers/personal_access_tokens/instance/policy_worker_spec.rb'
- 'ee/spec/workers/post_receive_spec.rb'

View File

@ -92,7 +92,6 @@ RSpec/FeatureCategory:
- 'ee/spec/graphql/ee/types/milestone_type_spec.rb'
- 'ee/spec/graphql/ee/types/mutation_type_spec.rb'
- 'ee/spec/graphql/ee/types/notes/noteable_interface_spec.rb'
- 'ee/spec/graphql/ee/types/repository/blob_type_spec.rb'
- 'ee/spec/graphql/ee/types/user_merge_request_interaction_type_spec.rb'
- 'ee/spec/graphql/mutations/app_sec/fuzzing/coverage/corpus/create_spec.rb'
- 'ee/spec/graphql/mutations/audit_events/streaming/headers/destroy_spec.rb'
@ -928,7 +927,6 @@ RSpec/FeatureCategory:
- 'ee/spec/services/app_sec/fuzzing/api/ci_configuration_create_service_spec.rb'
- 'ee/spec/services/app_sec/fuzzing/coverage/corpuses/create_service_spec.rb'
- 'ee/spec/services/application_settings/update_service_spec.rb'
- 'ee/spec/services/applications/create_service_spec.rb'
- 'ee/spec/services/approval_rules/finalize_service_spec.rb'
- 'ee/spec/services/approval_rules/merge_request_rule_destroy_service_spec.rb'
- 'ee/spec/services/approval_rules/params_filtering_service_spec.rb'
@ -2979,10 +2977,7 @@ RSpec/FeatureCategory:
- 'spec/lib/safe_zip/entry_spec.rb'
- 'spec/lib/safe_zip/extract_params_spec.rb'
- 'spec/lib/safe_zip/extract_spec.rb'
- 'spec/lib/security/ci_configuration/container_scanning_build_action_spec.rb'
- 'spec/lib/security/ci_configuration/sast_build_action_spec.rb'
- 'spec/lib/security/ci_configuration/sast_iac_build_action_spec.rb'
- 'spec/lib/security/ci_configuration/secret_detection_build_action_spec.rb'
- 'spec/lib/security/report_schema_version_matcher_spec.rb'
- 'spec/lib/serializers/unsafe_json_spec.rb'
- 'spec/lib/service_ping/devops_report_spec.rb'
@ -3685,7 +3680,6 @@ RSpec/FeatureCategory:
- 'spec/serializers/user_serializer_spec.rb'
- 'spec/serializers/web_ide_terminal_entity_spec.rb'
- 'spec/serializers/web_ide_terminal_serializer_spec.rb'
- 'spec/services/applications/create_service_spec.rb'
- 'spec/sidekiq/cron/job_gem_dependency_spec.rb'
- 'spec/sidekiq_cluster/sidekiq_cluster_spec.rb'
- 'spec/spam/concerns/has_spam_action_response_fields_spec.rb'

View File

@ -1382,7 +1382,6 @@ RSpec/NamedSubject:
- 'spec/helpers/gitlab_routing_helper_spec.rb'
- 'spec/helpers/groups/group_members_helper_spec.rb'
- 'spec/helpers/groups_helper_spec.rb'
- 'spec/helpers/hooks_helper_spec.rb'
- 'spec/helpers/integrations_helper_spec.rb'
- 'spec/helpers/jira_connect_helper_spec.rb'
- 'spec/helpers/labels_helper_spec.rb'
@ -1766,7 +1765,6 @@ RSpec/NamedSubject:
- 'spec/lib/gitlab/ci/yaml_processor_spec.rb'
- 'spec/lib/gitlab/cleanup/personal_access_tokens_spec.rb'
- 'spec/lib/gitlab/cleanup/project_uploads_spec.rb'
- 'spec/lib/gitlab/cleanup/remote_uploads_spec.rb'
- 'spec/lib/gitlab/closing_issue_extractor_spec.rb'
- 'spec/lib/gitlab/cluster/lifecycle_events_spec.rb'
- 'spec/lib/gitlab/cluster/rack_timeout_observer_spec.rb'

View File

@ -175,7 +175,6 @@ RSpec/VerifiedDoubles:
- 'ee/spec/workers/iterations/roll_over_issues_worker_spec.rb'
- 'ee/spec/workers/ldap_group_sync_worker_spec.rb'
- 'ee/spec/workers/merge_request_reset_approvals_worker_spec.rb'
- 'ee/spec/workers/new_epic_worker_spec.rb'
- 'qa/spec/git/repository_spec.rb'
- 'qa/spec/page/base_spec.rb'
- 'qa/spec/page/validator_spec.rb'

View File

@ -88,7 +88,6 @@ Style/HashEachMethods:
- 'lib/gitlab/utils/batch_loader.rb'
- 'lib/tasks/gitlab/db.rake'
- 'lib/tasks/gitlab/setup.rake'
- 'qa/qa/specs/features/ee/browser_ui/10_govern/change_vulnerability_status_spec.rb'
- 'qa/spec/specs/runner_spec.rb'
- 'scripts/generate_rspec_pipeline.rb'
- 'spec/config/settings_spec.rb'

View File

@ -1302,7 +1302,6 @@ Style/InlineDisableAnnotation:
- 'ee/app/workers/concerns/elastic/bulk_cron_worker.rb'
- 'ee/app/workers/concerns/geo/base_registry_sync_worker.rb'
- 'ee/app/workers/create_github_webhook_worker.rb'
- 'ee/app/workers/elastic/migration_worker.rb'
- 'ee/app/workers/elastic/namespace_update_worker.rb'
- 'ee/app/workers/elastic_cluster_reindexing_cron_worker.rb'
- 'ee/app/workers/elastic_full_index_worker.rb'
@ -1609,7 +1608,6 @@ Style/InlineDisableAnnotation:
- 'ee/spec/workers/ldap_all_groups_sync_worker_spec.rb'
- 'ee/spec/workers/ldap_group_sync_worker_spec.rb'
- 'ee/spec/workers/ldap_sync_worker_spec.rb'
- 'ee/spec/workers/new_epic_worker_spec.rb'
- 'ee/spec/workers/projects/register_suggested_reviewers_project_worker_spec.rb'
- 'ee/spec/workers/update_all_mirrors_worker_spec.rb'
- 'lib/api/access_requests.rb'
@ -1626,7 +1624,6 @@ Style/InlineDisableAnnotation:
- 'lib/api/ci/resource_groups.rb'
- 'lib/api/ci/runners.rb'
- 'lib/api/ci/secure_files.rb'
- 'lib/api/ci/triggers.rb'
- 'lib/api/commit_statuses.rb'
- 'lib/api/custom_attributes_endpoints.rb'
- 'lib/api/dependency_proxy.rb'
@ -1787,7 +1784,6 @@ Style/InlineDisableAnnotation:
- 'lib/gitlab/ci/trace/stream.rb'
- 'lib/gitlab/cleanup/personal_access_tokens.rb'
- 'lib/gitlab/cleanup/project_uploads.rb'
- 'lib/gitlab/cleanup/remote_uploads.rb'
- 'lib/gitlab/cluster/lifecycle_events.rb'
- 'lib/gitlab/cluster/mixins/puma_cluster.rb'
- 'lib/gitlab/config/entry/composable_array.rb'
@ -2051,9 +2047,6 @@ Style/InlineDisableAnnotation:
- 'qa/qa/service/shellout.rb'
- 'qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb'
- 'qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_basic_integration_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/10_govern/create_merge_request_with_secure_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/10_govern/group/group_audit_logs_1_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/10_govern/instance/instance_audit_logs_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/integrations/jira_issues_list_spec.rb'
- 'qa/qa/specs/qa_deprecation_toolkit_env.rb'
- 'qa/qa/support/fips.rb'

View File

@ -1 +1 @@
b47256232c83b9a8b5811cc27c22801ab63ce879
9277be2d60b30145b4afcbb171db3009d0beff7a

View File

@ -1 +1 @@
73665fe4d78f13031adb21ccd18fee421474b3e0
7dd8b96b0d2229cad3ff85dc637ccda307062331

View File

@ -62,7 +62,7 @@
{"name":"bigdecimal","version":"3.1.7","platform":"ruby","checksum":"e799b369a0005fc6d62eed7ef19139ac9bc319cc51470c637b9dcdf593600133"},
{"name":"bindata","version":"2.4.11","platform":"ruby","checksum":"c38e0c99ffcd80c10a0a7ae6c8586d2fe26bf245cbefac90bec8764523220f6a"},
{"name":"binding_of_caller","version":"1.0.0","platform":"ruby","checksum":"3aad25d1d538fc6e7972978f9bf512ccd992784009947c81633bea776713161d"},
{"name":"bootsnap","version":"1.18.4","platform":"ruby","checksum":"ac4c42af397f7ee15521820198daeff545e4c360d2772c601fbdc2c07d92af55"},
{"name":"bootsnap","version":"1.18.6","platform":"ruby","checksum":"0ae2393c1e911e38be0f24e9173e7be570c3650128251bf06240046f84a07d00"},
{"name":"browser","version":"5.3.1","platform":"ruby","checksum":"62745301701ff2c6c5d32d077bb12532b20be261929dcb52c6781ed0d5658b3c"},
{"name":"builder","version":"3.2.4","platform":"ruby","checksum":"99caf08af60c8d7f3a6b004029c4c3c0bdaebced6c949165fe98f1db27fbbc10"},
{"name":"bullet","version":"7.2.0","platform":"ruby","checksum":"3502c8a1b4f5db77fc8f6d3dd89a6a8c1a968219a45e12ae6cbaa9c09967ea89"},

View File

@ -406,7 +406,7 @@ GEM
bindata (2.4.11)
binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1)
bootsnap (1.18.4)
bootsnap (1.18.6)
msgpack (~> 1.2)
browser (5.3.1)
builder (3.2.4)

View File

@ -62,7 +62,7 @@
{"name":"bigdecimal","version":"3.1.7","platform":"ruby","checksum":"e799b369a0005fc6d62eed7ef19139ac9bc319cc51470c637b9dcdf593600133"},
{"name":"bindata","version":"2.4.11","platform":"ruby","checksum":"c38e0c99ffcd80c10a0a7ae6c8586d2fe26bf245cbefac90bec8764523220f6a"},
{"name":"binding_of_caller","version":"1.0.0","platform":"ruby","checksum":"3aad25d1d538fc6e7972978f9bf512ccd992784009947c81633bea776713161d"},
{"name":"bootsnap","version":"1.18.4","platform":"ruby","checksum":"ac4c42af397f7ee15521820198daeff545e4c360d2772c601fbdc2c07d92af55"},
{"name":"bootsnap","version":"1.18.6","platform":"ruby","checksum":"0ae2393c1e911e38be0f24e9173e7be570c3650128251bf06240046f84a07d00"},
{"name":"browser","version":"5.3.1","platform":"ruby","checksum":"62745301701ff2c6c5d32d077bb12532b20be261929dcb52c6781ed0d5658b3c"},
{"name":"builder","version":"3.2.4","platform":"ruby","checksum":"99caf08af60c8d7f3a6b004029c4c3c0bdaebced6c949165fe98f1db27fbbc10"},
{"name":"bullet","version":"7.2.0","platform":"ruby","checksum":"3502c8a1b4f5db77fc8f6d3dd89a6a8c1a968219a45e12ae6cbaa9c09967ea89"},

View File

@ -406,7 +406,7 @@ GEM
bindata (2.4.11)
binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1)
bootsnap (1.18.4)
bootsnap (1.18.6)
msgpack (~> 1.2)
browser (5.3.1)
builder (3.2.4)

View File

@ -1,4 +1,4 @@
import { visitUrl, constructWebIDEPath } from '~/lib/utils/url_utility';
import { visitUrl, constructWebIDEPath, appendLineRangeHashToUrl } from '~/lib/utils/url_utility';
import findAndFollowLink, { findAndFollowChildLink } from '~/lib/utils/navigation_utility';
import {
GO_TO_PROJECT_OVERVIEW,
@ -54,7 +54,8 @@ export default class ShortcutsNavigation {
iid: window.gl.mrWidgetData?.iid,
});
if (path) {
visitUrl(path, true);
const url = appendLineRangeHashToUrl(path);
visitUrl(url, true);
}
}
}

View File

@ -2,6 +2,7 @@ import { start } from '@gitlab/web-ide';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import csrf from '~/lib/utils/csrf';
import Tracking from '~/tracking';
import { getLineRangeFromHash } from '~/lib/utils/url_utility';
import {
getBaseConfig,
getOAuthConfig,
@ -63,6 +64,8 @@ export const initGitlabWebIDE = async (el) => {
const isLanguageServerEnabled = gon?.features?.webIdeLanguageServer || false;
const lineRange = getLineRangeFromHash();
try {
// See ClientOnlyConfig https://gitlab.com/gitlab-org/gitlab-web-ide/-/blob/main/packages/web-ide-types/src/config.ts#L17
await start(rootEl, {
@ -73,6 +76,7 @@ export const initGitlabWebIDE = async (el) => {
projectPath,
ref,
filePath,
lineRange,
mrId,
mrTargetProject: getMRTargetProject(),
forkInfo,

View File

@ -60,6 +60,8 @@ export default {
return {
isSelectedForReimport: false,
showMembershipsModal: false,
userHasSelectedNamespace: false,
showNamespaceRequiredError: false,
};
},
@ -72,8 +74,13 @@ export default {
},
showMembershipsWarning() {
const userNamespaceSelected = this.importTarget.targetNamespace === this.userNamespace;
return (this.isImportNotStarted || this.isSelectedForReimport) && userNamespaceSelected;
const usersNamespaceIsSelected = this.importTarget.targetNamespace === this.userNamespace;
return this.isNotImporting && usersNamespaceIsSelected;
},
isNotImporting() {
return this.isImportNotStarted || this.isSelectedForReimport;
},
isFinished() {
@ -128,6 +135,15 @@ export default {
this.updateImportTarget({ newName: value });
},
},
shouldBlockImportForNamespace() {
if (this.importTarget.targetNamespace) {
return false;
}
return (
!this.repo.importSource.target && this.isNotImporting && !this.userHasSelectedNamespace
);
},
},
methods: {
@ -156,7 +172,9 @@ export default {
},
onImportClick() {
if (this.showMembershipsWarning) {
if (this.shouldBlockImportForNamespace) {
this.showNamespaceRequiredError = true;
} else if (this.showMembershipsWarning) {
this.showMembershipsModal = true;
} else {
this.handleImportRepo();
@ -164,6 +182,8 @@ export default {
},
onSelect(value) {
this.userHasSelectedNamespace = true;
this.showNamespaceRequiredError = false;
this.updateImportTarget({ targetNamespace: value });
},
},
@ -209,6 +229,7 @@ export default {
<div class="gl-flex gl-w-full gl-items-stretch">
<import-target-dropdown
:selected="importTarget.targetNamespace"
:toggle-text="s__('ImportProjects|Select namespace')"
:user-namespace="userNamespace"
@select="onSelect"
/>
@ -224,6 +245,14 @@ export default {
data-testid="project-path-field"
/>
</div>
<p
v-if="showNamespaceRequiredError"
class="gl-m-0 gl-mt-2 gl-text-danger"
role="alert"
data-testid="namespace-required-warning"
>
{{ s__('ImportProjects|Select a destination namespace.') }}
</p>
</template>
<template v-else-if="repo.importedProject">{{ displayFullPath }}</template>
</div>
@ -264,9 +293,11 @@ export default {
<gl-modal
v-if="showMembershipsWarning"
v-model="showMembershipsModal"
modal-id="show-memberships-modal"
:title="
s__('ImportProjects|Are you sure you want to import the project to a personal namespace?')
"
data-testid="memberships-warning-modal"
:action-primary="$options.actionPrimary"
:action-cancel="$options.actionCancel"
@primary="handleImportRepo"

View File

@ -19,6 +19,6 @@ export const getImportTarget = (state) => (repoId) => {
return {
newName: repo.importSource.sanitizedName,
targetNamespace: state.defaultTargetNamespace,
targetNamespace: null,
};
};

View File

@ -831,3 +831,40 @@ export function stripRelativeUrlRootFromPath(path) {
return joinPaths('/', path.substring(relativeUrlRoot.length));
}
const LINE_RANGE_HASH_REGEX = /^#L(\d+)(?:-(\d+))?$/;
/**
* Retrieves the line number range from the url hash if it exists.
*
* @param {string} [hash=window.location.hash] - The URL hash string to parse. Defaults to the current window's location hash.
*
* @returns {{beginning: number, end: number}| null} An object containing the line number range selected,
* otherwise returns null
*/
export const getLineRangeFromHash = (hash = window.location.hash) => {
const match = hash.match(LINE_RANGE_HASH_REGEX);
if (!match || !match[1]) return null;
const beginning = parseInt(match[1], 10);
// If there's a second number (end of range), use it; otherwise use the start number
const end = match[2] ? parseInt(match[2], 10) : beginning;
return { beginning, end };
};
/**
* Appends the current window's line reference hash to a URL if it exists.
*
* @param {string} url - The base URL to which the line reference should be appended
* @param {string} [hash=window.location.hash] - The hash string to check and potentially append. Defaults to the current window's location hash.
* @returns {string} The URL with the line reference hash appended if the current window's
* hash matches the line reference pattern (#L<number> or #L<number>-<number>),
* otherwise returns the original URL unchanged
*/
export function appendLineRangeHashToUrl(url, hash = window.location.hash) {
if (LINE_RANGE_HASH_REGEX.test(hash)) {
return url + hash;
}
return url;
}

View File

@ -6,7 +6,7 @@ import {
GlTooltipDirective,
} from '@gitlab/ui';
import { s__, __ } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility';
import { visitUrl, appendLineRangeHashToUrl } from '~/lib/utils/url_utility';
import Tracking from '~/tracking';
import ConfirmForkModal from '~/vue_shared/components/web_ide/confirm_fork_modal.vue';
import { keysFor, GO_TO_PROJECT_WEBIDE } from '~/behaviors/shortcuts/keybindings';
@ -233,7 +233,8 @@ export default {
}
: {
handle: () => {
visitUrl(this.webIdeUrl, true);
const url = appendLineRangeHashToUrl(this.webIdeUrl);
visitUrl(url, true);
},
};

View File

@ -3,7 +3,7 @@
- extra_data = local_assigns.fetch(:extra_data, {})
- filterable = local_assigns.fetch(:filterable, true)
- paginatable = local_assigns.fetch(:paginatable, false)
- default_namespace_path = (local_assigns[:default_namespace] || current_user.namespace).full_path
- default_namespace_path = local_assigns[:default_namespace]&.full_path
- cancel_path = local_assigns.fetch(:cancel_path, nil)
- details_path = local_assigns.fetch(:details_path, nil)
- provider_title = Gitlab::ImportSources.title(local_assigns.fetch(:provider))

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddSchemaVersionToZoektNode < Gitlab::Database::Migration[2.3]
milestone '18.1'
def change
add_column :zoekt_nodes, :schema_version, :smallint, null: false, default: 0
end
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddSchemaVersionToZoektRepository < Gitlab::Database::Migration[2.3]
milestone '18.1'
def change
add_column :zoekt_repositories, :schema_version, :smallint, null: false, default: 0
end
end

View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
class AddIndexForPCiPipelineVariablesOnProjectId < Gitlab::Database::Migration[2.3]
include Gitlab::Database::PartitioningMigrationHelpers
disable_ddl_transaction!
milestone '18.1'
TABLE_NAME = :p_ci_pipeline_variables
INDEX_NAME = :index_p_ci_pipeline_variables_on_project_id
COLUMN_NAME = :project_id
def up
add_concurrent_partitioned_index(TABLE_NAME, COLUMN_NAME, name: INDEX_NAME)
end
def down
remove_concurrent_partitioned_index_by_name(TABLE_NAME, INDEX_NAME)
end
end

View File

@ -0,0 +1 @@
c245a850227686ec455e5da05a62e72c37df499286f245211f1f54269c304e85

View File

@ -0,0 +1 @@
66a16305b024955bbc525a03118280c7986218cfbadfdd6938f28ca614d72fb2

View File

@ -0,0 +1 @@
695693b64127b2e75eb3e038a78dc172735819232a7907a61d965418b4a370d8

View File

@ -26366,6 +26366,7 @@ CREATE TABLE zoekt_nodes (
indexed_bytes bigint DEFAULT 0 NOT NULL,
usable_storage_bytes bigint DEFAULT 0 NOT NULL,
usable_storage_bytes_locked_until timestamp with time zone,
schema_version smallint DEFAULT 0 NOT NULL,
CONSTRAINT check_32f39efba3 CHECK ((char_length(search_base_url) <= 1024)),
CONSTRAINT check_38c354a3c2 CHECK ((char_length(index_base_url) <= 1024))
);
@ -26409,6 +26410,7 @@ CREATE TABLE zoekt_repositories (
size_bytes bigint DEFAULT 0 NOT NULL,
index_file_count integer DEFAULT 0 NOT NULL,
retries_left smallint DEFAULT 10 NOT NULL,
schema_version smallint DEFAULT 0 NOT NULL,
CONSTRAINT c_zoekt_repositories_on_project_id_and_project_identifier CHECK (((project_id IS NULL) OR (project_identifier = project_id))),
CONSTRAINT c_zoekt_repositories_on_retries_left CHECK (((retries_left > 0) OR ((retries_left = 0) AND (state >= 200))))
);
@ -36541,6 +36543,8 @@ CREATE INDEX index_p_ci_job_annotations_on_project_id ON ONLY p_ci_job_annotatio
CREATE INDEX index_p_ci_job_artifact_reports_on_project_id ON ONLY p_ci_job_artifact_reports USING btree (project_id);
CREATE INDEX index_p_ci_pipeline_variables_on_project_id ON ONLY p_ci_pipeline_variables USING btree (project_id);
CREATE INDEX index_p_ci_pipelines_config_on_project_id ON ONLY p_ci_pipelines_config USING btree (project_id);
CREATE INDEX index_p_ci_runner_machine_builds_on_project_id ON ONLY p_ci_runner_machine_builds USING btree (project_id);

View File

@ -27,16 +27,40 @@ For larger GitLab instances, alternative backup strategies include:
## Data included in a backup
GitLab provides a command-line interface to back up your entire instance.
By default, the backup creates an archive in a single compressed tar file.
This file includes:
- Database data and configuration
- Git repositories, container registry images, and uploaded content
- Package registry data and CI/CD artifacts
- Account and group settings
- Project and group wikis
- Project-level secure files
- External merge request diffs
- CI/CD artifacts and job logs
- Git repositories and LFS objects
- External merge request diffs ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154914) in GitLab 17.1)
- Package registry data and container registry images
- Project and [group](../../user/project/wiki/group.md) wikis.
- Project-level attachments and uploads
- Secure Files ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121142) in GitLab 16.1)
- GitLab Pages content
- Terraform states
- Snippets
## Data not included in a backup
- [Mattermost data](../../integration/mattermost/_index.md#back-up-gitlab-mattermost)
- Redis (and thus Sidekiq jobs)
- [Object storage](#object-storage) on Linux package (Omnibus) / Docker / Self-compiled installations
- [Global server hooks](../server_hooks.md#create-global-server-hooks-for-all-repositories)
- [File hooks](../file_hooks.md)
- GitLab configuration files (`/etc/gitlab`)
- TLS- and SSH-related keys and certificates
- Other system files
{{< alert type="warning" >}}
You are highly advised to read about [storing configuration files](#storing-configuration-files) to back up those separately.
{{< /alert >}}
## Simple backup procedure
@ -196,41 +220,6 @@ GitLab uses Redis both as a cache store and to hold persistent data for our back
Elasticsearch is an optional database for advanced search. It can improve search
in both source-code level, and user generated content in issues, merge requests, and discussions. The [backup command](#backup-command) does _not_ back up Elasticsearch data. Elasticsearch data can be regenerated from PostgreSQL data after a restore. It is possible to [manually back up Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.html).
## Command-line interface
GitLab provides a command-line interface to back up your entire instance,
including:
- Database
- Attachments
- Git repositories data
- CI/CD job output logs
- CI/CD job artifacts
- LFS objects
- Terraform states
- Container registry images
- GitLab Pages content
- Packages
- Snippets
- [Group wikis](../../user/project/wiki/group.md)
- Project-level Secure Files ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121142) in GitLab 16.1)
- External merge request diffs ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154914) in GitLab 17.1)
Backups do not include:
- [Mattermost data](../../integration/mattermost/_index.md#back-up-gitlab-mattermost)
- Redis (and thus Sidekiq jobs)
- [Object storage](#object-storage) on Linux package (Omnibus) / Docker / Self-compiled installations
- [Global server hooks](../server_hooks.md#create-global-server-hooks-for-all-repositories)
- [File hooks](../file_hooks.md)
{{< alert type="warning" >}}
GitLab does not back up any configuration files (`/etc/gitlab`), TLS keys and certificates, or system
files. You are highly advised to read about [storing configuration files](#storing-configuration-files).
{{< /alert >}}
### Requirements
To be able to back up and restore, ensure that Rsync is installed on your
@ -815,7 +804,7 @@ You can back up specific repositories using the `REPOSITORIES_PATHS` option.
Similarly, you can use `SKIP_REPOSITORIES_PATHS` to skip certain repositories.
Both options accept a comma-separated list of project or group paths. If you
specify a group path, all repositories in all projects in the group and
descendent groups are included or skipped, depending on which option you used.
descendant groups are included or skipped, depending on which option you used.
For example, to back up all repositories for all projects in Group A (`group-a`), the repository for
Project C in Group B (`group-b/project-c`),

View File

@ -65,10 +65,9 @@ Restore:
### Certain GitLab configuration must match the original backed up environment
You likely also want to restore your previous `/etc/gitlab/gitlab.rb` (for Linux package installations)
You likely want to separately restore your previous `/etc/gitlab/gitlab.rb` (for Linux package installations)
or `/home/git/gitlab/config/gitlab.yml` (for self-compiled installations) and
any TLS keys, certificates (`/etc/gitlab/ssl`, `/etc/gitlab/trusted-certs`), or
[SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
[any TLS or SSH keys and certificates](backup_gitlab.md#data-not-included-in-a-backup).
Certain configuration is coupled to data in PostgreSQL. For example:
@ -453,7 +452,7 @@ that can cause data loss. The problem affects repositories that have been forked
You can restore specific repositories using the `REPOSITORIES_PATHS` and the `SKIP_REPOSITORIES_PATHS` options.
Both options accept a comma-separated list of project and group paths. If you
specify a group path, all repositories in all projects in the group and
descendent groups are included or skipped, depending on which option you used.
descendant groups are included or skipped, depending on which option you used.
Both the groups and projects must exist in the specified backup or on the target instance.
{{< alert type="note" >}}

View File

@ -448,7 +448,7 @@ curl --request DELETE \
## Instance-wide endpoints
Beside the group- and project-specific GitLab APIs explained above,
Beside the group- and project-specific GitLab APIs explained previously,
the container registry has its own endpoints.
To query those, follow the Registry's built-in mechanism to obtain and use an
[authentication token](https://distribution.github.io/distribution/spec/auth/token/).

View File

@ -99,7 +99,7 @@ Example response:
## The `value` field
For both the project and group-level endpoints above, the `value` field in the
For both the project and group-level endpoints described previously, the `value` field in the
API response has a different meaning depending on the provided `metric` query
parameter:

View File

@ -134,7 +134,8 @@ Returns the following status codes:
Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/license/:id"
curl --header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/license/:id"
```
Example response:
@ -175,7 +176,9 @@ POST /license
| `license` | string | yes | The license string |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/license?license=eyJkYXRhIjoiMHM5Q...S01Udz09XG4ifQ=="
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/license?license=eyJkYXRhIjoiMHM5Q...S01Udz09XG4ifQ=="
```
Example response:
@ -221,7 +224,9 @@ DELETE /license/:id
| `id` | integer | yes | ID of the GitLab license. |
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/license/:id"
curl --request DELETE \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/license/:id"
```
Returns:
@ -241,7 +246,9 @@ PUT /license/:id/refresh_billable_users
| `id` | integer | yes | ID of the GitLab license. |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/license/:id/refresh_billable_users"
curl --request PUT \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/license/:id/refresh_billable_users"
```
Example response:
@ -271,7 +278,9 @@ GET /license/usage_export.csv
```
```shell
curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/license/usage_export.csv"
curl --request GET \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/license/usage_export.csv"
```
Example response:

View File

@ -116,7 +116,7 @@ curl --request POST "https://gitlab.com/api/v4/projects/:id/snippets" \
-d @snippet.json
```
`snippet.json` used in the above example request:
`snippet.json` used in the previous example request:
```json
{
@ -168,7 +168,7 @@ curl --request PUT "https://gitlab.com/api/v4/projects/:id/snippets/:snippet_id"
-d @snippet.json
```
`snippet.json` used in the above example request:
`snippet.json` used in the previous example request:
```json
{

View File

@ -245,7 +245,7 @@ curl --request POST "https://gitlab.example.com/api/v4/snippets" \
-d @snippet.json
```
`snippet.json` used in the above example request:
`snippet.json` used in the previous example request:
```json
{
@ -336,7 +336,7 @@ curl --request PUT "https://gitlab.example.com/api/v4/snippets/1" \
-d @snippet.json
```
`snippet.json` used in the above example request:
`snippet.json` used in the previous example request:
```json
{

View File

@ -891,17 +891,15 @@ use three periods with no space (`...`) instead of the `&hellip;` HTML entity or
For more information, see [code blocks](_index.md#code-blocks).
Do not include any ellipses when documenting UI text.
For more information, see the [Microsoft Style Guide](https://learn.microsoft.com/en-us/style-guide/punctuation/ellipses).
Use:
Do not include any ellipses when documenting UI text. For example, use:
- **Create new**
- **Search or go to**
Instead of:
- **Create new...**
- **Search or go to...**
## email

View File

@ -363,7 +363,7 @@ curl --request POST \
{{< alert type="warning" >}}
Using your authorization key in the URL is insecure, as it's visible in server logs. We recommend
using one of the above header options if your tooling supports it.
using one of the header options described previously if your tooling supports it.
{{< /alert >}}

View File

@ -357,7 +357,7 @@ To purchase additional storage for your group on GitLab.com:
After your payment is processed, the extra storage is available for your group namespace.
To confirm the available storage, follow the first three steps listed above.
To confirm the available storage, follow the first three steps listed previously.
The **Purchased storage available** total is incremented by the amount purchased. All locked
projects are unlocked and their excess usage is deducted from the additional storage.

View File

@ -35,7 +35,7 @@ The Value Streams Dashboard includes panels that visualize the following metrics
With the Value Streams Dashboard, you can:
- Track and compare the above metrics over a period of time.
- Track and compare the metrics listed previously over a period of time.
- Identify downward trends early on.
- Understand security exposure.
- Drill down into individual projects or metrics to take actions for improvement.

View File

@ -182,15 +182,13 @@ If the import is successful, the new compliance framework appears in the list. A
{{< /history >}}
In GitLab Ultimate, you can define specific **requirements** for a compliance framework. Requirements are made up of one or more **controls**, which are checks against the configuration or behavior of projects that are assigned the framework. There is maximum of 5 controls per requirement.
In GitLab Ultimate, you can define specific **requirements** for a compliance framework. Requirements are made up of one
or more **controls**, which are checks against the configuration or behavior of projects that are assigned the framework. There is maximum of 5 controls per requirement.
### Controls
Each control includes logic that GitLab uses during scheduled or triggered scans to evaluate a project's adherence. For
more details on how adherence is tracked, see [Compliance status report](compliance_center/compliance_status_report.md).
Each control includes logic that GitLab uses during scheduled or triggered scans to evaluate a project's adherence. For more details on how adherence is tracked, see [Compliance status report](compliance_center/compliance_status_report.md).
#### GitLab controls
The following controls are available to use in framework requirements:
You can use GitLab compliance controls or external controls for framework requirements.
### GitLab compliance controls
@ -262,7 +260,7 @@ behavior of projects that are assigned to a compliance framework.
| Terraform enabled | `terraform_enabled` | Ensures that the [Terraform integration](../../administration/terraform_state.md) is enabled for the project. |
| Vulnerabilities SLO days over threshold | `vulnerabilities_slo_days_over_threshold` | Ensures that [vulnerabilities are addressed](../application_security/vulnerabilities/_index.md) inside SLO thresholds (180 days). |
#### External controls
### External controls
External controls are API calls to external systems that request the status of an external control or requirement.

View File

@ -21,7 +21,7 @@ For help developing custom feature flags, see
<div class="d-none">
<strong>If you don't see the feature flag tables below, view them at <a href="https://docs.gitlab.com/ee/user/feature_flags.html">docs.gitlab.com</a>.</strong>
</div>
<!-- the div above will not display on the docs site but will display on /help -->
<!-- the div tag will not display on the docs site but will display on /help -->
<!-- markdownlint-enable MD044 -->

View File

@ -94,7 +94,7 @@ To configure GitLab CI/CD as a backend:
`gitlab-tofu plan` commands.
1. Trigger the manual `deploy` job from the previous pipeline. This action runs the `gitlab-tofu apply` command, which provisions the defined infrastructure.
The output from the above commands should be viewable in the job logs.
The output from the previous commands should be viewable in the job logs.
The `gitlab-tofu` CLI is a wrapper around the `tofu` CLI.

View File

@ -860,10 +860,7 @@ URL references like `https://gitlab.com/gitlab-org/gitlab/-/issues/1234+s` are a
To update the rendered references if the assignee, milestone, or health status changed:
- Edit the comment or description and save it.
Issue [420807](https://gitlab.com/gitlab-org/gitlab/-/issues/420807) tracks improving how these
references refresh.
- Refresh the page.
### Comment preview on hover

View File

@ -32008,6 +32008,12 @@ msgstr ""
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
msgid "ImportProjects|Select a destination namespace."
msgstr ""
msgid "ImportProjects|Select namespace"
msgstr ""
msgid "ImportProjects|Select the repositories you want to import"
msgstr ""

View File

@ -73,7 +73,7 @@
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
"@rails/actioncable": "7.1.501",
"@rails/ujs": "7.1.501",
"@sentry/browser": "9.19.0",
"@sentry/browser": "9.22.0",
"@snowplow/browser-plugin-client-hints": "^3.24.2",
"@snowplow/browser-plugin-form-tracking": "^3.24.2",
"@snowplow/browser-plugin-ga-cookies": "^3.24.2",
@ -157,7 +157,7 @@
"graphiql": "^3.7.1",
"graphql": "16.11.0",
"graphql-tag": "^2.11.0",
"gridstack": "^11.1.2",
"gridstack": "^12.1.2",
"highlight.js": "^11.11.1",
"highlightjs-glimmer": "^2.2.2",
"immer": "^9.0.15",

View File

@ -34,7 +34,6 @@ RSpec.describe 'Import multiple repositories by uploading a manifest file', :js,
page.within(second_row) do
click_on 'Import'
end
click_on 'Continue import'
wait_for_requests

View File

@ -31,6 +31,8 @@ const TEST_BRANCH_NAME = '12345-foo-patch';
const TEST_USER_PREFERENCES_PATH = '/user/preferences';
const TEST_GITLAB_WEB_IDE_PUBLIC_PATH = 'test/webpack/assets/gitlab-web-ide/public/path';
const TEST_FILE_PATH = 'foo/README.md';
const TEST_LINE_NUMBER = { beginning: 42, end: 42 };
const TEST_LINE_RANGE = { beginning: 42, end: 46 };
const TEST_MR_ID = '7';
const TEST_MR_TARGET_PROJECT = 'gitlab-org/the-real-gitlab';
const TEST_SIGN_IN_PATH = 'sign-in';
@ -124,6 +126,7 @@ describe('ide/init_gitlab_web_ide', () => {
projectPath: TEST_PROJECT_PATH,
ref: TEST_BRANCH_NAME,
filePath: TEST_FILE_PATH,
lineRange: null,
mrId: TEST_MR_ID,
mrTargetProject: '',
forkInfo: null,
@ -193,6 +196,39 @@ describe('ide/init_gitlab_web_ide', () => {
});
});
describe('when URL has lineNumber in hash', () => {
beforeEach(() => {
setWindowLocation(`https://example.com/-/ide/path/to/file#L42`);
createSubject();
});
it('includes line number', () => {
expect(start).toHaveBeenCalledWith(
findRootElement(),
expect.objectContaining({
lineRange: TEST_LINE_NUMBER,
}),
);
});
});
describe('when URL has lineRange in hash', () => {
beforeEach(() => {
setWindowLocation(`https://example.com/-/ide/path/to/file#L42-46`);
createSubject();
});
it('includes line range', () => {
expect(start).toHaveBeenCalledWith(
findRootElement(),
expect.objectContaining({
lineRange: TEST_LINE_RANGE,
}),
);
});
});
describe('when forkInfo is in dataset', () => {
beforeEach(() => {
findRootElement().dataset.forkInfo = JSON.stringify(TEST_FORK_INFO);

View File

@ -1,4 +1,4 @@
import { GlBadge, GlButton, GlModal } from '@gitlab/ui';
import { GlBadge, GlButton } from '@gitlab/ui';
import Vue, { nextTick } from 'vue';
// eslint-disable-next-line no-restricted-imports
import Vuex from 'vuex';
@ -15,7 +15,7 @@ describe('ProviderRepoTableRow', () => {
const cancelImport = jest.fn();
const setImportTarget = jest.fn();
const groupImportTarget = {
targetNamespace: 'target',
targetNamespace: null,
newName: 'newName',
};
@ -45,7 +45,8 @@ describe('ProviderRepoTableRow', () => {
const findImportStatus = () => wrapper.findComponent(ImportStatus);
const findProviderLink = () => wrapper.findByTestId('provider-link');
const findMembershipsWarning = () => wrapper.findByTestId('memberships-warning');
const findGlModal = () => wrapper.findComponent(GlModal);
const findMembershipsWarningModal = () => wrapper.findByTestId('memberships-warning-modal');
const findNamespaceRequiredWarning = () => wrapper.findByTestId('namespace-required-warning');
const findCancelButton = () => {
const buttons = wrapper
@ -97,12 +98,37 @@ describe('ProviderRepoTableRow', () => {
expect(findImportTargetDropdown().exists()).toBe(true);
});
it('renders the dropdown without a default selected', () => {
expect(findImportTargetDropdown().props('selected')).toBe(null);
expect(findImportTargetDropdown().props().toggleText).toBe('Select namespace');
});
describe('when no namespace is selected', () => {
it('shows namespace required warning when import button is clicked', async () => {
findImportButton().vm.$emit('click');
await nextTick();
expect(findNamespaceRequiredWarning().text()).toBe('Select a destination namespace.');
});
it('does not trigger import when clicking import button', async () => {
findImportButton().vm.$emit('click');
await nextTick();
expect(fetchImport).not.toHaveBeenCalled();
});
});
describe('when user namespace is selected as import target', () => {
beforeEach(() => {
beforeEach(async () => {
mountComponent(
{ repo },
{ storeOptions: { importTarget: { targetNamespace: userNamespace } } },
);
const dropdown = findImportTargetDropdown();
dropdown.vm.$emit('select', userNamespace);
await nextTick();
});
it('shows memberships warning', () => {
@ -113,7 +139,7 @@ describe('ProviderRepoTableRow', () => {
findImportButton().vm.$emit('click');
await nextTick();
const modal = findGlModal();
const modal = findMembershipsWarningModal();
expect(modal.props('title')).toBe(
'Are you sure you want to import the project to a personal namespace?',
);
@ -122,11 +148,15 @@ describe('ProviderRepoTableRow', () => {
);
});
it('does not show `missing namespace` warning', () => {
expect(findNamespaceRequiredWarning().exists()).toBe(false);
});
it('triggers import when clicking modal primary button', async () => {
findImportButton().vm.$emit('click');
await nextTick();
findGlModal().vm.$emit('primary');
findMembershipsWarningModal().vm.$emit('primary');
expect(fetchImport).toHaveBeenCalledWith(expect.anything(), {
repoId: repo.importSource.id,
@ -136,53 +166,68 @@ describe('ProviderRepoTableRow', () => {
});
describe('when group namespace is selected as import target', () => {
beforeEach(async () => {
const dropdown = findImportTargetDropdown();
dropdown.vm.$emit('select', 'target');
await nextTick();
});
it('does not show memberships warning', () => {
expect(findMembershipsWarning().isVisible()).toBe(false);
});
it('does not show modal when import button is clicked', async () => {
it('does not show memberships modal when import button is clicked', async () => {
findImportButton().vm.$emit('click');
await nextTick();
expect(findGlModal().exists()).toBe(false);
});
});
it('renders import button', () => {
expect(findImportButton().exists()).toBe(true);
});
it('imports repo when clicking import button', async () => {
findImportButton().vm.$emit('click');
await nextTick();
expect(fetchImport).toHaveBeenCalledWith(expect.anything(), {
repoId: repo.importSource.id,
optionalStages: {},
});
});
it('includes optionalStages to import', async () => {
const OPTIONAL_STAGES = { stage1: true, stage2: false };
mountComponent({
repo,
optionalStages: OPTIONAL_STAGES,
expect(findMembershipsWarningModal().exists()).toBe(false);
});
findImportButton().vm.$emit('click');
await nextTick();
expect(fetchImport).toHaveBeenCalledWith(expect.anything(), {
repoId: repo.importSource.id,
optionalStages: OPTIONAL_STAGES,
it('does not show `missing namespace` warning when import button is clicked', async () => {
findImportButton().vm.$emit('click');
await nextTick();
expect(findNamespaceRequiredWarning().exists()).toBe(false);
});
});
it('does not render re-import button', () => {
expect(findReimportButton().exists()).toBe(false);
it('renders import button', () => {
expect(findImportButton().exists()).toBe(true);
});
it('imports repo when clicking import button', async () => {
findImportButton().vm.$emit('click');
await nextTick();
expect(fetchImport).toHaveBeenCalledWith(expect.anything(), {
repoId: repo.importSource.id,
optionalStages: {},
});
});
it('includes optionalStages to import', async () => {
const OPTIONAL_STAGES = { stage1: true, stage2: false };
mountComponent({
repo,
optionalStages: OPTIONAL_STAGES,
});
const dropdown = findImportTargetDropdown();
dropdown.vm.$emit('select', 'target');
await nextTick();
findImportButton().vm.$emit('click');
await nextTick();
expect(fetchImport).toHaveBeenCalledWith(expect.anything(), {
repoId: repo.importSource.id,
optionalStages: OPTIONAL_STAGES,
});
});
it('does not render re-import button', () => {
expect(findReimportButton().exists()).toBe(false);
});
});
});
@ -290,7 +335,12 @@ describe('ProviderRepoTableRow', () => {
await nextTick();
findImportTargetDropdown().vm.$emit('select', 'some-namespace');
await nextTick();
findReimportButton().vm.$emit('click');
await nextTick();
expect(findNamespaceRequiredWarning().exists()).toBe(false);
expect(fetchImport).toHaveBeenCalledWith(expect.anything(), {
repoId: repo.importSource.id,

View File

@ -55,7 +55,7 @@ describe('import_projects store actions', () => {
let localState;
const importRepoId = 1;
const otherImportRepoId = 2;
const defaultTargetNamespace = 'default';
const defaultTargetNamespace = null;
const sanitizedName = 'sanitizedName';
const defaultImportTarget = { newName: sanitizedName, targetNamespace: defaultTargetNamespace };

View File

@ -99,7 +99,7 @@ describe('import_projects store getters', () => {
expect(getImportTarget(localState)(IMPORTABLE_REPO.importSource.id)).toStrictEqual({
newName: IMPORTABLE_REPO.importSource.sanitizedName,
targetNamespace: localState.defaultTargetNamespace,
targetNamespace: null,
});
});

View File

@ -2,7 +2,11 @@ import setWindowLocation from 'helpers/set_window_location_helper';
import { TEST_HOST } from 'helpers/test_constants';
import * as urlUtils from '~/lib/utils/url_utility';
import { setGlobalAlerts } from '~/lib/utils/global_alerts';
import { setLocationHash } from '~/lib/utils/url_utility';
import {
appendLineRangeHashToUrl,
getLineRangeFromHash,
setLocationHash,
} from '~/lib/utils/url_utility';
import { validURLs, invalidURLs } from './mock_data';
jest.mock('~/lib/utils/global_alerts', () => ({
@ -476,6 +480,61 @@ describe('URL utility', () => {
});
});
describe('getLineRangeFromHash', () => {
beforeEach(() => {
window.location.hash = '';
});
it('returns null when no line number hash is present', () => {
expect(getLineRangeFromHash()).toBe(null);
});
it('returns line number when hash is present in URL', () => {
window.location.hash = '#L42';
expect(getLineRangeFromHash()).toStrictEqual({ beginning: 42, end: 42 });
});
it('returns line number range when hash is present in URL', () => {
window.location.hash = '#L10-42';
expect(getLineRangeFromHash()).toStrictEqual({ beginning: 10, end: 42 });
});
it('returns null when hash is not a line number', () => {
window.location.hash = '#L42InvalidHash123';
expect(getLineRangeFromHash()).toBe(null);
});
});
describe('appendLineRangeHashToUrl', () => {
beforeEach(() => {
window.location.hash = '';
});
it('appends line number hash when present in URL', () => {
window.location.hash = '#L42';
expect(appendLineRangeHashToUrl('https://example.com/ide')).toBe(
'https://example.com/ide#L42',
);
});
it('appends line number range hash when present in URL', () => {
window.location.hash = '#L10-42';
expect(appendLineRangeHashToUrl('https://example.com/ide')).toBe(
'https://example.com/ide#L10-42',
);
});
it('returns original URL when no line number hash is present', () => {
window.location.hash = '#something-else';
expect(appendLineRangeHashToUrl('https://example.com/ide')).toBe('https://example.com/ide');
});
it('returns original URL when hash is not a line number', () => {
window.location.hash = '#L42InvalidHash123';
expect(appendLineRangeHashToUrl('https://example.com/ide')).toBe('https://example.com/ide');
});
});
describe('visitUrl', () => {
let originalLocation;
const mockUrl = 'http://example.com/page';

View File

@ -16,7 +16,7 @@ import {
extendedWrapper,
} from 'helpers/vue_test_utils_helper';
import { visitUrl } from '~/lib/utils/url_utility';
import { visitUrl, appendLineRangeHashToUrl } from '~/lib/utils/url_utility';
import getWritableForksQuery from '~/vue_shared/components/web_ide/get_writable_forks.query.graphql';
jest.mock('~/lib/utils/url_utility');
@ -299,9 +299,12 @@ describe('vue_shared/components/web_ide_link', () => {
});
it('when web ide button is clicked it opens in a new tab', async () => {
const transformation = 'foo';
appendLineRangeHashToUrl.mockReturnValueOnce(transformation);
findDisclosureDropdownItems().at(1).props().item.handle();
await nextTick();
expect(visitUrl).toHaveBeenCalledWith(TEST_WEB_IDE_URL, true);
expect(appendLineRangeHashToUrl).toHaveBeenCalledWith(TEST_WEB_IDE_URL);
expect(visitUrl).toHaveBeenCalledWith(transformation, true);
});
});

View File

@ -498,6 +498,200 @@ RSpec.describe 'Internal Events matchers', :clean_gitlab_redis_shared_state, fea
.and change { user_1.reload.updated_at }
.and not_change { User.count }
end
describe 'instrumentation and testing contexts' do
shared_examples 'works correctly' do
specify do
expect { subject }
.to trigger_internal_events('g_edit_by_sfe')
.and increment_usage_metrics('redis_hll_counters.ide_edit.g_edit_by_sfe_weekly')
end
end
subject { track_event }
context 'with retries', retry: 2 do
context "with independent failure after the event" do
subject do
track_event
raise 'Fail first attempt, causing a retry' if RSpec.current_example.attempts == 0
end
it_behaves_like "works correctly"
end
context "with independent failure before the event" do
subject do
raise 'Fail first attempt, causing a retry' if RSpec.current_example.attempts == 0
track_event
end
it_behaves_like "works correctly"
end
context "with criteria met only on retry" do
subject do
track_event if RSpec.current_example.attempts > 0
end
it_behaves_like "works correctly"
end
end
context 'without clearing Redis state between examples', clean_gitlab_redis_shared_state: false do
it_behaves_like "works correctly"
end
context 'with snowplow not stubbed by default', :do_not_stub_snowplow_by_default do
it_behaves_like "works correctly"
end
context 'with aggregate_failures', :aggregate_failures do
context "with no failures" do
it_behaves_like "works correctly"
end
context "with failures" do
it "fails" do
pending('This example should always fail. Protects against false positives.')
# we can't test the error message because :aggregate_failures rescues errors
expect { nil }.to(trigger_internal_events('g_edit_by_sfe'))
expect { nil }.to(increment_usage_metrics('redis_hll_counters.ide_edit.g_edit_by_sfe_weekly'))
end
end
end
context 'when triggered from controllers' do
context 'when using controller specs', type: :controller do
controller(BaseActionController) do
include ProductAnalyticsTracking
track_internal_event :index, name: 'g_edit_by_sfe'
def index
render html: 'index page'
end
private
def tracking_project_source; end
def tracking_namespace_source; end
end
subject do
sign_in user_1
get :index
end
it_behaves_like "works correctly"
end
context 'when triggered from request specs', type: :request do
# ideally, this spec should be completed with a new controller generated inside the test
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user, maintainer_of: project) }
subject do
sign_in(user)
post namespace_project_create_blob_path(
namespace_id: project.namespace,
project_id: project,
id: 'master'
), params: {
branch_name: 'master',
file_name: 'docs/EXAMPLE_FILE',
content: 'Added changes',
commit_message: 'Create CHANGELOG'
}
end
it_behaves_like "works correctly"
end
context 'when triggered from rails model lifecycle hooks' do
let(:test_model) do
Class.new(ApplicationRecord) do
self.table_name = :merge_requests
after_initialize do
Gitlab::InternalEvents.track_event(
'create_merge_request',
user: user,
project: project
)
end
attr_accessor :user, :project
end
end
it 'works correctly' do
expect { test_model.new(user: user_1, project: project_1) }
.to trigger_internal_events('create_merge_request')
.with(user: user_1, project: project_1)
.and increment_usage_metrics('counts.merge_request_create')
end
end
context 'when triggered from sidekiq worker', :sidekiq_inline do
let(:test_worker) do
Class.new do
# `include ApplicationWorker` raises errors for unnamed classes
def self.name
'Gitlab::TestUsageWorker'
end
include ApplicationWorker
def perform(event, user_id, namespace_id)
Gitlab::InternalEvents.track_event(
event,
user: User.find(user_id),
namespace: Group.find(namespace_id)
)
end
end
end
subject do
stub_const('Gitlab::TestUsageWorker', test_worker)
test_worker.perform_async(
'g_edit_by_sfe',
user_1.id,
group_1.id
)
end
it_behaves_like "works correctly"
end
context 'when triggered from migrations' do
let(:migration) do
Class.new(Gitlab::Database::Migration[Gitlab::Database::Migration.current_version]) do
milestone '18.0'
@_defining_file = 'db/migrate/00000000000000_example.rb'
def up
Gitlab::InternalEvents.track_event(
'g_edit_by_sfe',
user: User.first,
namespace: Group.first
)
end
end
end
subject { migration.new.up }
it_behaves_like "works correctly"
end
end
end
end
context "when using the 'internal event tracking' shared example" do

View File

@ -153,7 +153,6 @@ module.exports = function storybookWebpackConfig({ config }) {
);
config.resolve.alias = {
...config.resolve.alias,
gridstack: require.resolve('gridstack/dist/es5/gridstack.js'),
'@cubejs-client/core': require.resolve('@cubejs-client/core/dist/cubejs-client-core.js'),
uuid: require.resolve('uuid'),
'/assets': path.resolve(__dirname, '../../app/assets'),

View File

@ -2591,51 +2591,51 @@
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==
"@sentry-internal/browser-utils@9.19.0":
version "9.19.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.19.0.tgz#b7df4f1de6e467e62f255967e441de68b5db5c2f"
integrity sha512-DlEHX4eIHe5yIuh/cFu9OiaFuk1CTnFK95zj61I7Q2fxmN43dIwC3xAAGJ/Hy+GDQi7kU+BiS2sudSHSTq81BA==
"@sentry-internal/browser-utils@9.22.0":
version "9.22.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.22.0.tgz#dd05ac2ed925b70a0ca9bdec472f2566761dad91"
integrity sha512-Ou1tBnVxFAIn8i9gvrWzRotNJQYiu3awNXpsFCw6qFwmiKAVPa6b13vCdolhXnrIiuR77jY1LQnKh9hXpoRzsg==
dependencies:
"@sentry/core" "9.19.0"
"@sentry/core" "9.22.0"
"@sentry-internal/feedback@9.19.0":
version "9.19.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.19.0.tgz#a3bf7a7a14d615eb3b8130a97b2c077767a54b27"
integrity sha512-yixRrv4NfpjhFW56AuUTjVwZlignB9FWAXXyrmRP3SsFeJCFrAsSD8HOxV9RXNr9ePYl7MEU0Agi43YWhJsiAw==
"@sentry-internal/feedback@9.22.0":
version "9.22.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.22.0.tgz#760f86903fde91a840bc77fc104b39a873301983"
integrity sha512-zgMVkoC61fgi41zLcSZA59vOtKxcLrKBo1ECYhPD1hxEaneNqY5fhXDwlQBw96P5l2yqkgfX6YZtSdU4ejI9yA==
dependencies:
"@sentry/core" "9.19.0"
"@sentry/core" "9.22.0"
"@sentry-internal/replay-canvas@9.19.0":
version "9.19.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.19.0.tgz#0f830ebadb7c49a3fb04457f1510aa7972445780"
integrity sha512-YC8yrOjuKSfQgGniJnzkdbFsWEPTlNpzeeYPTxS4ouH1FwfGrSkPmcddjor2YHaLfiuHHqQ/Vvq70n+zruJH7A==
"@sentry-internal/replay-canvas@9.22.0":
version "9.22.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.22.0.tgz#431e289a5db247265e640a1e7aecf9ff2dba6a70"
integrity sha512-EcG9IMSEalFe49kowBTJObWjof/iHteDwpyuAszsFDdQUYATrVUtwpwN7o52vDYWJud4arhjrQnMamIGxa79eQ==
dependencies:
"@sentry-internal/replay" "9.19.0"
"@sentry/core" "9.19.0"
"@sentry-internal/replay" "9.22.0"
"@sentry/core" "9.22.0"
"@sentry-internal/replay@9.19.0":
version "9.19.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.19.0.tgz#a1068ba5ba8eee9cd2459081be6e11bd3469d401"
integrity sha512-i/X9brRchbAF25yjxLTI7E8eoESRPBgIyQOWoWRXXt2n51iBRTjLXSaEfGvjdN+qrMq/yd6nC1/UqJVxXHeIhA==
"@sentry-internal/replay@9.22.0":
version "9.22.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.22.0.tgz#e67ed6cee4cf481d428986e4419ee099669df9ef"
integrity sha512-9GOycoKbrclcRXfcbNV8svbmAsOS5R4wXBQmKF4pFLkmFA/lJv9kdZSNYkRvkrxdNfbMIJXP+DV9EqTZcryXig==
dependencies:
"@sentry-internal/browser-utils" "9.19.0"
"@sentry/core" "9.19.0"
"@sentry-internal/browser-utils" "9.22.0"
"@sentry/core" "9.22.0"
"@sentry/browser@9.19.0":
version "9.19.0"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.19.0.tgz#17d5e2ef30e75083c56955cdbe5c2db5deabb542"
integrity sha512-efKfPQ0yQkdIkC7qJ5TIHxnecLNENGUYl1YD/TC8yyzW2JRf/3OYo5yg1hY2rhsP5RwQShXlT7uA03ABVIkA4A==
"@sentry/browser@9.22.0":
version "9.22.0"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.22.0.tgz#6eee0c047612b35e7ab4960350a57ffcc51f76f4"
integrity sha512-3TeRm74dvX0JdjX0AgkQa+22iUHwHnY+Q6M05NZ+tDeCNHGK/mEBTeqquS1oQX67jWyuvYmG3VV6RJUxtG9Paw==
dependencies:
"@sentry-internal/browser-utils" "9.19.0"
"@sentry-internal/feedback" "9.19.0"
"@sentry-internal/replay" "9.19.0"
"@sentry-internal/replay-canvas" "9.19.0"
"@sentry/core" "9.19.0"
"@sentry-internal/browser-utils" "9.22.0"
"@sentry-internal/feedback" "9.22.0"
"@sentry-internal/replay" "9.22.0"
"@sentry-internal/replay-canvas" "9.22.0"
"@sentry/core" "9.22.0"
"@sentry/core@9.19.0":
version "9.19.0"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.19.0.tgz#b0c291494abd4fdefb8f77d200e381c3f7167c3f"
integrity sha512-I41rKpMJHHZb0z0Nja+Lxto6IkEEmX3uWjnECypF8Z1HIjeJB0+PXl8p/7TeaKYqw2J2GYcRTg7jQZDmvKle1w==
"@sentry/core@9.22.0":
version "9.22.0"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.22.0.tgz#b35113bcba24a6ae437c548c2cbac941302a60ef"
integrity sha512-ixvtKmPF42Y6ckGUbFlB54OWI75H2gO5UYHojO6eXFpS7xO3ZGgV/QH6wb40mWK+0w5XZ0233FuU9VpsuE6mKA==
"@sinclair/typebox@^0.27.8":
version "0.27.8"
@ -8557,10 +8557,10 @@ graphql@16.11.0:
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.11.0.tgz#96d17f66370678027fdf59b2d4c20b4efaa8a633"
integrity sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==
gridstack@^11.1.2:
version "11.1.2"
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-11.1.2.tgz#e72091e2883f7b37cbd150c218d38eebc9fc4f18"
integrity sha512-6wJ5RffnFchF63/Yhs6tcZcWxRG1EgCnxgejbQsAjQ6Qj8QqKjew73jPq5c1yCAiyEAsXxI2tOJ8lZABOAZxoQ==
gridstack@^12.1.2:
version "12.1.2"
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-12.1.2.tgz#784f6d55873bb48fa9230c1284f769c9fbf785a8"
integrity sha512-IC1mkm5xonhAnftwIxsG+B3bawxC61ciKWEvX15ExpVQPbNVN7O9aZZhM7Y/eE4JaIR8PXrdkjd12gMnwNYRLQ==
gzip-size@^6.0.0:
version "6.0.0"