From f62886ebffeda00b6972f1644097a6b9f5016453 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 13 Jul 2023 15:07:15 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .gitlab/ci/global.gitlab-ci.yml | 319 ++++++------------ .../components/comment_type_dropdown.vue | 97 +++--- .../javascripts/observability/client.js | 41 +++ .../components/observability_container.vue | 86 +++++ .../components/skeleton/index.vue | 8 +- .../observability/mock_traces.json | 147 ++++++++ .../pages/projects/tracing/index/index.js | 4 + .../tracing/components/tracing_list.vue | 14 + app/assets/javascripts/tracing/list_index.vue | 37 ++ app/assets/stylesheets/framework/common.scss | 13 + .../projects/tracing_controller.rb | 5 +- app/helpers/projects/observability_helper.rb | 13 + .../protected_ref_deploy_key_access.rb | 2 +- app/views/projects/tracing/index.html.haml | 4 + db/database_connections/ci.yaml | 5 + db/database_connections/main.yaml | 2 + .../sbom_vulnerable_component_versions.yml | 2 + .../vulnerability_advisories.yml | 2 + ...gn_key_on_vulnerable_component_versions.rb | 17 + ...gn_key_on_vulnerable_component_versions.rb | 17 + ...2241_drop_vulnerable_component_versions.rb | 22 ++ ...5142334_drop_vulnerabilities_advisories.rb | 29 ++ db/schema_migrations/20230705141703 | 1 + db/schema_migrations/20230705141733 | 1 + db/schema_migrations/20230705142241 | 1 + db/schema_migrations/20230705142334 | 1 + db/structure.sql | 75 ---- doc/administration/settings/index.md | 2 +- .../settings/security_and_compliance.md | 25 ++ .../settings/sidekiq_job_limits.md | 35 ++ .../settings/security_and_compliance.md | 28 +- .../admin_area/settings/sidekiq_job_limits.md | 38 +-- .../index.md | 2 +- doc/user/group/import/index.md | 8 +- lib/api/ml_model_packages.rb | 17 +- .../database/database_connection_info.rb | 2 + lib/gitlab/database/gitlab_schema.rb | 31 +- .../automatic_lock_writes_on_tables.rb | 19 +- .../import_export/group/import_export.yml | 9 +- .../import_export/group/relation_factory.rb | 1 - lib/gitlab/observability.rb | 9 + locale/gitlab.pot | 6 + qa/qa/page/component/note.rb | 2 +- .../merge_request/user_posts_notes_spec.rb | 4 +- .../components/comment_type_dropdown_spec.js | 40 +-- .../observability_container_spec.js | 134 ++++++++ spec/frontend/observability/skeleton_spec.js | 37 +- spec/frontend/tracing/list_index_spec.js | 37 ++ .../projects/observability_helper_spec.rb | 21 ++ .../lib/gitlab/database/gitlab_schema_spec.rb | 3 + .../automatic_lock_writes_on_tables_spec.rb | 37 ++ .../group/relation_tree_restorer_spec.rb | 37 +- spec/lib/gitlab/observability_spec.rb | 15 + .../file_transfer/group_config_spec.rb | 7 +- spec/models/issue_spec.rb | 54 +-- spec/requests/api/ml_model_packages_spec.rb | 22 +- spec/requests/api/protected_branches_spec.rb | 2 +- spec/requests/api/protected_tags_spec.rb | 2 +- .../projects/tracing_controller_spec.rb | 14 +- .../discussion_comments_shared_example.rb | 45 +-- .../gitlab/feature_categories_rake_spec.rb | 3 +- .../typo3_distribution.tar.gz | Bin 71800 -> 77071 bytes 62 files changed, 1135 insertions(+), 578 deletions(-) create mode 100644 app/assets/javascripts/observability/client.js create mode 100644 app/assets/javascripts/observability/components/observability_container.vue create mode 100644 app/assets/javascripts/observability/mock_traces.json create mode 100644 app/assets/javascripts/pages/projects/tracing/index/index.js create mode 100644 app/assets/javascripts/tracing/components/tracing_list.vue create mode 100644 app/assets/javascripts/tracing/list_index.vue create mode 100644 app/helpers/projects/observability_helper.rb create mode 100644 app/views/projects/tracing/index.html.haml rename db/docs/{ => deleted_tables}/sbom_vulnerable_component_versions.yml (75%) rename db/docs/{ => deleted_tables}/vulnerability_advisories.yml (75%) create mode 100644 db/post_migrate/20230705141703_rollback_vulnerability_advisories_foreign_key_on_vulnerable_component_versions.rb create mode 100644 db/post_migrate/20230705141733_rollback_component_version_foreign_key_on_vulnerable_component_versions.rb create mode 100644 db/post_migrate/20230705142241_drop_vulnerable_component_versions.rb create mode 100644 db/post_migrate/20230705142334_drop_vulnerabilities_advisories.rb create mode 100644 db/schema_migrations/20230705141703 create mode 100644 db/schema_migrations/20230705141733 create mode 100644 db/schema_migrations/20230705142241 create mode 100644 db/schema_migrations/20230705142334 create mode 100644 doc/administration/settings/security_and_compliance.md create mode 100644 doc/administration/settings/sidekiq_job_limits.md create mode 100644 spec/frontend/observability/observability_container_spec.js create mode 100644 spec/frontend/tracing/list_index_spec.js create mode 100644 spec/helpers/projects/observability_helper_spec.rb diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml index cb35d5ff56d..d5eaa7768ea 100644 --- a/.gitlab/ci/global.gitlab-ci.yml +++ b/.gitlab/ci/global.gitlab-ci.yml @@ -213,296 +213,165 @@ - *node-modules-cache # We don't push this cache as it's already rebuilt by `update-assets-compile-*-cache` - *storybook-node-modules-cache-push -.use-pg12: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-12-pgvector-0.4.1 +.pg-base-variables: + variables: + POSTGRES_HOST_AUTH_METHOD: trust + +.db-services: + services: &db-services + - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-${PG_VERSION}-pgvector-0.4.1 command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] alias: postgres - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.0-alpine + - name: redis:6.2-alpine + +.use-pg12: + extends: + - .pg-base-variables + - .db-services variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "12" .use-pg13: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-13-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.2-alpine + extends: + - .pg-base-variables + - .db-services variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "13" .use-pg14: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-14-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.2-alpine + extends: + - .pg-base-variables + - .db-services variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "14" .use-pg15: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-15-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.2-alpine + extends: + - .pg-base-variables + - .db-services variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "15" +.zoekt-variables: + variables: + ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 + ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 + +.zoekt-services: + services: + - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 + alias: zoekt-ci-image + +.es7-base: + extends: + - .pg-base-variables + - .zoekt-variables + services: + - !reference [.db-services, services] + - !reference [.zoekt-services, services] + - name: elasticsearch:7.17.6 + command: ["elasticsearch", "-E", "discovery.type=single-node", "-E", "xpack.security.enabled=false"] + .use-pg12-es7-ee: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-12-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.0-alpine - - name: elasticsearch:7.17.6 - command: ["elasticsearch", "-E", "discovery.type=single-node", "-E", "xpack.security.enabled=false"] - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 - alias: zoekt-ci-image + extends: .es7-base variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "12" - ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 - ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 .use-pg13-es7-ee: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-13-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.2-alpine - - name: elasticsearch:7.17.6 - command: ["elasticsearch", "-E", "discovery.type=single-node", "-E", "xpack.security.enabled=false"] - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 - alias: zoekt-ci-image + extends: .es7-base variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "13" - ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 - ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 .use-pg14-es7-ee: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-14-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.2-alpine - - name: elasticsearch:7.17.6 - command: ["elasticsearch", "-E", "discovery.type=single-node", "-E", "xpack.security.enabled=false"] - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 - alias: zoekt-ci-image + extends: .es7-base variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "14" - ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 - ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 .use-pg15-es7-ee: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-15-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.2-alpine - - name: elasticsearch:7.17.6 - command: ["elasticsearch", "-E", "discovery.type=single-node", "-E", "xpack.security.enabled=false"] - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 - alias: zoekt-ci-image + extends: .es7-base variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "15" - ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 - ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 + +.es8-base: + extends: + - .pg-base-variables + - .zoekt-variables + services: + - !reference [.db-services, services] + - !reference [.zoekt-services, services] + - name: elasticsearch:8.6.2 + variables: + ES_SETTING_DISCOVERY_TYPE: "single-node" + ES_SETTING_XPACK_SECURITY_ENABLED: "false" .use-pg13-es8-ee: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-13-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.0-alpine - - name: elasticsearch:8.6.2 - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 - alias: zoekt-ci-image + extends: .es8-base variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "13" - ES_SETTING_DISCOVERY_TYPE: "single-node" - ES_SETTING_XPACK_SECURITY_ENABLED: "false" - ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 - ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 .use-pg14-es8-ee: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-14-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.0-alpine - - name: elasticsearch:8.6.2 - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 - alias: zoekt-ci-image + extends: .es8-base variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "14" - ES_SETTING_DISCOVERY_TYPE: "single-node" - ES_SETTING_XPACK_SECURITY_ENABLED: "false" - ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 - ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 .use-pg15-es8-ee: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-15-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.0-alpine - - name: elasticsearch:8.6.2 - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 - alias: zoekt-ci-image + extends: .es8-base variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "15" - ES_SETTING_DISCOVERY_TYPE: "single-node" - ES_SETTING_XPACK_SECURITY_ENABLED: "false" - ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 - ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 + +.os1-base: + extends: + - .pg-base-variables + - .zoekt-variables + services: + - !reference [.db-services, services] + - !reference [.zoekt-services, services] + - name: opensearchproject/opensearch:1.3.5 + alias: elasticsearch + command: ["bin/opensearch", "-E", "discovery.type=single-node", "-E", "plugins.security.disabled=true"] .use-pg13-opensearch1-ee: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-13-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.0-alpine - - name: opensearchproject/opensearch:1.3.5 - alias: elasticsearch - command: ["bin/opensearch", "-E", "discovery.type=single-node", "-E", "plugins.security.disabled=true"] - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 - alias: zoekt-ci-image + extends: .os1-base variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "13" - ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 - ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 - -.use-pg13-opensearch2-ee: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-13-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.0-alpine - - name: opensearchproject/opensearch:2.2.1 - alias: elasticsearch - command: ["bin/opensearch", "-E", "discovery.type=single-node", "-E", "plugins.security.disabled=true"] - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 - alias: zoekt-ci-image - variables: - POSTGRES_HOST_AUTH_METHOD: trust - PG_VERSION: "13" - ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 - ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 .use-pg14-opensearch1-ee: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-14-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.0-alpine - - name: opensearchproject/opensearch:1.3.5 - alias: elasticsearch - command: ["bin/opensearch", "-E", "discovery.type=single-node", "-E", "plugins.security.disabled=true"] - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 - alias: zoekt-ci-image + extends: .os1-base variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "14" - ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 - ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 - -.use-pg14-opensearch2-ee: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-14-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.0-alpine - - name: opensearchproject/opensearch:2.2.1 - alias: elasticsearch - command: ["bin/opensearch", "-E", "discovery.type=single-node", "-E", "plugins.security.disabled=true"] - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 - alias: zoekt-ci-image - variables: - POSTGRES_HOST_AUTH_METHOD: trust - PG_VERSION: "14" - ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 - ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 .use-pg15-opensearch1-ee: - services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-15-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.0-alpine - - name: opensearchproject/opensearch:1.3.5 - alias: elasticsearch - command: ["bin/opensearch", "-E", "discovery.type=single-node", "-E", "plugins.security.disabled=true"] - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 - alias: zoekt-ci-image + extends: .os1-base variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "15" - ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 - ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 -.use-pg15-opensearch2-ee: +.os2-base: + extends: + - .pg-base-variables + - .zoekt-variables services: - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:postgres-15-pgvector-0.4.1 - command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off", "-c", "max_locks_per_transaction=128"] - alias: postgres - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:redis-cluster-6.2.12 - alias: rediscluster # configure connections in config/redis.yml - - name: redis:6.0-alpine + - !reference [.db-services, services] + - !reference [.zoekt-services, services] - name: opensearchproject/opensearch:2.2.1 alias: elasticsearch command: ["bin/opensearch", "-E", "discovery.type=single-node", "-E", "plugins.security.disabled=true"] - - name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:zoekt-ci-image-1.1 - alias: zoekt-ci-image + +.use-pg13-opensearch2-ee: + extends: .os2-base + variables: + PG_VERSION: "13" + +.use-pg14-opensearch2-ee: + extends: .os2-base + variables: + PG_VERSION: "14" + +.use-pg15-opensearch2-ee: + extends: .os2-base variables: - POSTGRES_HOST_AUTH_METHOD: trust PG_VERSION: "15" - ZOEKT_INDEX_BASE_URL: http://zoekt-ci-image:6060 - ZOEKT_SEARCH_BASE_URL: http://zoekt-ci-image:6070 .use-kaniko: image: diff --git a/app/assets/javascripts/notes/components/comment_type_dropdown.vue b/app/assets/javascripts/notes/components/comment_type_dropdown.vue index 543be838920..2e4f925194f 100644 --- a/app/assets/javascripts/notes/components/comment_type_dropdown.vue +++ b/app/assets/javascripts/notes/components/comment_type_dropdown.vue @@ -1,16 +1,20 @@ diff --git a/app/assets/javascripts/observability/client.js b/app/assets/javascripts/observability/client.js new file mode 100644 index 00000000000..6e39d2b450b --- /dev/null +++ b/app/assets/javascripts/observability/client.js @@ -0,0 +1,41 @@ +// import axios from '~/lib/utils/axios_utils'; +import * as mockData from './mock_traces.json'; + +function enableTraces(provisioningUrl) { + console.log(`Enabling tracing - ${provisioningUrl}`); // eslint-disable-line no-console + + return new Promise((resolve) => { + setTimeout(() => { + resolve(); + }, 500); + }); +} + +function isTracingEnabled(provisioningUrl) { + console.log(`Checking status - ${provisioningUrl}`); // eslint-disable-line no-console + + return new Promise((resolve) => { + setTimeout(() => { + resolve(false); + }, 1000); + }); +} + +function fetchTraces(tracingUrl) { + console.log(`Fetching traces from ${tracingUrl}`); // eslint-disable-line no-console + + // axios.get(`${this.endpoint}/v1/jaeger/22/api/services`, { credentials: 'include' }); + return new Promise((resolve) => { + setTimeout(() => { + resolve(mockData.data); + }, 2000); + }); +} + +export function buildClient({ provisioningUrl, tracingUrl }) { + return { + enableTraces: () => enableTraces(provisioningUrl), + isTracingEnabled: () => isTracingEnabled(provisioningUrl), + fetchTraces: () => fetchTraces(tracingUrl), + }; +} diff --git a/app/assets/javascripts/observability/components/observability_container.vue b/app/assets/javascripts/observability/components/observability_container.vue new file mode 100644 index 00000000000..7fb352cc171 --- /dev/null +++ b/app/assets/javascripts/observability/components/observability_container.vue @@ -0,0 +1,86 @@ + + + diff --git a/app/assets/javascripts/observability/components/skeleton/index.vue b/app/assets/javascripts/observability/components/skeleton/index.vue index d91f2874943..75e5ca81939 100644 --- a/app/assets/javascripts/observability/components/skeleton/index.vue +++ b/app/assets/javascripts/observability/components/skeleton/index.vue @@ -61,6 +61,12 @@ export default { this.hideSkeleton(); }, + onError() { + clearTimeout(this.errorTimeout); + clearTimeout(this.loadingTimeout); + + this.showError(); + }, setLoadingTimeout() { this.loadingTimeout = setTimeout(() => { /** @@ -130,7 +136,7 @@ export default {
diff --git a/app/assets/javascripts/observability/mock_traces.json b/app/assets/javascripts/observability/mock_traces.json new file mode 100644 index 00000000000..7b472081a24 --- /dev/null +++ b/app/assets/javascripts/observability/mock_traces.json @@ -0,0 +1,147 @@ +{ + "data": [ + { + "traceID": "668ec7d464968a87", + "date": "Mon, 03 Jul 2023 14:35:37 GMT", + "service": "HealthCheck", + "operation": "/grpc.health.v1.Health/Check", + "duration": 100, + "method": "GET", + "status": 200, + "spans": [ + + ], + "warnings": null + }, + { + "traceID": "668ec7d464968a87", + "date": "Mon, 03 Jul 2023 14:35:37 GMT", + "service": "HealthCheck", + "operation": "/grpc.health.v1.Health/Check", + "duration": 343, + "method": "GET", + "status": 200, + "spans": [ + + ], + "warnings": null + }, + { + "traceID": "668ec7d464968a87", + "date": "Mon, 03 Jul 2023 14:35:37 GMT", + "service": "HealthCheck", + "operation": "/grpc.health.v1.Health/Check", + "duration": 343, + "method": "GET", + "status": 200, + "spans": [ + + ], + "warnings": null + }, + { + "traceID": "668ec7d464968a87", + "date": "Mon, 03 Jul 2023 14:35:37 GMT", + "service": "HealthCheck", + "operation": "/grpc.health.v1.Health/Check", + "duration": 343, + "method": "GET", + "status": 200, + "spans": [ + + ], + "warnings": null + }, + { + "traceID": "668ec7d464968a87", + "date": "Mon, 03 Jul 2023 14:35:37 GMT", + "service": "HealthCheck", + "operation": "/grpc.health.v1.Health/Check", + "duration": 343, + "method": "GET", + "status": 200, + "spans": [ + + ], + "warnings": null + }, + { + "traceID": "668ec7d464968a87", + "date": "Mon, 03 Jul 2023 14:35:37 GMT", + "service": "HealthCheck", + "operation": "/grpc.health.v1.Health/Check", + "duration": 343, + "method": "GET", + "status": 200, + "spans": [ + + ], + "warnings": null + }, + { + "traceID": "668ec7d464968a87", + "date": "Mon, 03 Jul 2023 14:35:37 GMT", + "service": "HealthCheck", + "operation": "/grpc.health.v1.Health/Check", + "duration": 343, + "method": "GET", + "status": 200, + "spans": [ + + ], + "warnings": null + }, + { + "traceID": "668ec7d464968a87", + "date": "Mon, 03 Jul 2023 14:35:37 GMT", + "service": "HealthCheck", + "operation": "/grpc.health.v1.Health/Check", + "duration": 343, + "method": "GET", + "status": 200, + "spans": [ + + ], + "warnings": null + }, + { + "traceID": "668ec7d464968a87", + "date": "Mon, 03 Jul 2023 14:35:37 GMT", + "service": "HealthCheck", + "operation": "/grpc.health.v1.Health/Check", + "duration": 343, + "method": "GET", + "status": 200, + "spans": [ + + ], + "warnings": null + }, + { + "traceID": "668ec7d464968a87", + "date": "Mon, 03 Jul 2023 14:35:37 GMT", + "service": "HealthCheck", + "operation": "/grpc.health.v1.Health/Check", + "duration": 343, + "method": "GET", + "status": 200, + "spans": [ + + ], + "warnings": null + }, + { + "traceID": "668ec7d464968a87", + "date": "Mon, 03 Jul 2023 14:35:37 GMT", + "service": "HealthCheck", + "operation": "/grpc.health.v1.Health/Check", + "duration": 343, + "method": "GET", + "status": 200, + "spans": [ + + ], + "warnings": null + } + ] +} diff --git a/app/assets/javascripts/pages/projects/tracing/index/index.js b/app/assets/javascripts/pages/projects/tracing/index/index.js new file mode 100644 index 00000000000..64ca303f8ba --- /dev/null +++ b/app/assets/javascripts/pages/projects/tracing/index/index.js @@ -0,0 +1,4 @@ +import { initSimpleApp } from '~/helpers/init_simple_app_helper'; +import ListIndex from '~/tracing/list_index.vue'; + +initSimpleApp('#js-tracing', ListIndex); diff --git a/app/assets/javascripts/tracing/components/tracing_list.vue b/app/assets/javascripts/tracing/components/tracing_list.vue new file mode 100644 index 00000000000..38acda8a1b4 --- /dev/null +++ b/app/assets/javascripts/tracing/components/tracing_list.vue @@ -0,0 +1,14 @@ + + + diff --git a/app/assets/javascripts/tracing/list_index.vue b/app/assets/javascripts/tracing/list_index.vue new file mode 100644 index 00000000000..432fbb81506 --- /dev/null +++ b/app/assets/javascripts/tracing/list_index.vue @@ -0,0 +1,37 @@ + + + diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 904c1a51471..7b8d9281148 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -549,3 +549,16 @@ li.note { See https://gitlab.com/gitlab-org/gitlab/issues/36857 for more details. **/ .gl-line-height-14 { line-height: $gl-line-height-14; } + +// TODO: To be removed once `split` option for new dropdowns is implemented. +// See issue at https://gitlab.com/gitlab-org/gitlab-ui/-/issues/2263 +.gl-new-dropdown.split:nth-child(n+2) { + .gl-new-dropdown-toggle { + margin-left: 1px; + + &.btn-tertiary, + &.disabled { + margin-left: -1px; + } + } +} diff --git a/app/controllers/projects/tracing_controller.rb b/app/controllers/projects/tracing_controller.rb index 71ca03deb8c..d1218ebf344 100644 --- a/app/controllers/projects/tracing_controller.rb +++ b/app/controllers/projects/tracing_controller.rb @@ -8,10 +8,7 @@ module Projects before_action :check_tracing_enabled - def index - # TODO frontend changes coming separately https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125014 - render html: helpers.tag.strong('Tracing') - end + def index; end private diff --git a/app/helpers/projects/observability_helper.rb b/app/helpers/projects/observability_helper.rb new file mode 100644 index 00000000000..24bc1928a36 --- /dev/null +++ b/app/helpers/projects/observability_helper.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Projects + module ObservabilityHelper + def observability_tracing_view_model(project) + Gitlab::Json.generate({ + tracingUrl: Gitlab::Observability.tracing_url(project), + provisioningUrl: Gitlab::Observability.provisioning_url(project), + oauthUrl: Gitlab::Observability.oauth_url + }) + end + end +end diff --git a/app/models/concerns/protected_ref_deploy_key_access.rb b/app/models/concerns/protected_ref_deploy_key_access.rb index a62cce1368d..4275476a1ff 100644 --- a/app/models/concerns/protected_ref_deploy_key_access.rb +++ b/app/models/concerns/protected_ref_deploy_key_access.rb @@ -24,7 +24,7 @@ module ProtectedRefDeployKeyAccess end def humanize - return "Deploy key" if deploy_key.present? + return deploy_key.title if deploy_key? super end diff --git a/app/views/projects/tracing/index.html.haml b/app/views/projects/tracing/index.html.haml new file mode 100644 index 00000000000..ae6608cf343 --- /dev/null +++ b/app/views/projects/tracing/index.html.haml @@ -0,0 +1,4 @@ +- page_title _('Tracing') + +#js-tracing{ data: { view_model: observability_tracing_view_model(@project) } } + diff --git a/db/database_connections/ci.yaml b/db/database_connections/ci.yaml index daa155dcb00..5331765214e 100644 --- a/db/database_connections/ci.yaml +++ b/db/database_connections/ci.yaml @@ -4,6 +4,11 @@ gitlab_schemas: - gitlab_internal - gitlab_shared - gitlab_ci +lock_gitlab_schemas: + - gitlab_main + - gitlab_main_clusterwide + - gitlab_main_cell + - gitlab_pm klass: Ci::ApplicationRecord # if CI database is not configured, use this database fallback_database: main diff --git a/db/database_connections/main.yaml b/db/database_connections/main.yaml index dfdd50eb085..9eadd26ec26 100644 --- a/db/database_connections/main.yaml +++ b/db/database_connections/main.yaml @@ -6,6 +6,8 @@ gitlab_schemas: - gitlab_main - gitlab_main_cell - gitlab_pm +lock_gitlab_schemas: + - gitlab_ci # Note that we use ActiveRecord::Base here and not ApplicationRecord. # This is deliberate, as: # - the load balancer must be enabled for _all_ models diff --git a/db/docs/sbom_vulnerable_component_versions.yml b/db/docs/deleted_tables/sbom_vulnerable_component_versions.yml similarity index 75% rename from db/docs/sbom_vulnerable_component_versions.yml rename to db/docs/deleted_tables/sbom_vulnerable_component_versions.yml index 8747b6c6588..7642cb5ea53 100644 --- a/db/docs/sbom_vulnerable_component_versions.yml +++ b/db/docs/deleted_tables/sbom_vulnerable_component_versions.yml @@ -7,4 +7,6 @@ feature_categories: description: Stores information about vulnerable SBoM components introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95622 milestone: '15.4' +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125426 +removed_in_milestone: '16.2' gitlab_schema: gitlab_main diff --git a/db/docs/vulnerability_advisories.yml b/db/docs/deleted_tables/vulnerability_advisories.yml similarity index 75% rename from db/docs/vulnerability_advisories.yml rename to db/docs/deleted_tables/vulnerability_advisories.yml index 6ce7f30aa7c..613ab678f35 100644 --- a/db/docs/vulnerability_advisories.yml +++ b/db/docs/deleted_tables/vulnerability_advisories.yml @@ -8,4 +8,6 @@ feature_categories: description: Stores vulnerability advisories introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95622 milestone: '15.4' +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125426 +removed_in_milestone: '16.2' gitlab_schema: gitlab_main diff --git a/db/post_migrate/20230705141703_rollback_vulnerability_advisories_foreign_key_on_vulnerable_component_versions.rb b/db/post_migrate/20230705141703_rollback_vulnerability_advisories_foreign_key_on_vulnerable_component_versions.rb new file mode 100644 index 00000000000..92feca76511 --- /dev/null +++ b/db/post_migrate/20230705141703_rollback_vulnerability_advisories_foreign_key_on_vulnerable_component_versions.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class RollbackVulnerabilityAdvisoriesForeignKeyOnVulnerableComponentVersions < Gitlab::Database::Migration[2.1] + SOURCE_TABLE = :sbom_vulnerable_component_versions + TARGET_TABLE = :vulnerability_advisories + COLUMN = :vulnerability_advisory_id + + disable_ddl_transaction! + + def up + # Foreign key is removed when the table is dropped in the next migration. + end + + def down + add_concurrent_foreign_key SOURCE_TABLE, TARGET_TABLE, column: COLUMN, on_delete: :cascade + end +end diff --git a/db/post_migrate/20230705141733_rollback_component_version_foreign_key_on_vulnerable_component_versions.rb b/db/post_migrate/20230705141733_rollback_component_version_foreign_key_on_vulnerable_component_versions.rb new file mode 100644 index 00000000000..c54d4ebd1e3 --- /dev/null +++ b/db/post_migrate/20230705141733_rollback_component_version_foreign_key_on_vulnerable_component_versions.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class RollbackComponentVersionForeignKeyOnVulnerableComponentVersions < Gitlab::Database::Migration[2.1] + SOURCE_TABLE = :sbom_vulnerable_component_versions + TARGET_TABLE = :sbom_component_versions + COLUMN = :sbom_component_version_id + + disable_ddl_transaction! + + def up + # Foreign key is removed when the table is dropped in the next migration. + end + + def down + add_concurrent_foreign_key SOURCE_TABLE, TARGET_TABLE, column: COLUMN, on_delete: :cascade + end +end diff --git a/db/post_migrate/20230705142241_drop_vulnerable_component_versions.rb b/db/post_migrate/20230705142241_drop_vulnerable_component_versions.rb new file mode 100644 index 00000000000..10432f6b515 --- /dev/null +++ b/db/post_migrate/20230705142241_drop_vulnerable_component_versions.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class DropVulnerableComponentVersions < Gitlab::Database::Migration[2.1] + ADVISORY_INDEX_NAME = "index_vulnerable_component_versions_on_vulnerability_advisory" + SBOM_COMPONENT_INDEX_NAME = "index_vulnerable_component_versions_on_sbom_component_version" + + def up + drop_table :sbom_vulnerable_component_versions + end + + def down + create_table :sbom_vulnerable_component_versions do |t| + t.references :vulnerability_advisory, + index: { name: ADVISORY_INDEX_NAME } + + t.references :sbom_component_version, + index: { name: SBOM_COMPONENT_INDEX_NAME } + + t.timestamps_with_timezone null: false + end + end +end diff --git a/db/post_migrate/20230705142334_drop_vulnerabilities_advisories.rb b/db/post_migrate/20230705142334_drop_vulnerabilities_advisories.rb new file mode 100644 index 00000000000..e6bee52eb0c --- /dev/null +++ b/db/post_migrate/20230705142334_drop_vulnerabilities_advisories.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +class DropVulnerabilitiesAdvisories < Gitlab::Database::Migration[2.1] + def up + drop_table :vulnerability_advisories + end + + def down + create_table :vulnerability_advisories, id: false do |t| + t.uuid :uuid, null: false + t.timestamps_with_timezone null: false + t.primary_key :id + t.date :created_date, null: false + t.date :published_date, null: false + t.text :description, limit: 2048 + t.text :title, limit: 2048 + t.text :component_name, limit: 2048 + t.text :solution, limit: 2048 + t.text :not_impacted, limit: 2048 + t.text :cvss_v2, limit: 128 + t.text :cvss_v3, limit: 128 + t.text :affected_range, limit: 32 + t.text :identifiers, array: true, default: [] + t.text :fixed_versions, array: true, default: [] + t.text :urls, array: true, default: [] + t.text :links, array: true, default: [] + end + end +end diff --git a/db/schema_migrations/20230705141703 b/db/schema_migrations/20230705141703 new file mode 100644 index 00000000000..51c3cd350c1 --- /dev/null +++ b/db/schema_migrations/20230705141703 @@ -0,0 +1 @@ +dafb3395a28180da275eceddb87af4deb0008b2d0793dd0ea3f34d2ae8bd5c10 \ No newline at end of file diff --git a/db/schema_migrations/20230705141733 b/db/schema_migrations/20230705141733 new file mode 100644 index 00000000000..2b5870f2ba5 --- /dev/null +++ b/db/schema_migrations/20230705141733 @@ -0,0 +1 @@ +2cea22d62a5a08a643b3043bea1e14e4965f57201db559995cab8616d7586f55 \ No newline at end of file diff --git a/db/schema_migrations/20230705142241 b/db/schema_migrations/20230705142241 new file mode 100644 index 00000000000..4d4ee24d798 --- /dev/null +++ b/db/schema_migrations/20230705142241 @@ -0,0 +1 @@ +ae094cd61e252b30c1ebe0e5369ff2c061aa96079bbc1addde160003e2263886 \ No newline at end of file diff --git a/db/schema_migrations/20230705142334 b/db/schema_migrations/20230705142334 new file mode 100644 index 00000000000..ace38aed2f7 --- /dev/null +++ b/db/schema_migrations/20230705142334 @@ -0,0 +1 @@ +33de9f678eb493070ceaae0e50461cffbcdbb5a542740b9fc595cba2c8c32808 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 239970ac959..633b2943d1a 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -22361,23 +22361,6 @@ CREATE SEQUENCE sbom_sources_id_seq ALTER SEQUENCE sbom_sources_id_seq OWNED BY sbom_sources.id; -CREATE TABLE sbom_vulnerable_component_versions ( - id bigint NOT NULL, - vulnerability_advisory_id bigint, - sbom_component_version_id bigint, - created_at timestamp with time zone NOT NULL, - updated_at timestamp with time zone NOT NULL -); - -CREATE SEQUENCE sbom_vulnerable_component_versions_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - -ALTER SEQUENCE sbom_vulnerable_component_versions_id_seq OWNED BY sbom_vulnerable_component_versions.id; - CREATE TABLE scan_result_policies ( id bigint NOT NULL, security_orchestration_policy_configuration_id bigint NOT NULL, @@ -24116,44 +24099,6 @@ CREATE SEQUENCE vulnerabilities_id_seq ALTER SEQUENCE vulnerabilities_id_seq OWNED BY vulnerabilities.id; -CREATE TABLE vulnerability_advisories ( - uuid uuid NOT NULL, - created_at timestamp with time zone NOT NULL, - updated_at timestamp with time zone NOT NULL, - id bigint NOT NULL, - created_date date NOT NULL, - published_date date NOT NULL, - description text, - title text, - component_name text, - solution text, - not_impacted text, - cvss_v2 text, - cvss_v3 text, - affected_range text, - identifiers text[] DEFAULT '{}'::text[], - fixed_versions text[] DEFAULT '{}'::text[], - urls text[] DEFAULT '{}'::text[], - links text[] DEFAULT '{}'::text[], - CONSTRAINT check_3ab0544d19 CHECK ((char_length(title) <= 2048)), - CONSTRAINT check_3b57023409 CHECK ((char_length(affected_range) <= 32)), - CONSTRAINT check_4d5cd7be9c CHECK ((char_length(component_name) <= 2048)), - CONSTRAINT check_962f256a51 CHECK ((char_length(solution) <= 2048)), - CONSTRAINT check_aae93955fb CHECK ((char_length(cvss_v3) <= 128)), - CONSTRAINT check_b8a17497f3 CHECK ((char_length(cvss_v2) <= 128)), - CONSTRAINT check_c05a35f418 CHECK ((char_length(not_impacted) <= 2048)), - CONSTRAINT check_ff9f6483b6 CHECK ((char_length(description) <= 2048)) -); - -CREATE SEQUENCE vulnerability_advisories_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - -ALTER SEQUENCE vulnerability_advisories_id_seq OWNED BY vulnerability_advisories.id; - CREATE TABLE vulnerability_exports ( id bigint NOT NULL, created_at timestamp with time zone NOT NULL, @@ -25935,8 +25880,6 @@ ALTER TABLE ONLY sbom_occurrences ALTER COLUMN id SET DEFAULT nextval('sbom_occu ALTER TABLE ONLY sbom_sources ALTER COLUMN id SET DEFAULT nextval('sbom_sources_id_seq'::regclass); -ALTER TABLE ONLY sbom_vulnerable_component_versions ALTER COLUMN id SET DEFAULT nextval('sbom_vulnerable_component_versions_id_seq'::regclass); - ALTER TABLE ONLY scan_result_policies ALTER COLUMN id SET DEFAULT nextval('scan_result_policies_id_seq'::regclass); ALTER TABLE ONLY schema_inconsistencies ALTER COLUMN id SET DEFAULT nextval('schema_inconsistencies_id_seq'::regclass); @@ -26083,8 +26026,6 @@ ALTER TABLE ONLY value_stream_dashboard_counts ALTER COLUMN id SET DEFAULT nextv ALTER TABLE ONLY vulnerabilities ALTER COLUMN id SET DEFAULT nextval('vulnerabilities_id_seq'::regclass); -ALTER TABLE ONLY vulnerability_advisories ALTER COLUMN id SET DEFAULT nextval('vulnerability_advisories_id_seq'::regclass); - ALTER TABLE ONLY vulnerability_exports ALTER COLUMN id SET DEFAULT nextval('vulnerability_exports_id_seq'::regclass); ALTER TABLE ONLY vulnerability_external_issue_links ALTER COLUMN id SET DEFAULT nextval('vulnerability_external_issue_links_id_seq'::regclass); @@ -28383,9 +28324,6 @@ ALTER TABLE ONLY sbom_occurrences ALTER TABLE ONLY sbom_sources ADD CONSTRAINT sbom_sources_pkey PRIMARY KEY (id); -ALTER TABLE ONLY sbom_vulnerable_component_versions - ADD CONSTRAINT sbom_vulnerable_component_versions_pkey PRIMARY KEY (id); - ALTER TABLE ONLY scan_result_policies ADD CONSTRAINT scan_result_policies_pkey PRIMARY KEY (id); @@ -28650,9 +28588,6 @@ ALTER TABLE ONLY verification_codes ALTER TABLE ONLY vulnerabilities ADD CONSTRAINT vulnerabilities_pkey PRIMARY KEY (id); -ALTER TABLE ONLY vulnerability_advisories - ADD CONSTRAINT vulnerability_advisories_pkey PRIMARY KEY (id); - ALTER TABLE ONLY vulnerability_exports ADD CONSTRAINT vulnerability_exports_pkey PRIMARY KEY (id); @@ -33529,10 +33464,6 @@ CREATE UNIQUE INDEX index_vulnerability_statistics_on_unique_project_id ON vulne CREATE UNIQUE INDEX index_vulnerability_user_mentions_on_note_id ON vulnerability_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL); -CREATE INDEX index_vulnerable_component_versions_on_sbom_component_version ON sbom_vulnerable_component_versions USING btree (sbom_component_version_id); - -CREATE INDEX index_vulnerable_component_versions_on_vulnerability_advisory ON sbom_vulnerable_component_versions USING btree (vulnerability_advisory_id); - CREATE UNIQUE INDEX index_vulns_user_mentions_on_vulnerability_id ON vulnerability_user_mentions USING btree (vulnerability_id) WHERE (note_id IS NULL); CREATE UNIQUE INDEX index_vulns_user_mentions_on_vulnerability_id_and_note_id ON vulnerability_user_mentions USING btree (vulnerability_id, note_id); @@ -35906,9 +35837,6 @@ ALTER TABLE ONLY issues ALTER TABLE ONLY ci_build_trace_chunks ADD CONSTRAINT fk_89e29fa5ee_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; -ALTER TABLE ONLY sbom_vulnerable_component_versions - ADD CONSTRAINT fk_8a2a1197f9 FOREIGN KEY (sbom_component_version_id) REFERENCES sbom_component_versions(id) ON DELETE CASCADE; - ALTER TABLE ONLY protected_branch_merge_access_levels ADD CONSTRAINT fk_8a3072ccb3 FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE; @@ -36242,9 +36170,6 @@ ALTER TABLE ONLY lists ALTER TABLE ONLY agent_activity_events ADD CONSTRAINT fk_d6f785c9fc FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL; -ALTER TABLE ONLY sbom_vulnerable_component_versions - ADD CONSTRAINT fk_d720a1959a FOREIGN KEY (vulnerability_advisory_id) REFERENCES vulnerability_advisories(id) ON DELETE CASCADE; - ALTER TABLE ONLY user_achievements ADD CONSTRAINT fk_d7653ef780 FOREIGN KEY (revoked_by_user_id) REFERENCES users(id) ON DELETE SET NULL; diff --git a/doc/administration/settings/index.md b/doc/administration/settings/index.md index 8f349c13bb6..cf7640c75c1 100644 --- a/doc/administration/settings/index.md +++ b/doc/administration/settings/index.md @@ -70,7 +70,7 @@ The **CI/CD** settings contain: ## Security and Compliance settings -- [License compliance settings](../../user/admin_area/settings/security_and_compliance.md#choose-package-registry-metadata-to-sync): Enable or disable synchronization of package metadata by a registry type. +- [License compliance settings](security_and_compliance.md#choose-package-registry-metadata-to-sync): Enable or disable synchronization of package metadata by a registry type. ### Geo **(PREMIUM SELF)** diff --git a/doc/administration/settings/security_and_compliance.md b/doc/administration/settings/security_and_compliance.md new file mode 100644 index 00000000000..2237866ad9c --- /dev/null +++ b/doc/administration/settings/security_and_compliance.md @@ -0,0 +1,25 @@ +--- +stage: Secure +group: Composition Analysis +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +type: howto +--- + +# Security and Compliance Admin Area settings **(ULTIMATE SELF)** + +The settings for package metadata synchronization are located in the [Admin Area](index.md). + +## Choose package registry metadata to sync + +WARNING: +The full package metadata sync can add up to 30 GB to the PostgreSQL database. Ensure you have provisioned enough disk space for the database before enabling this feature. +We are actively working on reducing this data size in [epic 10415](https://gitlab.com/groups/gitlab-org/-/epics/10415). + +To choose the packages you want to synchronize with the GitLab License Database for [License Compliance](../../user/compliance/license_scanning_of_cyclonedx_files/index.md): + +1. On the left sidebar, expand the top-most chevron (**{chevron-down}**). +1. Select **Admin Area**. +1. Select **Settings > Security and Compliance**. +1. Expand **License Compliance**. +1. Select or clear checkboxes for the package registries that you want to sync. +1. Select **Save changes**. diff --git a/doc/administration/settings/sidekiq_job_limits.md b/doc/administration/settings/sidekiq_job_limits.md new file mode 100644 index 00000000000..d5cd24c5237 --- /dev/null +++ b/doc/administration/settings/sidekiq_job_limits.md @@ -0,0 +1,35 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +type: reference +--- + +# Sidekiq job size limits **(FREE SELF)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68982) in GitLab 14.3. + +[Sidekiq](../sidekiq/index.md) jobs get stored in +Redis. To avoid excessive memory for Redis, we: + +- Compress job arguments before storing them in Redis. +- Reject jobs that exceed the specified threshold limit after compression. + +To access Sidekiq job size limits: + +1. On the left sidebar, expand the top-most chevron (**{chevron-down}**). +1. Select **Admin Area**. +1. Select **Settings > Preferences**. +1. Expand **Sidekiq job size limits**. +1. Adjust the compression threshold or size limit. The compression can + be disabled by selecting the **Track** mode. + +## Available settings + +| Setting | Default | Description | +|-------------------------------------------|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Limiting mode | Compress | This mode compresses the jobs at the specified threshold and rejects them if they exceed the specified limit after compression. | +| Sidekiq job compression threshold (bytes) | 100 000 (100 KB) | When the size of arguments exceeds this threshold, they are compressed before being stored in Redis. | +| Sidekiq job size limit (bytes) | 0 | The jobs exceeding this size after compression are rejected. This avoids excessive memory usage in Redis leading to instability. Setting it to 0 prevents rejecting jobs. | + +After changing these values, [restart Sidekiq](../restart_gitlab.md). diff --git a/doc/user/admin_area/settings/security_and_compliance.md b/doc/user/admin_area/settings/security_and_compliance.md index 54fd04f6521..8c1e514c575 100644 --- a/doc/user/admin_area/settings/security_and_compliance.md +++ b/doc/user/admin_area/settings/security_and_compliance.md @@ -1,25 +1,11 @@ --- -stage: Secure -group: Composition Analysis -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments -type: howto +redirect_to: '../../../administration/settings/security_and_compliance.md' +remove_date: '2023-10-13' --- -# Security and Compliance Admin Area settings **(ULTIMATE SELF)** +This document was moved to [another location](../../../administration/settings/security_and_compliance.md). -The settings for package metadata synchronization are located in the [Admin Area](index.md). - -## Choose package registry metadata to sync - -WARNING: -The full package metadata sync can add up to 30 GB to the PostgreSQL database. Ensure you have provisioned enough disk space for the database before enabling this feature. -We are actively working on reducing this data size in [epic 10415](https://gitlab.com/groups/gitlab-org/-/epics/10415). - -To choose the packages you want to synchronize with the GitLab License Database for [License Compliance](../../compliance/license_scanning_of_cyclonedx_files/index.md): - -1. On the left sidebar, expand the top-most chevron (**{chevron-down}**). -1. Select **Admin Area**. -1. Select **Settings > Security and Compliance**. -1. Expand **License Compliance**. -1. Select or clear checkboxes for the package registries that you want to sync. -1. Select **Save changes**. + + + + diff --git a/doc/user/admin_area/settings/sidekiq_job_limits.md b/doc/user/admin_area/settings/sidekiq_job_limits.md index 08c3ced4c4e..81be26ec8e0 100644 --- a/doc/user/admin_area/settings/sidekiq_job_limits.md +++ b/doc/user/admin_area/settings/sidekiq_job_limits.md @@ -1,35 +1,11 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments -type: reference +redirect_to: '../../../administration/settings/sidekiq_job_limits.md' +remove_date: '2023-10-13' --- -# Sidekiq job size limits **(FREE SELF)** +This document was moved to [another location](../../../administration/settings/sidekiq_job_limits.md). -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68982) in GitLab 14.3. - -[Sidekiq](../../../administration/sidekiq/index.md) jobs get stored in -Redis. To avoid excessive memory for Redis, we: - -- Compress job arguments before storing them in Redis. -- Reject jobs that exceed the specified threshold limit after compression. - -To access Sidekiq job size limits: - -1. On the left sidebar, expand the top-most chevron (**{chevron-down}**). -1. Select **Admin Area**. -1. Select **Settings > Preferences**. -1. Expand **Sidekiq job size limits**. -1. Adjust the compression threshold or size limit. The compression can - be disabled by selecting the **Track** mode. - -## Available settings - -| Setting | Default | Description | -|-------------------------------------------|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Limiting mode | Compress | This mode compresses the jobs at the specified threshold and rejects them if they exceed the specified limit after compression. | -| Sidekiq job compression threshold (bytes) | 100 000 (100 KB) | When the size of arguments exceeds this threshold, they are compressed before being stored in Redis. | -| Sidekiq job size limit (bytes) | 0 | The jobs exceeding this size after compression are rejected. This avoids excessive memory usage in Redis leading to instability. Setting it to 0 prevents rejecting jobs. | - -After changing these values, [restart Sidekiq](../../../administration/restart_gitlab.md). + + + + diff --git a/doc/user/compliance/license_scanning_of_cyclonedx_files/index.md b/doc/user/compliance/license_scanning_of_cyclonedx_files/index.md index 22defd593cd..1fbe67a62b2 100644 --- a/doc/user/compliance/license_scanning_of_cyclonedx_files/index.md +++ b/doc/user/compliance/license_scanning_of_cyclonedx_files/index.md @@ -23,7 +23,7 @@ Licenses not in the SPDX list are reported as "Unknown". License information can Prerequisites: -- On GitLab self-managed only, enable [Synchronization with the GitLab License Database](../../admin_area/settings/security_and_compliance.md#choose-package-registry-metadata-to-sync) in Admin Area for the GitLab instance. On GitLab SaaS this step has already been completed. +- On GitLab self-managed only, enable [Synchronization with the GitLab License Database](../../../administration/settings/security_and_compliance.md#choose-package-registry-metadata-to-sync) in Admin Area for the GitLab instance. On GitLab SaaS this step has already been completed. - Enable [Dependency Scanning](../../application_security/dependency_scanning/index.md#configuration) and ensure that its prerequisites are met. diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md index f854dc418d6..eb67223c61f 100644 --- a/doc/user/group/import/index.md +++ b/doc/user/group/import/index.md @@ -208,10 +208,10 @@ Group items that are migrated to the destination GitLab instance include: | Boards | [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18938) | | Board lists | [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24863) | | Epics 1 | [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/issues/250281) | -| Group labels | [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/292429) | +| Group labels 2 | [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/292429) | | Iterations | [GitLab 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/292428) | | Iteration cadences | [GitLab 15.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96570) | -| Members 2 | [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/299415) | +| Members 3 | [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/299415) | | Group milestones | [GitLab 13.10](https://gitlab.com/gitlab-org/gitlab/-/issues/292427) | | Namespace settings | [GitLab 14.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85128) | | Release milestones | [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/339422) | @@ -222,6 +222,8 @@ Group items that are migrated to the destination GitLab instance include: associations [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62074) in GitLab 13.12, state and state ID [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28203) in GitLab 13.7, and system note metadata [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63551) in GitLab 14.0. +1. Group Labels cannot retain any associated Label Priorities during import. These labels will need to be re-prioritized manually + once the relevant Project is migrated to the destination instance. 1. Group members are associated with the imported group if the user: - Already exists in the destination GitLab instance. - Has a public email in the source GitLab instance that matches a confirmed email in the destination GitLab instance. @@ -490,7 +492,7 @@ for your version of GitLab to check which items can be imported to the destinati Group items that are exported include: - Milestones -- Labels +- Group Labels (_without_ associated label priorities) - Boards and Board Lists - Badges - Subgroups (including all the aforementioned data) diff --git a/lib/api/ml_model_packages.rb b/lib/api/ml_model_packages.rb index 43a61537aa2..35d231d9fe1 100644 --- a/lib/api/ml_model_packages.rb +++ b/lib/api/ml_model_packages.rb @@ -6,7 +6,7 @@ module API include ::API::Helpers::Authentication ML_MODEL_PACKAGES_REQUIREMENTS = { - package_name: API::NO_SLASH_URL_PART_REGEX, + model_name: API::NO_SLASH_URL_PART_REGEX, file_name: API::NO_SLASH_URL_PART_REGEX }.freeze @@ -47,15 +47,15 @@ module API resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do namespace ':id/packages/ml_models' do params do - requires :package_name, type: String, desc: 'Package name', regexp: Gitlab::Regex.ml_model_name_regex, + requires :model_name, type: String, desc: 'Model name', regexp: Gitlab::Regex.ml_model_name_regex, file_path: true - requires :package_version, type: String, desc: 'Package version', + requires :model_version, type: String, desc: 'Model version', regexp: Gitlab::Regex.ml_model_version_regex requires :file_name, type: String, desc: 'Package file name', regexp: Gitlab::Regex.ml_model_file_name_regex, file_path: true optional :status, type: String, values: ALLOWED_STATUSES, desc: 'Package status' end - namespace ':package_name/*package_version/:file_name', requirements: ML_MODEL_PACKAGES_REQUIREMENTS do + namespace ':model_name/*model_version/:file_name', requirements: ML_MODEL_PACKAGES_REQUIREMENTS do desc 'Workhorse authorize model package file' do detail 'Introduced in GitLab 16.1' success code: 200 @@ -91,7 +91,12 @@ module API bad_request!('File is too large') if max_file_size_exceeded? - create_package_file_params = declared(params).merge(build: current_authenticated_job) + create_package_file_params = declared(params).merge( + build: current_authenticated_job, + package_name: params[:model_name], + package_version: params[:model_version] + ) + package_file = ::Packages::MlModel::CreatePackageFileService .new(project, current_user, create_package_file_params) .execute @@ -119,7 +124,7 @@ module API authorize_read_package!(project) package = ::Packages::MlModel::PackageFinder.new(project) - .execute!(params[:package_name], params[:package_version]) + .execute!(params[:model_name], params[:model_version]) package_file = ::Packages::PackageFileFinder.new(package, params[:file_name]).execute! present_package_file!(package_file) diff --git a/lib/gitlab/database/database_connection_info.rb b/lib/gitlab/database/database_connection_info.rb index 57ecbcd64ae..f0cafcf041b 100644 --- a/lib/gitlab/database/database_connection_info.rb +++ b/lib/gitlab/database/database_connection_info.rb @@ -6,6 +6,7 @@ module Gitlab :name, :description, :gitlab_schemas, + :lock_gitlab_schemas, :klass, :fallback_database, :db_dir, @@ -20,6 +21,7 @@ module Gitlab self.name = name.to_sym self.gitlab_schemas = gitlab_schemas.map(&:to_sym) self.klass = klass.constantize + self.lock_gitlab_schemas = (lock_gitlab_schemas || []).map(&:to_sym) self.fallback_database = fallback_database&.to_sym self.db_dir = Rails.root.join(db_dir || 'db') end diff --git a/lib/gitlab/database/gitlab_schema.rb b/lib/gitlab/database/gitlab_schema.rb index 9b58284b389..0bd357b7730 100644 --- a/lib/gitlab/database/gitlab_schema.rb +++ b/lib/gitlab/database/gitlab_schema.rb @@ -23,6 +23,21 @@ module Gitlab tables.map { |table| table_schema!(table) }.to_set end + # Mainly used for test tables + # It maps table names prefixes to gitlab_schemas. + # The order of keys matter. Prefixes that contain other prefixes should come first. + IMPLICIT_GITLAB_SCHEMAS = { + '_test_gitlab_main_clusterwide_' => :gitlab_main_clusterwide, + '_test_gitlab_main_cell_' => :gitlab_main_cell, + '_test_gitlab_main_' => :gitlab_main, + '_test_gitlab_ci_' => :gitlab_ci, + '_test_gitlab_embedding_' => :gitlab_embedding, + '_test_gitlab_geo_' => :gitlab_geo, + '_test_gitlab_pm_' => :gitlab_pm, + '_test_' => :gitlab_shared, + 'pg_' => :gitlab_internal + }.freeze + # rubocop:disable Metrics/CyclomaticComplexity def self.table_schema(name) schema_name, table_name = name.split('.', 2) # Strip schema name like: `public.` @@ -54,19 +69,11 @@ module Gitlab # All tables from `information_schema.` are marked as `internal` return :gitlab_internal if schema_name == 'information_schema' - return :gitlab_main if table_name.start_with?('_test_gitlab_main_') + IMPLICIT_GITLAB_SCHEMAS.each do |prefix, gitlab_schema| + return gitlab_schema if table_name.start_with?(prefix) + end - return :gitlab_ci if table_name.start_with?('_test_gitlab_ci_') - - return :gitlab_embedding if table_name.start_with?('_test_gitlab_embedding_') - - return :gitlab_geo if table_name.start_with?('_test_gitlab_geo_') - - # All tables that start with `_test_` without a following schema are shared and ignored - return :gitlab_shared if table_name.start_with?('_test_') - - # All `pg_` tables are marked as `internal` - return :gitlab_internal if table_name.start_with?('pg_') + nil end # rubocop:enable Metrics/CyclomaticComplexity diff --git a/lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables.rb b/lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables.rb index 55c4fd6a7af..fe456fab505 100644 --- a/lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables.rb +++ b/lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables.rb @@ -11,7 +11,9 @@ module Gitlab end def exec_migration(connection, direction) - return super if %w[main ci].exclude?(Gitlab::Database.db_config_name(connection)) + db_config_name = Gitlab::Database.db_config_name(connection) + db_info = Gitlab::Database.all_database_connections.fetch(db_config_name) + return super if db_info.lock_gitlab_schemas.empty? return super if automatic_lock_on_writes_disabled? # This compares the tables only on the `public` schema. Partitions are not affected @@ -20,7 +22,7 @@ module Gitlab new_tables = connection.tables - tables new_tables.each do |table_name| - lock_writes_on_table(connection, table_name) if should_lock_writes_on_table?(table_name) + lock_writes_on_table(connection, table_name) if should_lock_writes_on_table?(db_info, table_name) end end @@ -39,16 +41,17 @@ module Gitlab end end - def should_lock_writes_on_table?(table_name) - # currently gitlab_schema represents only present existing tables, this is workaround for deleted tables - # that should be skipped as they will be removed in a future migration. + def should_lock_writes_on_table?(db_info, table_name) + # We skip locking writes on tables that are scheduled for deletion in a future migration return false if Gitlab::Database::GitlabSchema.deleted_tables_to_schema[table_name] table_schema = Gitlab::Database::GitlabSchema.table_schema!(table_name.to_s) - return false unless %i[gitlab_main gitlab_ci].include?(table_schema) - - Gitlab::Database.gitlab_schemas_for_connection(connection).exclude?(table_schema) + # This takes into consideration which database mode is used. + # In single-db and single-db-ci-connection the main database includes gitlab_ci tables, + # so we don't lock them there. + Gitlab::Database.gitlab_schemas_for_connection(connection).exclude?(table_schema) && + db_info.lock_gitlab_schemas.include?(table_schema) end # with_retries creates new a transaction. So we set it to false if the connection is diff --git a/lib/gitlab/import_export/group/import_export.yml b/lib/gitlab/import_export/group/import_export.yml index c2a1a1f8575..7a91cfb340a 100644 --- a/lib/gitlab/import_export/group/import_export.yml +++ b/lib/gitlab/import_export/group/import_export.yml @@ -7,12 +7,10 @@ tree: group: - :milestones - :badges - - labels: - - :priorities + - :labels - boards: - lists: - - label: - - :priorities + - :label - :board - members: - :user @@ -126,8 +124,7 @@ ee: - boards: - :board_assignee - :milestone - - labels: - - :priorities + - :labels - lists: - milestone: - events: diff --git a/lib/gitlab/import_export/group/relation_factory.rb b/lib/gitlab/import_export/group/relation_factory.rb index 1b8436c4ed9..664ef5358ef 100644 --- a/lib/gitlab/import_export/group/relation_factory.rb +++ b/lib/gitlab/import_export/group/relation_factory.rb @@ -6,7 +6,6 @@ module Gitlab class RelationFactory < Base::RelationFactory OVERRIDES = { labels: :group_labels, - priorities: :label_priorities, label: :group_label, parent: :epic, iterations_cadences: 'Iterations::Cadence' diff --git a/lib/gitlab/observability.rb b/lib/gitlab/observability.rb index 0e6089e1d21..b500df86363 100644 --- a/lib/gitlab/observability.rb +++ b/lib/gitlab/observability.rb @@ -27,6 +27,15 @@ module Gitlab "#{Gitlab::Observability.observability_url}/v1/auth/start" end + def tracing_url(project) + "#{Gitlab::Observability.observability_url}/query/#{project.group.id}/#{project.id}/v1/traces" + end + + def provisioning_url(_project) + # TODO Change to correct endpoint when API is ready + Gitlab::Observability.observability_url.to_s + end + # Returns true if the GitLab Observability UI (GOUI) feature flag is enabled # # @deprecated diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 21d81d0968c..035a173e9e0 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -881,6 +881,9 @@ msgstr "" msgid "%{linkStart} Learn more%{linkEnd}." msgstr "" +msgid "%{linkStart}%{linkEnd} review summary" +msgstr "" + msgid "%{listToShow}, and %{awardsListLength} more" msgstr "" @@ -11353,6 +11356,9 @@ msgstr "" msgid "Comment templates can be used when creating comments inside issues, merge requests, and epics." msgstr "" +msgid "Comment type" +msgstr "" + msgid "Comment/Reply (quoting selected text)" msgstr "" diff --git a/qa/qa/page/component/note.rb b/qa/qa/page/component/note.rb index 84cc481945f..900dc62f6b7 100644 --- a/qa/qa/page/component/note.rb +++ b/qa/qa/page/component/note.rb @@ -148,7 +148,7 @@ module QA def start_discussion(text) fill_element :comment_field, text - within_element(:comment_button) { click_button(class: 'dropdown-toggle-split') } + within_element(:comment_button) { click_button(class: 'gl-new-dropdown-toggle') } click_element :discussion_menu_item click_element :comment_button diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb index d1e00d730b7..146e4d1265a 100644 --- a/spec/features/merge_request/user_posts_notes_spec.rb +++ b/spec/features/merge_request/user_posts_notes_spec.rb @@ -46,8 +46,8 @@ RSpec.describe 'Merge request > User posts notes', :js, feature_category: :code_ it 'has enable submit button, preview button and saves content to local storage' do page.within('.js-main-target-form') do page.within('[data-testid="comment-button"]') do - expect(page).to have_css('.split-content-button') - expect(page).not_to have_css('.split-content-button[disabled]') + expect(page).to have_css('.gl-button') + expect(page).not_to have_css('.disabled') end expect(page).to have_css('.js-md-preview-button', visible: true) end diff --git a/spec/frontend/notes/components/comment_type_dropdown_spec.js b/spec/frontend/notes/components/comment_type_dropdown_spec.js index b891c1f553d..053542a421c 100644 --- a/spec/frontend/notes/components/comment_type_dropdown_spec.js +++ b/spec/frontend/notes/components/comment_type_dropdown_spec.js @@ -1,4 +1,4 @@ -import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; +import { GlButton, GlCollapsibleListbox, GlListboxItem } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import CommentTypeDropdown from '~/notes/components/comment_type_dropdown.vue'; @@ -8,9 +8,9 @@ import { COMMENT_FORM } from '~/notes/i18n'; describe('CommentTypeDropdown component', () => { let wrapper; - const findCommentGlDropdown = () => wrapper.findComponent(GlDropdown); - const findCommentDropdownOption = () => wrapper.findAllComponents(GlDropdownItem).at(0); - const findDiscussionDropdownOption = () => wrapper.findAllComponents(GlDropdownItem).at(1); + const findCommentButton = () => wrapper.findComponent(GlButton); + const findCommentListboxOption = () => wrapper.findAllComponents(GlListboxItem).at(0); + const findDiscussionListboxOption = () => wrapper.findAllComponents(GlListboxItem).at(1); const mountComponent = ({ props = {} } = {}) => { wrapper = extendedWrapper( @@ -20,6 +20,10 @@ describe('CommentTypeDropdown component', () => { noteType: constants.COMMENT, ...props, }, + stubs: { + GlCollapsibleListbox, + GlListboxItem, + }, }), ); }; @@ -33,15 +37,15 @@ describe('CommentTypeDropdown component', () => { ({ isInternalNote, buttonText }) => { mountComponent({ props: { noteType: constants.COMMENT, isInternalNote } }); - expect(findCommentGlDropdown().props()).toMatchObject({ text: buttonText }); + expect(findCommentButton().text()).toBe(buttonText); }, ); it('Should set correct dropdown item checked when comment is selected', () => { mountComponent({ props: { noteType: constants.COMMENT } }); - expect(findCommentDropdownOption().props()).toMatchObject({ isChecked: true }); - expect(findDiscussionDropdownOption().props()).toMatchObject({ isChecked: false }); + expect(findCommentListboxOption().props('isSelected')).toBe(true); + expect(findDiscussionListboxOption().props('isSelected')).toBe(false); }); it.each` @@ -53,32 +57,22 @@ describe('CommentTypeDropdown component', () => { ({ isInternalNote, buttonText }) => { mountComponent({ props: { noteType: constants.DISCUSSION, isInternalNote } }); - expect(findCommentGlDropdown().props()).toMatchObject({ text: buttonText }); + expect(findCommentButton().text()).toBe(buttonText); }, ); it('Should set correct dropdown item option checked when discussion is selected', () => { mountComponent({ props: { noteType: constants.DISCUSSION } }); - expect(findCommentDropdownOption().props()).toMatchObject({ isChecked: false }); - expect(findDiscussionDropdownOption().props()).toMatchObject({ isChecked: true }); + expect(findCommentListboxOption().props('isSelected')).toBe(false); + expect(findDiscussionListboxOption().props('isSelected')).toBe(true); }); it('Should emit `change` event when clicking on an alternate dropdown option', () => { mountComponent({ props: { noteType: constants.DISCUSSION } }); - const event = { - type: 'click', - stopPropagation: jest.fn(), - preventDefault: jest.fn(), - }; - - findCommentDropdownOption().vm.$emit('click', event); - findDiscussionDropdownOption().vm.$emit('click', event); - - // ensure the native events don't trigger anything - expect(event.stopPropagation).toHaveBeenCalledTimes(2); - expect(event.preventDefault).toHaveBeenCalledTimes(2); + findCommentListboxOption().trigger('click'); + findDiscussionListboxOption().trigger('click'); expect(wrapper.emitted('change')[0]).toEqual([constants.COMMENT]); expect(wrapper.emitted('change').length).toEqual(1); @@ -87,7 +81,7 @@ describe('CommentTypeDropdown component', () => { it('Should emit `click` event when clicking on the action button', () => { mountComponent({ props: { noteType: constants.DISCUSSION } }); - findCommentGlDropdown().vm.$emit('click'); + findCommentButton().vm.$emit('click'); expect(wrapper.emitted('click').length > 0).toBe(true); }); diff --git a/spec/frontend/observability/observability_container_spec.js b/spec/frontend/observability/observability_container_spec.js new file mode 100644 index 00000000000..1152df072d4 --- /dev/null +++ b/spec/frontend/observability/observability_container_spec.js @@ -0,0 +1,134 @@ +import { nextTick } from 'vue'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import { stubComponent } from 'helpers/stub_component'; +import ObservabilityContainer from '~/observability/components/observability_container.vue'; +import ObservabilitySkeleton from '~/observability/components/skeleton/index.vue'; +import { buildClient } from '~/observability/client'; + +jest.mock('~/observability/client'); + +describe('ObservabilityContainer', () => { + let wrapper; + + const mockSkeletonOnContentLoaded = jest.fn(); + const mockSkeletonOnError = jest.fn(); + + const OAUTH_URL = 'https://example.com/oauth'; + const TRACING_URL = 'https://example.com/tracing'; + const PROVISIONING_URL = 'https://example.com/provisioning'; + + beforeEach(() => { + jest.spyOn(console, 'error').mockImplementation(); + + buildClient.mockReturnValue({}); + + wrapper = shallowMountExtended(ObservabilityContainer, { + propsData: { + oauthUrl: OAUTH_URL, + tracingUrl: TRACING_URL, + provisioningUrl: PROVISIONING_URL, + }, + stubs: { + ObservabilitySkeleton: stubComponent(ObservabilitySkeleton, { + methods: { onContentLoaded: mockSkeletonOnContentLoaded, onError: mockSkeletonOnError }, + }), + }, + slots: { + default: { + render(h) { + h(`
mockedComponent
`); + }, + name: 'MockComponent', + props: { + observabilityClient: { + type: Object, + required: true, + }, + }, + }, + }, + }); + }); + + const dispatchMessageEvent = (status, origin) => + window.dispatchEvent( + new MessageEvent('message', { + data: { + type: 'AUTH_COMPLETION', + status, + }, + origin: origin ?? new URL(OAUTH_URL).origin, + }), + ); + + const findIframe = () => wrapper.findByTestId('observability-oauth-iframe'); + const findSlotComponent = () => wrapper.findComponent({ name: 'MockComponent' }); + + it('should render the oauth iframe', () => { + const iframe = findIframe(); + expect(iframe.exists()).toBe(true); + expect(iframe.attributes('hidden')).toBe('hidden'); + expect(iframe.attributes('src')).toBe(OAUTH_URL); + expect(iframe.attributes('sandbox')).toBe('allow-same-origin allow-forms allow-scripts'); + }); + + it('should render the ObservabilitySkeleton', () => { + const skeleton = wrapper.findComponent(ObservabilitySkeleton); + expect(skeleton.exists()).toBe(true); + }); + + it('should not render the default slot', () => { + expect(findSlotComponent().exists()).toBe(false); + }); + + it('renders the slot content and removes the iframe on oauth success message', async () => { + dispatchMessageEvent('success'); + + await nextTick(); + + expect(mockSkeletonOnContentLoaded).toHaveBeenCalledTimes(1); + + const slotComponent = findSlotComponent(); + expect(slotComponent.exists()).toBe(true); + expect(buildClient).toHaveBeenCalledWith({ + provisioningUrl: PROVISIONING_URL, + tracingUrl: TRACING_URL, + }); + expect(findIframe().exists()).toBe(false); + }); + + it('does not render the slot content and removes the iframe on oauth error message', async () => { + dispatchMessageEvent('error'); + + await nextTick(); + + expect(mockSkeletonOnError).toHaveBeenCalledTimes(1); + + expect(findSlotComponent().exists()).toBe(false); + expect(findIframe().exists()).toBe(false); + expect(buildClient).not.toHaveBeenCalled(); + }); + + it('handles oauth message only once', () => { + dispatchMessageEvent('success'); + dispatchMessageEvent('success'); + + expect(mockSkeletonOnContentLoaded).toHaveBeenCalledTimes(1); + }); + + it('only handles messages from the oauth url', () => { + dispatchMessageEvent('success', 'www.fake-url.com'); + + expect(mockSkeletonOnContentLoaded).toHaveBeenCalledTimes(0); + expect(findSlotComponent().exists()).toBe(false); + expect(findIframe().exists()).toBe(true); + }); + + it('does not handle messages if the component has been destroyed', () => { + wrapper.destroy(); + + dispatchMessageEvent('success'); + + expect(mockSkeletonOnContentLoaded).toHaveBeenCalledTimes(0); + }); +}); diff --git a/spec/frontend/observability/skeleton_spec.js b/spec/frontend/observability/skeleton_spec.js index 65dbb003743..cf9ed814c9f 100644 --- a/spec/frontend/observability/skeleton_spec.js +++ b/spec/frontend/observability/skeleton_spec.js @@ -19,7 +19,7 @@ describe('Skeleton component', () => { const SKELETON_VARIANTS = Object.values(SKELETON_VARIANTS_BY_ROUTE); - const findContentWrapper = () => wrapper.findByTestId('observability-wrapper'); + const findContentWrapper = () => wrapper.findByTestId('content-wrapper'); const findExploreSkeleton = () => wrapper.findComponent(ExploreSkeleton); @@ -42,8 +42,8 @@ describe('Skeleton component', () => { mountComponent({ variant: 'explore' }); }); - describe('loading timers', () => { - it('show Skeleton if content is not loaded within CONTENT_WAIT_MS', async () => { + describe('showing content', () => { + it('shows the skeleton if content is not loaded within CONTENT_WAIT_MS', async () => { expect(findExploreSkeleton().exists()).toBe(false); expect(findContentWrapper().isVisible()).toBe(false); @@ -55,7 +55,7 @@ describe('Skeleton component', () => { expect(findContentWrapper().isVisible()).toBe(false); }); - it('does not show the skeleton if content has loaded within CONTENT_WAIT_MS', async () => { + it('does not show the skeleton if content loads within CONTENT_WAIT_MS', async () => { expect(findExploreSkeleton().exists()).toBe(false); expect(findContentWrapper().isVisible()).toBe(false); @@ -73,9 +73,25 @@ describe('Skeleton component', () => { expect(findContentWrapper().isVisible()).toBe(true); expect(findExploreSkeleton().exists()).toBe(false); }); + + it('hides the skeleton after content loads', async () => { + jest.advanceTimersByTime(DEFAULT_TIMERS.CONTENT_WAIT_MS); + + await nextTick(); + + expect(findExploreSkeleton().exists()).toBe(true); + expect(findContentWrapper().isVisible()).toBe(false); + + wrapper.vm.onContentLoaded(); + + await nextTick(); + + expect(findContentWrapper().isVisible()).toBe(true); + expect(findExploreSkeleton().exists()).toBe(false); + }); }); - describe('error timeout', () => { + describe('error handling', () => { it('shows the error dialog if content has not loaded within TIMEOUT_MS', async () => { expect(findAlert().exists()).toBe(false); jest.advanceTimersByTime(DEFAULT_TIMERS.TIMEOUT_MS); @@ -86,6 +102,17 @@ describe('Skeleton component', () => { expect(findContentWrapper().isVisible()).toBe(false); }); + it('shows the error dialog if content fails to load', async () => { + expect(findAlert().exists()).toBe(false); + + wrapper.vm.onError(); + + await nextTick(); + + expect(findAlert().exists()).toBe(true); + expect(findContentWrapper().isVisible()).toBe(false); + }); + it('does not show the error dialog if content has loaded within TIMEOUT_MS', async () => { wrapper.vm.onContentLoaded(); jest.advanceTimersByTime(DEFAULT_TIMERS.TIMEOUT_MS); diff --git a/spec/frontend/tracing/list_index_spec.js b/spec/frontend/tracing/list_index_spec.js new file mode 100644 index 00000000000..a5759035c2f --- /dev/null +++ b/spec/frontend/tracing/list_index_spec.js @@ -0,0 +1,37 @@ +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import ListIndex from '~/tracing/list_index.vue'; +import TracingList from '~/tracing/components/tracing_list.vue'; +import ObservabilityContainer from '~/observability/components/observability_container.vue'; + +describe('ListIndex', () => { + const props = { + oauthUrl: 'https://example.com/oauth', + tracingUrl: 'https://example.com/tracing', + provisioningUrl: 'https://example.com/provisioning', + }; + + let wrapper; + + const mountComponent = () => { + wrapper = shallowMountExtended(ListIndex, { + propsData: props, + }); + }; + + it('renders ObservabilityContainer component', () => { + mountComponent(); + + const observabilityContainer = wrapper.findComponent(ObservabilityContainer); + expect(observabilityContainer.exists()).toBe(true); + expect(observabilityContainer.props('oauthUrl')).toBe(props.oauthUrl); + expect(observabilityContainer.props('tracingUrl')).toBe(props.tracingUrl); + expect(observabilityContainer.props('provisioningUrl')).toBe(props.provisioningUrl); + }); + + it('renders TracingList component inside ObservabilityContainer', () => { + mountComponent(); + + const observabilityContainer = wrapper.findComponent(ObservabilityContainer); + expect(observabilityContainer.findComponent(TracingList).exists()).toBe(true); + }); +}); diff --git a/spec/helpers/projects/observability_helper_spec.rb b/spec/helpers/projects/observability_helper_spec.rb new file mode 100644 index 00000000000..65b6ddf04ec --- /dev/null +++ b/spec/helpers/projects/observability_helper_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'json' + +RSpec.describe Projects::ObservabilityHelper, type: :helper, feature_category: :tracing do + describe '#observability_tracing_view_model' do + let_it_be(:group) { build_stubbed(:group) } + let_it_be(:project) { build_stubbed(:project, group: group) } + + it 'generates the correct JSON' do + expected_json = { + tracingUrl: Gitlab::Observability.tracing_url(project), + provisioningUrl: Gitlab::Observability.provisioning_url(project), + oauthUrl: Gitlab::Observability.oauth_url + }.to_json + + expect(helper.observability_tracing_view_model(project)).to eq(expected_json) + end + end +end diff --git a/spec/lib/gitlab/database/gitlab_schema_spec.rb b/spec/lib/gitlab/database/gitlab_schema_spec.rb index 48f5cdb995b..1c864239ae6 100644 --- a/spec/lib/gitlab/database/gitlab_schema_spec.rb +++ b/spec/lib/gitlab/database/gitlab_schema_spec.rb @@ -29,6 +29,9 @@ RSpec.describe Gitlab::Database::GitlabSchema, feature_category: :database do 'audit_events_part_5fc467ac26' | :gitlab_main '_test_gitlab_main_table' | :gitlab_main '_test_gitlab_ci_table' | :gitlab_ci + '_test_gitlab_main_clusterwide_table' | :gitlab_main_clusterwide + '_test_gitlab_main_cell_table' | :gitlab_main_cell + '_test_gitlab_pm_table' | :gitlab_pm '_test_my_table' | :gitlab_shared 'pg_attribute' | :gitlab_internal end diff --git a/spec/lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables_spec.rb b/spec/lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables_spec.rb index e4241348b54..577bf00ba2f 100644 --- a/spec/lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables_spec.rb +++ b/spec/lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables_spec.rb @@ -9,7 +9,10 @@ RSpec.describe Gitlab::Database::MigrationHelpers::AutomaticLockWritesOnTables, let(:schema_class) { Class.new(Gitlab::Database::Migration[2.1]) } let(:skip_automatic_lock_on_writes) { false } let(:gitlab_main_table_name) { :_test_gitlab_main_table } + let(:gitlab_main_clusterwide_table_name) { :_test_gitlab_main_clusterwide_table } + let(:gitlab_main_cell_table_name) { :_test_gitlab_main_cell_table } let(:gitlab_ci_table_name) { :_test_gitlab_ci_table } + let(:gitlab_pm_table_name) { :_test_gitlab_pm_table } let(:gitlab_geo_table_name) { :_test_gitlab_geo_table } let(:gitlab_shared_table_name) { :_test_table } @@ -24,8 +27,11 @@ RSpec.describe Gitlab::Database::MigrationHelpers::AutomaticLockWritesOnTables, # Drop the created test tables, because we use non-transactional tests after do drop_table_if_exists(gitlab_main_table_name) + drop_table_if_exists(gitlab_main_clusterwide_table_name) + drop_table_if_exists(gitlab_main_cell_table_name) drop_table_if_exists(gitlab_ci_table_name) drop_table_if_exists(gitlab_geo_table_name) + drop_table_if_exists(gitlab_pm_table_name) drop_table_if_exists(gitlab_shared_table_name) drop_table_if_exists(renamed_gitlab_main_table_name) drop_table_if_exists(renamed_gitlab_ci_table_name) @@ -82,8 +88,12 @@ RSpec.describe Gitlab::Database::MigrationHelpers::AutomaticLockWritesOnTables, context 'when single database' do let(:config_model) { Gitlab::Database.database_base_models[:main] } let(:create_gitlab_main_table_migration_class) { create_table_migration(gitlab_main_table_name) } + let(:create_gitlab_main_cell_table_migration_class) { create_table_migration(gitlab_main_cell_table_name) } let(:create_gitlab_ci_table_migration_class) { create_table_migration(gitlab_ci_table_name) } let(:create_gitlab_shared_table_migration_class) { create_table_migration(gitlab_shared_table_name) } + let(:create_gitlab_main_clusterwide_table_migration_class) do + create_table_migration(gitlab_main_clusterwide_table_name) + end before do skip_if_database_exists(:ci) @@ -93,13 +103,19 @@ RSpec.describe Gitlab::Database::MigrationHelpers::AutomaticLockWritesOnTables, expect(Gitlab::Database::LockWritesManager).not_to receive(:new) create_gitlab_main_table_migration_class.migrate(:up) + create_gitlab_main_cell_table_migration_class.migrate(:up) + create_gitlab_main_clusterwide_table_migration_class.migrate(:up) create_gitlab_ci_table_migration_class.migrate(:up) create_gitlab_shared_table_migration_class.migrate(:up) expect do create_gitlab_main_table_migration_class.connection.execute("DELETE FROM #{gitlab_main_table_name}") + create_gitlab_main_cell_table_migration_class.connection.execute("DELETE FROM #{gitlab_main_cell_table_name}") create_gitlab_ci_table_migration_class.connection.execute("DELETE FROM #{gitlab_ci_table_name}") create_gitlab_shared_table_migration_class.connection.execute("DELETE FROM #{gitlab_shared_table_name}") + create_gitlab_main_clusterwide_table_migration_class.connection.execute( + "DELETE FROM #{gitlab_main_clusterwide_table_name}" + ) end.not_to raise_error end end @@ -163,6 +179,27 @@ RSpec.describe Gitlab::Database::MigrationHelpers::AutomaticLockWritesOnTables, end end + context 'for creating a gitlab_main_clusterwide table' do + let(:table_name) { gitlab_main_clusterwide_table_name } + + it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:main] + it_behaves_like 'locks writes on table', Gitlab::Database.database_base_models[:ci] + end + + context 'for creating a gitlab_main_cell table' do + let(:table_name) { gitlab_main_cell_table_name } + + it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:main] + it_behaves_like 'locks writes on table', Gitlab::Database.database_base_models[:ci] + end + + context 'for creating a gitlab_pm table' do + let(:table_name) { gitlab_pm_table_name } + + it_behaves_like 'does not lock writes on table', Gitlab::Database.database_base_models[:main] + it_behaves_like 'locks writes on table', Gitlab::Database.database_base_models[:ci] + end + context 'for creating a gitlab_ci table' do let(:table_name) { gitlab_ci_table_name } diff --git a/spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb index 495cefa002a..9852f6c9652 100644 --- a/spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb @@ -71,20 +71,22 @@ RSpec.describe Gitlab::ImportExport::Group::RelationTreeRestorer, feature_catego before do allow(shared.logger).to receive(:info).and_call_original allow(relation_reader).to receive(:consume_relation).and_call_original - - allow(relation_reader) - .to receive(:consume_relation) - .with(importable_name, 'labels') - .and_return([[label, 0]]) end context 'when relation object is new' do + before do + allow(relation_reader) + .to receive(:consume_relation) + .with(importable_name, 'boards') + .and_return([[board, 0]]) + end + context 'when relation object has invalid subrelations' do - let(:label) do + let(:board) do { - 'title' => 'test', - 'priorities' => [LabelPriority.new, LabelPriority.new], - 'type' => 'GroupLabel' + 'name' => 'test', + 'lists' => [List.new, List.new], + 'group_id' => importable.id } end @@ -94,26 +96,33 @@ RSpec.describe Gitlab::ImportExport::Group::RelationTreeRestorer, feature_catego .with( message: '[Project/Group Import] Invalid subrelation', group_id: importable.id, - relation_key: 'labels', - error_messages: "Project can't be blank, Priority can't be blank, and Priority is not a number" + relation_key: 'boards', + error_messages: "Label can't be blank, Position can't be blank, and Position is not a number" ) subject - label = importable.labels.first + board = importable.boards.last failure = importable.import_failures.first expect(importable.import_failures.count).to eq(2) - expect(label.title).to eq('test') + expect(board.name).to eq('test') expect(failure.exception_class).to eq('ActiveRecord::RecordInvalid') expect(failure.source).to eq('RelationTreeRestorer#save_relation_object') expect(failure.exception_message) - .to eq("Project can't be blank, Priority can't be blank, and Priority is not a number") + .to eq("Label can't be blank, Position can't be blank, and Position is not a number") end end end context 'when relation object is persisted' do + before do + allow(relation_reader) + .to receive(:consume_relation) + .with(importable_name, 'labels') + .and_return([[label, 0]]) + end + context 'when relation object is invalid' do let(:label) { create(:group_label, group: group, title: 'test') } diff --git a/spec/lib/gitlab/observability_spec.rb b/spec/lib/gitlab/observability_spec.rb index 84d591e2520..61f69a0171a 100644 --- a/spec/lib/gitlab/observability_spec.rb +++ b/spec/lib/gitlab/observability_spec.rb @@ -3,6 +3,9 @@ require 'spec_helper' RSpec.describe Gitlab::Observability, feature_category: :error_tracking do + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, group: group) } + describe '.observability_url' do let(:gitlab_url) { 'https://example.com' } @@ -37,6 +40,18 @@ RSpec.describe Gitlab::Observability, feature_category: :error_tracking do it { is_expected.to eq("#{described_class.observability_url}/v1/auth/start") } end + describe '.tracing_url' do + subject { described_class.tracing_url(project) } + + it { is_expected.to eq("#{described_class.observability_url}/query/#{group.id}/#{project.id}/v1/traces") } + end + + describe '.provisioning_url' do + subject { described_class.provisioning_url(project) } + + it { is_expected.to eq(described_class.observability_url.to_s) } + end + describe '.build_full_url' do let_it_be(:group) { build_stubbed(:group, id: 123) } let(:observability_url) { described_class.observability_url } diff --git a/spec/models/bulk_imports/file_transfer/group_config_spec.rb b/spec/models/bulk_imports/file_transfer/group_config_spec.rb index e50f52c728f..9e1e7cf6d6e 100644 --- a/spec/models/bulk_imports/file_transfer/group_config_spec.rb +++ b/spec/models/bulk_imports/file_transfer/group_config_spec.rb @@ -40,7 +40,12 @@ RSpec.describe BulkImports::FileTransfer::GroupConfig, feature_category: :import describe '#top_relation_tree' do it 'returns relation tree of a top level relation' do - expect(subject.top_relation_tree('labels')).to eq('priorities' => {}) + expect(subject.top_relation_tree('boards')).to include( + 'lists' => a_hash_including({ + 'board' => anything, + 'label' => anything + }) + ) end end diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 7cf3981969c..a91ac7a2c20 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -1510,52 +1510,22 @@ RSpec.describe Issue, feature_category: :team_planning do end describe '#publicly_visible?' do - context 'using a public project' do - let(:project) { create(:project, :public) } + let(:project) { build(:project, project_visiblity) } + let(:issue) { build(:issue, confidential: confidential, project: project) } - it 'returns true for a regular issue' do - issue = build(:issue, project: project) + subject { issue.send(:publicly_visible?) } - expect(issue).to be_truthy - end - - it 'returns false for a confidential issue' do - issue = build(:issue, :confidential, project: project) - - expect(issue).not_to be_falsy - end + where(:project_visiblity, :confidential, :expected_value) do + :public | false | true + :public | true | false + :internal | false | false + :internal | true | false + :private | false | false + :private | true | false end - context 'using an internal project' do - let(:project) { create(:project, :internal) } - - it 'returns false for a regular issue' do - issue = build(:issue, project: project) - - expect(issue).not_to be_falsy - end - - it 'returns false for a confidential issue' do - issue = build(:issue, :confidential, project: project) - - expect(issue).not_to be_falsy - end - end - - context 'using a private project' do - let(:project) { create(:project, :private) } - - it 'returns false for a regular issue' do - issue = build(:issue, project: project) - - expect(issue).not_to be_falsy - end - - it 'returns false for a confidential issue' do - issue = build(:issue, :confidential, project: project) - - expect(issue).not_to be_falsy - end + with_them do + it { is_expected.to eq(expected_value) } end end diff --git a/spec/requests/api/ml_model_packages_spec.rb b/spec/requests/api/ml_model_packages_spec.rb index a559f1642e8..3166298b430 100644 --- a/spec/requests/api/ml_model_packages_spec.rb +++ b/spec/requests/api/ml_model_packages_spec.rb @@ -124,18 +124,18 @@ RSpec.describe ::API::MlModelPackages, feature_category: :mlops do project.send("add_#{user_role}", user) if member && user_role != :anonymous end - describe 'PUT /api/v4/projects/:id/packages/ml_models/:package_name/:package_version/:file_name/authorize' do + describe 'PUT /api/v4/projects/:id/packages/ml_models/:model_name/:model_version/:file_name/authorize' do include_context 'ml model authorize permissions table' let(:token) { tokens[:personal_access_token] } let(:user_headers) { { 'HTTP_AUTHORIZATION' => token } } let(:headers) { user_headers.merge(workhorse_headers) } let(:request) { authorize_upload_file(headers) } - let(:package_name) { 'my_package' } + let(:model_name) { 'my_package' } let(:file_name) { 'myfile.tar.gz' } subject(:api_response) do - url = "/projects/#{project.id}/packages/ml_models/#{package_name}/0.0.1/#{file_name}/authorize" + url = "/projects/#{project.id}/packages/ml_models/#{model_name}/0.0.1/#{file_name}/authorize" put api(url), headers: headers @@ -162,7 +162,7 @@ RSpec.describe ::API::MlModelPackages, feature_category: :mlops do end describe 'application security' do - where(:package_name, :file_name) do + where(:model_name, :file_name) do 'my-package/../' | 'myfile.tar.gz' 'my-package%2f%2e%2e%2f' | 'myfile.tar.gz' 'my_package' | '../.ssh%2fauthorized_keys' @@ -177,7 +177,7 @@ RSpec.describe ::API::MlModelPackages, feature_category: :mlops do end end - describe 'PUT /api/v4/projects/:id/packages/ml_models/:package_name/:package_version/:file_name' do + describe 'PUT /api/v4/projects/:id/packages/ml_models/:model_name/:model_version/:file_name' do include_context 'ml model authorize permissions table' let_it_be(:file_name) { 'model.md5' } @@ -188,10 +188,10 @@ RSpec.describe ::API::MlModelPackages, feature_category: :mlops do let(:params) { { file: temp_file(file_name) } } let(:file_key) { :file } let(:send_rewritten_field) { true } - let(:package_name) { 'my_package' } + let(:model_name) { 'my_package' } subject(:api_response) do - url = "/projects/#{project.id}/packages/ml_models/#{package_name}/0.0.1/#{file_name}" + url = "/projects/#{project.id}/packages/ml_models/#{model_name}/0.0.1/#{file_name}" workhorse_finalize( api(url), @@ -236,14 +236,14 @@ RSpec.describe ::API::MlModelPackages, feature_category: :mlops do end end - describe 'GET /api/v4/projects/:project_id/packages/ml_models/:package_name/:package_version/:file_name' do + describe 'GET /api/v4/projects/:project_id/packages/ml_models/:model_name/:model_version/:file_name' do include_context 'ml model authorize permissions table' let_it_be(:package) { create(:ml_model_package, project: project, name: 'model', version: '0.0.1') } let_it_be(:package_file) { create(:package_file, :generic, package: package, file_name: 'model.md5') } - let(:package_name) { package.name } - let(:package_version) { package.version } + let(:model_name) { package.name } + let(:model_version) { package.version } let(:file_name) { package_file.file_name } let(:token) { tokens[:personal_access_token] } @@ -251,7 +251,7 @@ RSpec.describe ::API::MlModelPackages, feature_category: :mlops do let(:headers) { user_headers.merge(workhorse_headers) } subject(:api_response) do - url = "/projects/#{project.id}/packages/ml_models/#{package_name}/#{package_version}/#{file_name}" + url = "/projects/#{project.id}/packages/ml_models/#{model_name}/#{model_version}/#{file_name}" get api(url), headers: headers diff --git a/spec/requests/api/protected_branches_spec.rb b/spec/requests/api/protected_branches_spec.rb index 04d5f7ac20a..ad3a69fec9d 100644 --- a/spec/requests/api/protected_branches_spec.rb +++ b/spec/requests/api/protected_branches_spec.rb @@ -121,7 +121,7 @@ RSpec.describe API::ProtectedBranches, feature_category: :source_code_management get api(route, user) expect(json_response['push_access_levels']).to include( - a_hash_including('access_level_description' => 'Deploy key', 'deploy_key_id' => deploy_key.id) + a_hash_including('access_level_description' => deploy_key.title, 'deploy_key_id' => deploy_key.id) ) end end diff --git a/spec/requests/api/protected_tags_spec.rb b/spec/requests/api/protected_tags_spec.rb index c6398e624f8..4e7227b2294 100644 --- a/spec/requests/api/protected_tags_spec.rb +++ b/spec/requests/api/protected_tags_spec.rb @@ -95,7 +95,7 @@ RSpec.describe API::ProtectedTags, feature_category: :source_code_management do get api(route, user) expect(json_response['create_access_levels']).to include( - a_hash_including('access_level_description' => 'Deploy key', 'deploy_key_id' => deploy_key.id) + a_hash_including('access_level_description' => deploy_key.title, 'deploy_key_id' => deploy_key.id) ) end end diff --git a/spec/requests/projects/tracing_controller_spec.rb b/spec/requests/projects/tracing_controller_spec.rb index 520e99b120a..eecaa0d962a 100644 --- a/spec/requests/projects/tracing_controller_spec.rb +++ b/spec/requests/projects/tracing_controller_spec.rb @@ -3,7 +3,8 @@ require 'spec_helper' RSpec.describe Projects::TracingController, feature_category: :tracing do - let_it_be(:project) { create(:project, :repository) } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, group: group) } let_it_be(:user) { create(:user) } let(:path) { nil } let(:observability_tracing_ff) { true } @@ -44,6 +45,17 @@ RSpec.describe Projects::TracingController, feature_category: :tracing do expect(subject).to have_gitlab_http_status(:ok) end + it 'renders the js-tracing element correctly' do + element = Nokogiri::HTML.parse(subject.body).at_css('#js-tracing') + + expected_view_model = { + tracingUrl: Gitlab::Observability.tracing_url(project), + provisioningUrl: Gitlab::Observability.provisioning_url(project), + oauthUrl: Gitlab::Observability.oauth_url + }.to_json + expect(element.attributes['data-view-model'].value).to eq(expected_view_model) + end + context 'when feature is disabled' do let(:observability_tracing_ff) { false } diff --git a/spec/support/shared_examples/features/discussion_comments_shared_example.rb b/spec/support/shared_examples/features/discussion_comments_shared_example.rb index ac8055138d7..ba520d0c609 100644 --- a/spec/support/shared_examples/features/discussion_comments_shared_example.rb +++ b/spec/support/shared_examples/features/discussion_comments_shared_example.rb @@ -3,8 +3,8 @@ RSpec.shared_examples 'thread comments for commit and snippet' do |resource_name| let(:form_selector) { '.js-main-target-form' } let(:dropdown_selector) { "#{form_selector} .comment-type-dropdown" } - let(:toggle_selector) { "#{dropdown_selector} .gl-dropdown-toggle" } - let(:menu_selector) { "#{dropdown_selector} .dropdown-menu" } + let(:toggle_selector) { "#{dropdown_selector} .gl-new-dropdown-toggle" } + let(:menu_selector) { "#{dropdown_selector} .gl-new-dropdown-contents" } let(:submit_selector) { "#{form_selector} .js-comment-submit-button > button:first-child" } let(:close_selector) { "#{form_selector} .btn-comment-and-close" } let(:comments_selector) { '.timeline > .note.timeline-entry:not(.being-posted)' } @@ -63,33 +63,6 @@ RSpec.shared_examples 'thread comments for commit and snippet' do |resource_name expect(page).not_to have_selector menu_selector end - it 'clicking the ul padding or divider should not change the text' do - execute_script("document.querySelector('#{menu_selector}').click()") - - # on issues page, the menu closes when clicking anywhere, on other pages it will - # remain open if clicking divider or menu padding, but should not change button action - # - # if dropdown menu is not toggled (and also not present), - # it's "issue-type" dropdown - if first(menu_selector, minimum: 0).nil? - expect(find(dropdown_selector)).to have_content 'Comment' - - find(toggle_selector).click - execute_script("document.querySelector('#{menu_selector} .dropdown-divider').click()") - else - execute_script("document.querySelector('#{menu_selector}').click()") - - expect(page).to have_selector menu_selector - expect(find(dropdown_selector)).to have_content 'Comment' - - execute_script("document.querySelector('#{menu_selector} .dropdown-divider').click()") - - expect(page).to have_selector menu_selector - end - - expect(find(dropdown_selector)).to have_content 'Comment' - end - describe 'when selecting "Start thread"' do before do find("#{menu_selector} li", match: :first) @@ -178,10 +151,10 @@ end RSpec.shared_examples 'thread comments for issue, epic and merge request' do |resource_name| let(:form_selector) { '.js-main-target-form' } - let(:dropdown_selector) { "#{form_selector} [data-testid='comment-button']" } - let(:submit_button_selector) { "#{dropdown_selector} .split-content-button" } - let(:toggle_selector) { "#{dropdown_selector} .dropdown-toggle-split" } - let(:menu_selector) { "#{dropdown_selector} .dropdown-menu" } + let(:dropdown_selector) { "#{form_selector} .comment-type-dropdown" } + let(:toggle_selector) { "#{dropdown_selector} .gl-new-dropdown-toggle" } + let(:menu_selector) { "#{dropdown_selector} .gl-new-dropdown-contents" } + let(:submit_selector) { "#{form_selector} .js-comment-submit-button > button:first-child" } let(:close_selector) { "#{form_selector} .btn-comment-and-close" } let(:comments_selector) { '.timeline > .note.timeline-entry:not(.being-posted)' } let(:comment) { 'My comment' } @@ -191,7 +164,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re find("#{form_selector} .note-textarea").send_keys(comment) - find(submit_button_selector).click + find(submit_selector).click wait_for_all_requests @@ -260,7 +233,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re describe 'creating a thread' do before do - find(submit_button_selector).click + find(submit_selector).click wait_for_requests find(comments_selector, match: :first) @@ -366,7 +339,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re end it 'updates the submit button text and closes the dropdown' do - button = find(submit_button_selector) + button = find(submit_selector) expect(button).to have_content 'Comment' diff --git a/spec/tasks/gitlab/feature_categories_rake_spec.rb b/spec/tasks/gitlab/feature_categories_rake_spec.rb index 33f4bca4c85..f495c7e8911 100644 --- a/spec/tasks/gitlab/feature_categories_rake_spec.rb +++ b/spec/tasks/gitlab/feature_categories_rake_spec.rb @@ -40,7 +40,8 @@ RSpec.describe 'gitlab:feature_categories:index', :silence_stdout, feature_categ ) ), 'database_tables' => a_hash_including( - 'container_scanning' => a_collection_including('vulnerability_advisories') + 'continuous_integration' => a_collection_including('ci_pipelines'), + 'user_profile' => a_collection_including('users') ) } diff --git a/vendor/project_templates/typo3_distribution.tar.gz b/vendor/project_templates/typo3_distribution.tar.gz index 13c158d1462aa10c8462ad28105a13efcb2645c9..1de92d781af829b2b553c7b171db40e162bdaf49 100644 GIT binary patch literal 77071 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�v}!9zzcTi2$qi; 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 F{|n=fSM&e? literal 71800 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≪VyTy}oNP?Wttb1SRQh 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