diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-24 12:07:53 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-24 12:07:53 +0300 |
commit | 52b219b6f40e49471c66765a95a550f6de256b6a (patch) | |
tree | 37102bf58bd19bb23ab99bf940763a0d5311965b | |
parent | 9933e246c88dfa3d62eb0bab258539711663b904 (diff) |
Add latest changes from gitlab-org/gitlab@master
52 files changed, 1173 insertions, 550 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml index ae0d4610927..1bb28aae21a 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -163,7 +163,6 @@ overrides: - '*.config.js' - '*.config.*.js' - 'jest_resolver.js' - - storybook/config/*.js rules: '@gitlab/require-i18n-strings': off import/no-extraneous-dependencies: off diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml index c3f14011c5b..fc98f771344 100644 --- a/.gitlab/ci/review.gitlab-ci.yml +++ b/.gitlab/ci/review.gitlab-ci.yml @@ -108,26 +108,30 @@ start-review-app-pipeline: - artifact: review-app-pipeline.yml job: e2e-test-pipeline-generate -include: - - project: gitlab-org/quality/pipeline-common - ref: 5.2.2 - file: - - /ci/danger-review.yml - danger-review: extends: - .default-retry - .ruby-node-cache - .review:rules:danger - image: "${DEFAULT_CI_IMAGE}" + stage: test + needs: [] before_script: - source scripts/utils.sh - bundle_install_script "--with danger" - yarn_install_script + script: + # ${DANGER_DANGERFILE} is used by Jihulab for customizing danger support: https://jihulab.com/gitlab-cn/gitlab/-/blob/main-jh/jh/.gitlab-ci.yml + - > + if [ -z "$DANGER_GITLAB_API_TOKEN" ]; then + run_timed_command danger_as_local + else + danger_id=$(echo -n ${DANGER_GITLAB_API_TOKEN} | md5sum | awk '{print $1}' | cut -c5-10) + run_timed_command "bundle exec danger --fail-on-errors=true --verbose --danger_id=\"${danger_id}\" --dangerfile=\"${DANGER_DANGERFILE:-Dangerfile}\"" + fi danger-review-local: - extends: danger-review - before_script: - - !reference ["danger-review", "before_script"] - # We unset DANGER_GITLAB_API_TOKEN so that Danger will run as local from `danger-review:script` - - unset DANGER_GITLAB_API_TOKEN + extends: + - danger-review + - .review:rules:danger-local + script: + - run_timed_command danger_as_local diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index 87c74438d00..95da3b3cf49 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -97,6 +97,7 @@ const Api = { secureFilePath: '/api/:version/projects/:project_id/secure_files/:secure_file_id', secureFilesPath: '/api/:version/projects/:project_id/secure_files', dependencyProxyPath: '/api/:version/groups/:id/dependency_proxy/cache', + markdownPath: '/api/:version/markdown', group(groupId, callback = () => {}) { const url = Api.buildUrl(Api.groupPath).replace(':id', groupId); @@ -1017,6 +1018,12 @@ const Api = { return axios.delete(url, { params: { ...options } }); }, + + markdown(data = {}) { + const url = Api.buildUrl(this.markdownPath); + + return axios.post(url, data); + }, }; export default Api; diff --git a/app/assets/javascripts/content_editor/content_editor.stories.js b/app/assets/javascripts/content_editor/content_editor.stories.js index 9e1a4bfe361..b98050b61ea 100644 --- a/app/assets/javascripts/content_editor/content_editor.stories.js +++ b/app/assets/javascripts/content_editor/content_editor.stories.js @@ -1,26 +1,31 @@ +import Api from '~/api'; import { ContentEditor } from './index'; export default { component: ContentEditor, - title: 'content_editor/content_editor', + title: 'ce/content_editor/content_editor', }; const Template = (_, { argTypes }) => ({ components: { ContentEditor }, props: Object.keys(argTypes), - template: '<content-editor v-bind="$props" @initialized="loadContent" />', - methods: { - loadContent(contentEditor) { - contentEditor.setSerializedContent('Hello content editor'); - }, - }, + template: ` + <content-editor v-bind="$props" /> + `, }); export const Default = Template.bind({}); Default.args = { - renderMarkdown: () => '<p>Hello content editor</p>', + project: 'gitlab-org/gitlab-shell', + renderMarkdown: async (text) => { + const response = await Api.markdown({ text, gfm: true, project: Default.args.project }); + + return response.data.html; + }, + markdown: 'This is **bold text**', uploadsPath: '/uploads/', serializerConfig: {}, extensions: [], + enableAutocomplete: false, }; diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js index a4c13f9e40e..6ab530576fc 100644 --- a/app/assets/javascripts/lib/graphql.js +++ b/app/assets/javascripts/lib/graphql.js @@ -120,6 +120,8 @@ function createApolloClient(resolvers = {}, config = {}) { cacheConfig = { typePolicies: {}, possibleTypes: {} }, fetchPolicy = fetchPolicies.CACHE_FIRST, typeDefs, + httpHeaders = {}, + fetchCredentials = 'same-origin', path = '/api/graphql', useGet = false, } = config; @@ -138,11 +140,12 @@ function createApolloClient(resolvers = {}, config = {}) { uri, headers: { [csrf.headerKey]: csrf.token, + ...httpHeaders, }, // fetch won’t send cookies in older browsers, unless you set the credentials init option. // We set to `same-origin` which is default value in modern browsers. // See https://github.com/whatwg/fetch/pull/585 for more information. - credentials: 'same-origin', + credentials: fetchCredentials, batchMax, }; diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml index 1400ac9ca72..93ac252823a 100644 --- a/app/views/devise/passwords/new.html.haml +++ b/app/views/devise/passwords/new.html.haml @@ -7,7 +7,10 @@ = f.label :email, class: ("gl-mb-1" if Feature.enabled?(:restyle_login_page)) = f.email_field :email, class: "form-control gl-form-input", required: true, autocomplete: 'off', value: params[:user_email], autofocus: true, title: _('Please provide a valid email address.') .form-text.text-muted - = _('Requires your primary GitLab email address.') + - if Feature.enabled?(:password_reset_any_verified_email) + = _('Requires a verified GitLab email address.') + - else + = _('Requires your primary GitLab email address.') - if recaptcha_enabled? .gl-px-5 diff --git a/db/migrate/20230523101514_finalize_user_type_migration.rb b/db/migrate/20230523101514_finalize_user_type_migration.rb new file mode 100644 index 00000000000..f8ae4c7bb2c --- /dev/null +++ b/db/migrate/20230523101514_finalize_user_type_migration.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class FinalizeUserTypeMigration < Gitlab::Database::Migration[2.1] + MIGRATION = 'MigrateHumanUserType' + + disable_ddl_transaction! + + def up + finalize_background_migration(MIGRATION) + end + + def down + # no-op + end +end diff --git a/db/schema_migrations/20230523101514 b/db/schema_migrations/20230523101514 new file mode 100644 index 00000000000..76c331d425d --- /dev/null +++ b/db/schema_migrations/20230523101514 @@ -0,0 +1 @@ +d9efa5185994ecc7d2025d450a1072286674a0a2d94f7f2aa11a6b6b24d4f5da
\ No newline at end of file diff --git a/doc/development/fe_guide/storybook.md b/doc/development/fe_guide/storybook.md index 8e0814ad96b..44169f110c7 100644 --- a/doc/development/fe_guide/storybook.md +++ b/doc/development/fe_guide/storybook.md @@ -53,8 +53,64 @@ To add a story: If the component is located in the `ee/` directory, make sure to prefix the story's title with `ee/` as well. This will ensure the Storybook navigation maps closely to our internal directory structure. -## Mock backend APIs +## Using GitLab REST and GraphQL APIs -The GitLab Storybook uses [MirajeJS](https://miragejs.com/) to mock REST and GraphQL APIs. Storybook shares the MirajeJS server -with the [frontend integration tests](../testing_guide/testing_levels.md#frontend-integration-tests). You can find the MirajeJS -configuration files in `spec/frontend_integration/mock_server`. +You can write stories for components that use either GitLab’s [REST](../../api/rest/index.md) or +[GraphQL](../../api/graphql/index.md) APIs. + +### Set up API access token and GitLab instance URL + +To add a story with API access: + +1. Create a [personal access token](../../user/profile/personal_access_tokens.md) in your GitLab instance. + + NOTE: + If you test against `gitlab.com`, make sure to use a token with `read_api` if possible and to make the token short-lived. + +1. Create an `.env` file in the `storybook` directory. Use the `storybook/.env.template` file as +a starting point. + +1. Set the `API_ACCESS_TOKEN` variable to the access token that you created. + +1. Set the `GITLAB_URL` variable to the GitLab instance’s domain URL, for example: `http://gdk.test:3000`. + +1. Start or restart your storybook. + +You can also use the GitLab API Access panel in the Storybook UI to set the GitLab instance URL and access token. + +### Using REST API + +The Storybook sets up `~/lib/utils/axios_utils` in `storybook/config/preview.js`. Components that use the REST API +should work out of the box as long as you provide a valid GitLab instance URL and access token. + +### Using GraphQL + +To write a story for a component that uses the GraphQL API, use the `createVueApollo` method provided in +the Story context. + +```javascript +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import WorkspacesList from './list.vue'; + +Vue.use(VueApollo); + +const Template = (_, { argTypes, createVueApollo }) => { + return { + components: { WorkspacesList }, + apolloProvider: createVueApollo(), + props: Object.keys(argTypes), + template: '<workspaces-list />', + }; +}; + +export default { + component: WorkspacesList, + title: 'ee/remote_development/workspaces_list', +}; + +export const Default = Template.bind({}); + +Default.args = {}; + +``` diff --git a/doc/update/index.md b/doc/update/index.md index 00c55f1e4b4..07baec8d072 100644 --- a/doc/update/index.md +++ b/doc/update/index.md @@ -265,6 +265,15 @@ NOTE: Specific information that follow related to Ruby and Git versions do not apply to [Omnibus installations](https://docs.gitlab.com/omnibus/) and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with appropriate Ruby and Git versions and are not using system binaries for Ruby and Git. There is no need to install Ruby or Git when utilizing these two approaches. +### 16.1.0 + +- A `MigrateHumanUserType` background migration will be finalized with + the `FinalizeUserTypeMigration` migration. + GitLab 16.0 introduced a [batched background migration](background_migrations.md#batched-background-migrations) to + [migrate `user_type` values from `NULL` to `0`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115849). This + migration may take multiple days to complete on larger GitLab instances. Make sure the migration + has completed successfully before upgrading to 16.1.0. + ### 16.0.0 - Sidekiq jobs are only routed to `default` and `mailers` queues by default, and as a result, diff --git a/doc/user/workspace/index.md b/doc/user/workspace/index.md index 647960459bf..45d9e262bed 100644 --- a/doc/user/workspace/index.md +++ b/doc/user/workspace/index.md @@ -37,6 +37,7 @@ Each workspace includes its own set of dependencies, libraries, and tools, which dns_zone: "workspaces.example.dev" ``` +- You must have at least the Developer role in the root group. - In each public project you want to use this feature for, create a [devfile](#devfile): 1. On the top bar, select **Main menu > Projects** and find your project. 1. In the root directory of your project, create a file named `.devfile.yaml`. You can use one of the [example configurations](#example-configurations). diff --git a/lib/gitlab/database/background_migration/batched_migration.rb b/lib/gitlab/database/background_migration/batched_migration.rb index 2c1a14c56f6..2118393beb0 100644 --- a/lib/gitlab/database/background_migration/batched_migration.rb +++ b/lib/gitlab/database/background_migration/batched_migration.rb @@ -216,7 +216,12 @@ module Gitlab end def health_context - HealthStatus::Context.new(connection, [table_name], gitlab_schema.to_sym) + @health_context ||= Gitlab::Database::HealthStatus::Context.new( + self, + connection, + [table_name], + gitlab_schema.to_sym + ) end def hold!(until_time: 10.minutes.from_now) diff --git a/lib/gitlab/database/background_migration/batched_migration_runner.rb b/lib/gitlab/database/background_migration/batched_migration_runner.rb index 7224ff2b517..e3e8754c758 100644 --- a/lib/gitlab/database/background_migration/batched_migration_runner.rb +++ b/lib/gitlab/database/background_migration/batched_migration_runner.rb @@ -144,7 +144,7 @@ module Gitlab end def adjust_migration(active_migration) - signals = HealthStatus.evaluate(active_migration) + signals = Gitlab::Database::HealthStatus.evaluate(active_migration.health_context) if signals.any?(&:stop?) active_migration.hold! diff --git a/lib/gitlab/database/background_migration/health_status.rb b/lib/gitlab/database/background_migration/health_status.rb deleted file mode 100644 index 96905fd0bc5..00000000000 --- a/lib/gitlab/database/background_migration/health_status.rb +++ /dev/null @@ -1,45 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Database - module BackgroundMigration - module HealthStatus - DEFAULT_INIDICATORS = [ - Indicators::AutovacuumActiveOnTable, - Indicators::WriteAheadLog, - Indicators::PatroniApdex - ].freeze - - # Rather than passing along the migration, we use a more explicitly defined context - Context = Struct.new(:connection, :tables, :gitlab_schema) - - def self.evaluate(migration, indicators = DEFAULT_INIDICATORS) - indicators.map do |indicator| - signal = begin - indicator.new(migration.health_context).evaluate - rescue StandardError => e - Gitlab::ErrorTracking.track_exception(e, migration_id: migration.id, - job_class_name: migration.job_class_name) - - Signals::Unknown.new(indicator, reason: "unexpected error: #{e.message} (#{e.class})") - end - - log_signal(signal, migration) if signal.log_info? - - signal - end - end - - def self.log_signal(signal, migration) - Gitlab::BackgroundMigration::Logger.info( - migration_id: migration.id, - health_status_indicator: signal.indicator_class.to_s, - indicator_signal: signal.short_name, - signal_reason: signal.reason, - message: "#{migration} signaled: #{signal}" - ) - end - end - end - end -end diff --git a/lib/gitlab/database/background_migration/health_status/indicators.rb b/lib/gitlab/database/background_migration/health_status/indicators.rb deleted file mode 100644 index 69503e5b61f..00000000000 --- a/lib/gitlab/database/background_migration/health_status/indicators.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Database - module BackgroundMigration - module HealthStatus - module Indicators - end - end - end - end -end diff --git a/lib/gitlab/database/background_migration/health_status/indicators/autovacuum_active_on_table.rb b/lib/gitlab/database/background_migration/health_status/indicators/autovacuum_active_on_table.rb deleted file mode 100644 index 48e12609a13..00000000000 --- a/lib/gitlab/database/background_migration/health_status/indicators/autovacuum_active_on_table.rb +++ /dev/null @@ -1,41 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Database - module BackgroundMigration - module HealthStatus - module Indicators - class AutovacuumActiveOnTable - def initialize(context) - @context = context - end - - def evaluate - return Signals::NotAvailable.new(self.class, reason: 'indicator disabled') unless enabled? - - autovacuum_active_on = active_autovacuums_for(context.tables) - - if autovacuum_active_on.empty? - Signals::Normal.new(self.class, reason: 'no autovacuum running on any relevant tables') - else - Signals::Stop.new(self.class, reason: "autovacuum running on: #{autovacuum_active_on.join(', ')}") - end - end - - private - - attr_reader :context - - def enabled? - Feature.enabled?(:batched_migrations_health_status_autovacuum, type: :ops) - end - - def active_autovacuums_for(tables) - Gitlab::Database::PostgresAutovacuumActivity.for_tables(tables) - end - end - end - end - end - end -end diff --git a/lib/gitlab/database/background_migration/health_status/indicators/patroni_apdex.rb b/lib/gitlab/database/background_migration/health_status/indicators/patroni_apdex.rb deleted file mode 100644 index 0dd6dd5c2a4..00000000000 --- a/lib/gitlab/database/background_migration/health_status/indicators/patroni_apdex.rb +++ /dev/null @@ -1,90 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Database - module BackgroundMigration - module HealthStatus - module Indicators - class PatroniApdex - include Gitlab::Utils::StrongMemoize - - def initialize(context) - @context = context - end - - def evaluate - return Signals::NotAvailable.new(self.class, reason: 'indicator disabled') unless enabled? - - connection_error_message = fetch_connection_error_message - return unknown_signal(connection_error_message) if connection_error_message.present? - - apdex_sli = fetch_sli(apdex_sli_query) - return unknown_signal('Patroni service apdex can not be calculated') unless apdex_sli.present? - - if apdex_sli.to_f > apdex_slo.to_f - Signals::Normal.new(self.class, reason: 'Patroni service apdex is above SLO') - else - Signals::Stop.new(self.class, reason: 'Patroni service apdex is below SLO') - end - end - - private - - attr_reader :context - - def enabled? - Feature.enabled?(:batched_migrations_health_status_patroni_apdex, type: :ops) - end - - def unknown_signal(reason) - Signals::Unknown.new(self.class, reason: reason) - end - - def fetch_connection_error_message - return 'Patroni Apdex Settings not configured' unless database_apdex_settings.present? - return 'Prometheus client is not ready' unless client.ready? - return 'Apdex SLI query is not configured' unless apdex_sli_query - return 'Apdex SLO is not configured' unless apdex_slo - end - - def client - @client ||= Gitlab::PrometheusClient.new( - database_apdex_settings[:prometheus_api_url], - allow_local_requests: true, - verify: true - ) - end - - def database_apdex_settings - @database_apdex_settings ||= Gitlab::CurrentSettings.database_apdex_settings&.with_indifferent_access - end - - def apdex_sli_query - { - gitlab_main: database_apdex_settings[:apdex_sli_query][:main], - gitlab_ci: database_apdex_settings[:apdex_sli_query][:ci] - }.fetch(context.gitlab_schema.to_sym) - end - strong_memoize_attr :apdex_sli_query - - def apdex_slo - { - gitlab_main: database_apdex_settings[:apdex_slo][:main], - gitlab_ci: database_apdex_settings[:apdex_slo][:ci] - }.fetch(context.gitlab_schema.to_sym) - end - strong_memoize_attr :apdex_slo - - def fetch_sli(query) - response = client.query(query) - metric = response&.first || {} - value = metric.fetch('value', []) - - Array.wrap(value).second - end - end - end - end - end - end -end diff --git a/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log.rb b/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log.rb deleted file mode 100644 index d2fb0a8b751..00000000000 --- a/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log.rb +++ /dev/null @@ -1,74 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Database - module BackgroundMigration - module HealthStatus - module Indicators - class WriteAheadLog - include Gitlab::Utils::StrongMemoize - - LIMIT = 42 - PENDING_WAL_COUNT_SQL = <<~SQL - WITH - current_wal_file AS ( - SELECT pg_walfile_name(pg_current_wal_insert_lsn()) AS pg_walfile_name - ), - current_wal AS ( - SELECT - ('x' || substring(pg_walfile_name, 9, 8))::bit(32)::int AS log, - ('x' || substring(pg_walfile_name, 17, 8))::bit(32)::int AS seg, - pg_walfile_name - FROM current_wal_file - ), - archive_wal AS ( - SELECT - ('x' || substring(last_archived_wal, 9, 8))::bit(32)::int AS log, - ('x' || substring(last_archived_wal, 17, 8))::bit(32)::int AS seg, - last_archived_wal - FROM pg_stat_archiver - ) - SELECT ((current_wal.log - archive_wal.log) * 256) + (current_wal.seg - archive_wal.seg) AS pending_wal_count - FROM current_wal, archive_wal - SQL - - def initialize(context) - @connection = context.connection - end - - def evaluate - return Signals::NotAvailable.new(self.class, reason: 'indicator disabled') unless enabled? - - unless pending_wal_count - return Signals::NotAvailable.new(self.class, reason: 'WAL archive queue can not be calculated') - end - - if pending_wal_count > LIMIT - Signals::Stop.new(self.class, reason: "WAL archive queue is too big") - else - Signals::Normal.new(self.class, reason: 'WAL archive queue is within limit') - end - end - - private - - attr_reader :connection - - def enabled? - Feature.enabled?(:batched_migrations_health_status_wal, type: :ops) - end - - # Returns number of WAL segments pending archival - def pending_wal_count - strong_memoize(:pending_wal_count) do - Gitlab::Database::LoadBalancing::Session.current.use_primary do - connection.execute(PENDING_WAL_COUNT_SQL).to_a.first&.fetch('pending_wal_count') - end - end - end - end - end - end - end - end -end diff --git a/lib/gitlab/database/background_migration/health_status/signals.rb b/lib/gitlab/database/background_migration/health_status/signals.rb deleted file mode 100644 index 534c4330cf2..00000000000 --- a/lib/gitlab/database/background_migration/health_status/signals.rb +++ /dev/null @@ -1,71 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Database - module BackgroundMigration - module HealthStatus - module Signals - # Base class for a signal - class Base - attr_reader :indicator_class, :reason - - def initialize(indicator_class, reason:) - @indicator_class = indicator_class - @reason = reason - end - - def to_s - "#{short_name} (indicator: #{indicator_class}; reason: #{reason})" - end - - # :nocov: - def log_info? - false - end - - def stop? - false - end - # :nocov: - - def short_name - self.class.name.demodulize - end - end - - # A Signals::Stop is an indication to put a migration on hold or stop it entirely: - # In general, we want to slow down or pause the migration. - class Stop < Base - # :nocov: - def log_info? - true - end - - def stop? - true - end - # :nocov: - end - - # A Signals::Normal indicates normal system state: We carry on with the migration - # and may even attempt to optimize its throughput etc. - class Normal < Base; end - - # When given an Signals::Unknown, something unexpected happened while - # we evaluated system indicators. - class Unknown < Base - # :nocov: - def log_info? - true - end - # :nocov: - end - - # No signal could be determined, e.g. because the indicator - # was disabled. - class NotAvailable < Base; end - end - end - end - end -end diff --git a/lib/gitlab/database/health_status.rb b/lib/gitlab/database/health_status.rb new file mode 100644 index 00000000000..69bb8a70afd --- /dev/null +++ b/lib/gitlab/database/health_status.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module HealthStatus + DEFAULT_INIDICATORS = [ + Indicators::AutovacuumActiveOnTable, + Indicators::WriteAheadLog, + Indicators::PatroniApdex + ].freeze + + class << self + def evaluate(context, indicators = DEFAULT_INIDICATORS) + indicators.map do |indicator| + signal = begin + indicator.new(context).evaluate + rescue StandardError => e + Gitlab::ErrorTracking.track_exception(e, **context.status_checker_info) + + Signals::Unknown.new(indicator, reason: "unexpected error: #{e.message} (#{e.class})") + end + + log_signal(signal, context) if signal.log_info? + + signal + end + end + + def log_signal(signal, context) + Gitlab::Database::HealthStatus::Logger.info(**context.status_checker_info.merge( + health_status_indicator: signal.indicator_class.to_s, + indicator_signal: signal.short_name, + signal_reason: signal.reason, + message: "#{context.status_checker} signaled: #{signal}" + )) + end + end + end + end +end diff --git a/lib/gitlab/database/health_status/context.rb b/lib/gitlab/database/health_status/context.rb new file mode 100644 index 00000000000..a1d9efead1f --- /dev/null +++ b/lib/gitlab/database/health_status/context.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module HealthStatus + class Context + attr_reader :status_checker, :connection, :tables, :gitlab_schema + + # status_checker: the caller object which checks for database health status + # eg: batched_migration + def initialize(status_checker, connection, tables, gitlab_schema) + @status_checker = status_checker + @connection = connection + @tables = tables + @gitlab_schema = gitlab_schema + end + + def status_checker_info + data = { + status_checker_id: status_checker.id, + status_checker_type: status_checker.class.name + } + + if status_checker.is_a?(Gitlab::Database::BackgroundMigration::BatchedMigration) + data[:job_class_name] = status_checker.job_class_name + end + + data + end + end + end + end +end diff --git a/lib/gitlab/database/health_status/indicators.rb b/lib/gitlab/database/health_status/indicators.rb new file mode 100644 index 00000000000..a149c36aae4 --- /dev/null +++ b/lib/gitlab/database/health_status/indicators.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module HealthStatus + module Indicators + end + end + end +end diff --git a/lib/gitlab/database/health_status/indicators/autovacuum_active_on_table.rb b/lib/gitlab/database/health_status/indicators/autovacuum_active_on_table.rb new file mode 100644 index 00000000000..6bf2bbf0c70 --- /dev/null +++ b/lib/gitlab/database/health_status/indicators/autovacuum_active_on_table.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module HealthStatus + module Indicators + class AutovacuumActiveOnTable + def initialize(context) + @tables = context.tables + end + + def evaluate + return Signals::NotAvailable.new(self.class, reason: 'indicator disabled') unless enabled? + + autovacuum_active_on = active_autovacuums_for(tables) + + if autovacuum_active_on.empty? + Signals::Normal.new(self.class, reason: 'no autovacuum running on any relevant tables') + else + Signals::Stop.new(self.class, reason: "autovacuum running on: #{autovacuum_active_on.join(', ')}") + end + end + + private + + attr_reader :tables + + def enabled? + Feature.enabled?(:batched_migrations_health_status_autovacuum, type: :ops) + end + + def active_autovacuums_for(tables) + Gitlab::Database::PostgresAutovacuumActivity.for_tables(tables) + end + end + end + end + end +end diff --git a/lib/gitlab/database/health_status/indicators/patroni_apdex.rb b/lib/gitlab/database/health_status/indicators/patroni_apdex.rb new file mode 100644 index 00000000000..680c86cf7b2 --- /dev/null +++ b/lib/gitlab/database/health_status/indicators/patroni_apdex.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module HealthStatus + module Indicators + class PatroniApdex + include Gitlab::Utils::StrongMemoize + + def initialize(context) + @gitlab_schema = context.gitlab_schema.to_sym + end + + def evaluate + return Signals::NotAvailable.new(self.class, reason: 'indicator disabled') unless enabled? + + connection_error_message = fetch_connection_error_message + return unknown_signal(connection_error_message) if connection_error_message.present? + + apdex_sli = fetch_sli(apdex_sli_query) + return unknown_signal('Patroni service apdex can not be calculated') unless apdex_sli.present? + + if apdex_sli.to_f > apdex_slo.to_f + Signals::Normal.new(self.class, reason: 'Patroni service apdex is above SLO') + else + Signals::Stop.new(self.class, reason: 'Patroni service apdex is below SLO') + end + end + + private + + attr_reader :gitlab_schema + + def enabled? + Feature.enabled?(:batched_migrations_health_status_patroni_apdex, type: :ops) + end + + def unknown_signal(reason) + Signals::Unknown.new(self.class, reason: reason) + end + + def fetch_connection_error_message + return 'Patroni Apdex Settings not configured' unless database_apdex_settings.present? + return 'Prometheus client is not ready' unless client.ready? + return 'Apdex SLI query is not configured' unless apdex_sli_query + return 'Apdex SLO is not configured' unless apdex_slo + end + + def client + @client ||= Gitlab::PrometheusClient.new( + database_apdex_settings[:prometheus_api_url], + allow_local_requests: true, + verify: true + ) + end + + def database_apdex_settings + @database_apdex_settings ||= Gitlab::CurrentSettings.database_apdex_settings&.with_indifferent_access + end + + def apdex_sli_query + { + gitlab_main: database_apdex_settings[:apdex_sli_query][:main], + gitlab_ci: database_apdex_settings[:apdex_sli_query][:ci] + }.fetch(gitlab_schema) + end + strong_memoize_attr :apdex_sli_query + + def apdex_slo + { + gitlab_main: database_apdex_settings[:apdex_slo][:main], + gitlab_ci: database_apdex_settings[:apdex_slo][:ci] + }.fetch(gitlab_schema) + end + strong_memoize_attr :apdex_slo + + def fetch_sli(query) + response = client.query(query) + metric = response&.first || {} + value = metric.fetch('value', []) + + Array.wrap(value).second + end + end + end + end + end +end diff --git a/lib/gitlab/database/health_status/indicators/write_ahead_log.rb b/lib/gitlab/database/health_status/indicators/write_ahead_log.rb new file mode 100644 index 00000000000..1614b17df48 --- /dev/null +++ b/lib/gitlab/database/health_status/indicators/write_ahead_log.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module HealthStatus + module Indicators + class WriteAheadLog + include Gitlab::Utils::StrongMemoize + + LIMIT = 42 + PENDING_WAL_COUNT_SQL = <<~SQL + WITH + current_wal_file AS ( + SELECT pg_walfile_name(pg_current_wal_insert_lsn()) AS pg_walfile_name + ), + current_wal AS ( + SELECT + ('x' || substring(pg_walfile_name, 9, 8))::bit(32)::int AS log, + ('x' || substring(pg_walfile_name, 17, 8))::bit(32)::int AS seg, + pg_walfile_name + FROM current_wal_file + ), + archive_wal AS ( + SELECT + ('x' || substring(last_archived_wal, 9, 8))::bit(32)::int AS log, + ('x' || substring(last_archived_wal, 17, 8))::bit(32)::int AS seg, + last_archived_wal + FROM pg_stat_archiver + ) + SELECT ((current_wal.log - archive_wal.log) * 256) + (current_wal.seg - archive_wal.seg) AS pending_wal_count + FROM current_wal, archive_wal + SQL + + def initialize(context) + @connection = context.connection + end + + def evaluate + return Signals::NotAvailable.new(self.class, reason: 'indicator disabled') unless enabled? + + unless pending_wal_count + return Signals::NotAvailable.new(self.class, reason: 'WAL archive queue can not be calculated') + end + + if pending_wal_count > LIMIT + Signals::Stop.new(self.class, reason: "WAL archive queue is too big") + else + Signals::Normal.new(self.class, reason: 'WAL archive queue is within limit') + end + end + + private + + attr_reader :connection + + def enabled? + Feature.enabled?(:batched_migrations_health_status_wal, type: :ops) + end + + # Returns number of WAL segments pending archival + def pending_wal_count + Gitlab::Database::LoadBalancing::Session.current.use_primary do + connection.execute(PENDING_WAL_COUNT_SQL).to_a.first&.fetch('pending_wal_count') + end + end + strong_memoize_attr :pending_wal_count + end + end + end + end +end diff --git a/lib/gitlab/database/health_status/logger.rb b/lib/gitlab/database/health_status/logger.rb new file mode 100644 index 00000000000..820c1aeb695 --- /dev/null +++ b/lib/gitlab/database/health_status/logger.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module HealthStatus + class Logger < ::Gitlab::JsonLogger + exclude_context! + + def self.file_name_noext + 'database_health_status' + end + end + end + end +end diff --git a/lib/gitlab/database/health_status/signals.rb b/lib/gitlab/database/health_status/signals.rb new file mode 100644 index 00000000000..e1bcdcae9c7 --- /dev/null +++ b/lib/gitlab/database/health_status/signals.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module HealthStatus + module Signals + # Base class for a signal + class Base + attr_reader :indicator_class, :reason + + def initialize(indicator_class, reason:) + @indicator_class = indicator_class + @reason = reason + end + + def to_s + "#{short_name} (indicator: #{indicator_class}; reason: #{reason})" + end + + def log_info? + false + end + + def stop? + false + end + + def short_name + self.class.name.demodulize + end + end + + # A Signals::Stop is an indication to put a migration on hold or stop it entirely: + # In general, we want to slow down or pause the migration. + class Stop < Base + def log_info? + true + end + + def stop? + true + end + end + + # A Signals::Normal indicates normal system state: We carry on with the migration + # and may even attempt to optimize its throughput etc. + class Normal < Base; end + + # When given an Signals::Unknown, something unexpected happened while + # we evaluated system indicators. + class Unknown < Base + def log_info? + true + end + end + + # No signal could be determined, e.g. because the indicator + # was disabled. + class NotAvailable < Base; end + end + end + end +end diff --git a/lib/tasks/frontend.rake b/lib/tasks/frontend.rake index e768c42736d..a6754f13089 100644 --- a/lib/tasks/frontend.rake +++ b/lib/tasks/frontend.rake @@ -18,30 +18,12 @@ unless Rails.env.production? t.rspec_opts = '--format documentation' end - desc 'GitLab | Frontend | Generate fixtures for JavaScript integration tests' - RSpec::Core::RakeTask.new(:mock_server_rspec_fixtures) do |t, args| - require 'yaml' - - base_path = Pathname.new('spec/frontend_integration/fixture_generators.yml') - ee_path = Pathname.new('ee') + base_path - - fixtures = YAML.safe_load(base_path.read) - fixtures.concat(Array(YAML.safe_load(ee_path.read))) if Gitlab.ee? && ee_path.exist? - - t.pattern = fixtures.join(',') - ENV['NO_KNAPSACK'] = 'true' - t.rspec_opts = '--format documentation' - end - desc 'GitLab | Frontend | Run JavaScript tests' task tests: ['yarn:check'] do sh "yarn test" do |ok, res| abort('rake frontend:tests failed') unless ok end end - - desc 'GitLab | Frontend | Shortcut for generating all fixtures used by MirajeJS mock server' - task mock_server_fixtures: ['frontend:mock_server_rspec_fixtures', 'gitlab:graphql:schema:dump'] end desc 'GitLab | Frontend | Shortcut for frontend:fixtures and frontend:tests' diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 487cc4e1a4d..8df4d6eeffb 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -38419,6 +38419,9 @@ msgid_plural "Requires %{count} approvals from %{names}." msgstr[0] "" msgstr[1] "" +msgid "Requires a verified GitLab email address." +msgstr "" + msgid "Requires values to meet regular expression requirements." msgstr "" diff --git a/scripts/frontend/start_storybook.sh b/scripts/frontend/start_storybook.sh index 7ae0a21b15b..622e35f5483 100755 --- a/scripts/frontend/start_storybook.sh +++ b/scripts/frontend/start_storybook.sh @@ -3,14 +3,6 @@ bold=$(tput bold) normal=$(tput sgr0) -echo -e "Storybook provides a mock server that allows creating stories for components that make HTTP requests." -echo -e "${bold}Storybook will fail to start if it can’t find the fixtures used by the mock server.${normal}\n" -read -rp "Would you like to generate/update the frontend fixtures used by the mock server (y/N)? " answer - -if [[ "$answer" =~ ^(Y|y)$ ]] ; then - bundle exec rake frontend:mock_server_fixtures -fi - if ! [[ -d storybook/node_modules ]] ; then yarn storybook:install fi diff --git a/scripts/utils.sh b/scripts/utils.sh index 66512798a11..40cf6716528 100644 --- a/scripts/utils.sh +++ b/scripts/utils.sh @@ -114,6 +114,8 @@ function yarn_install_script() { retry yarn install --frozen-lockfile + retry yarn storybook:install --frozen-lockfile + section_end "yarn-install" } @@ -290,6 +292,13 @@ function fail_pipeline_early() { fi } +function danger_as_local() { + # Force danger to skip CI source GitLab and fallback to "local only git repo". + unset GITLAB_CI + # We need to base SHA to help danger determine the base commit for this shallow clone. + bundle exec danger dry_run --fail-on-errors=true --verbose --base="${CI_MERGE_REQUEST_DIFF_BASE_SHA}" --head="${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA:-$CI_COMMIT_SHA}" --dangerfile="${DANGER_DANGERFILE:-Dangerfile}" +} + # We're inlining this function in `.gitlab/ci/package-and-test/main.gitlab-ci.yml` so make sure to reflect any changes there function assets_image_tag() { local cache_assets_hash_file="cached-assets-hash.txt" diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb index 4ef2e7f936b..0faa468233d 100644 --- a/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb +++ b/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do +RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner, feature_category: :database do let(:connection) { Gitlab::Database.database_base_models[:main].connection } let(:migration_wrapper) { double('test wrapper') } @@ -15,8 +15,8 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do end before do - normal_signal = instance_double(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Normal, stop?: false) - allow(Gitlab::Database::BackgroundMigration::HealthStatus).to receive(:evaluate).and_return([normal_signal]) + normal_signal = instance_double(Gitlab::Database::HealthStatus::Signals::Normal, stop?: false) + allow(Gitlab::Database::HealthStatus).to receive(:evaluate).and_return([normal_signal]) end describe '#run_migration_job' do @@ -65,7 +65,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do end context 'migration health' do - let(:health_status) { Gitlab::Database::BackgroundMigration::HealthStatus } + let(:health_status) { Gitlab::Database::HealthStatus } let(:stop_signal) { health_status::Signals::Stop.new(:indicator, reason: 'Take a break') } let(:normal_signal) { health_status::Signals::Normal.new(:indicator, reason: 'All good') } let(:not_available_signal) { health_status::Signals::NotAvailable.new(:indicator, reason: 'Indicator is disabled') } diff --git a/spec/lib/gitlab/database/background_migration/health_status/indicators/autovacuum_active_on_table_spec.rb b/spec/lib/gitlab/database/health_status/indicators/autovacuum_active_on_table_spec.rb index 1c0f5a0c420..cd145bd5c0f 100644 --- a/spec/lib/gitlab/database/background_migration/health_status/indicators/autovacuum_active_on_table_spec.rb +++ b/spec/lib/gitlab/database/health_status/indicators/autovacuum_active_on_table_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators::AutovacuumActiveOnTable, +RSpec.describe Gitlab::Database::HealthStatus::Indicators::AutovacuumActiveOnTable, feature_category: :database do include Database::DatabaseHelpers @@ -23,11 +23,18 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: let(:tables) { [table] } let(:table) { 'users' } - let(:context) { Gitlab::Database::BackgroundMigration::HealthStatus::Context.new(connection, tables) } + let(:context) do + Gitlab::Database::HealthStatus::Context.new( + described_class, + connection, + tables, + :gitlab_main + ) + end context 'without autovacuum activity' do it 'returns Normal signal' do - expect(subject).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Normal) + expect(subject).to be_a(Gitlab::Database::HealthStatus::Signals::Normal) end it 'remembers the indicator class' do @@ -41,7 +48,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: end it 'returns Stop signal' do - expect(subject).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Stop) + expect(subject).to be_a(Gitlab::Database::HealthStatus::Signals::Stop) end it 'explains why' do @@ -55,7 +62,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: it 'returns NoSignal signal in case the feature flag is disabled' do stub_feature_flags(batched_migrations_health_status_autovacuum: false) - expect(subject).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::NotAvailable) + expect(subject).to be_a(Gitlab::Database::HealthStatus::Signals::NotAvailable) end end end diff --git a/spec/lib/gitlab/database/background_migration/health_status/indicators/patroni_apdex_spec.rb b/spec/lib/gitlab/database/health_status/indicators/patroni_apdex_spec.rb index d3102a105ea..e0e3a0a7c23 100644 --- a/spec/lib/gitlab/database/background_migration/health_status/indicators/patroni_apdex_spec.rb +++ b/spec/lib/gitlab/database/health_status/indicators/patroni_apdex_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators::PatroniApdex, :aggregate_failures, feature_category: :database do # rubocop:disable Layout/LineLength +RSpec.describe Gitlab::Database::HealthStatus::Indicators::PatroniApdex, :aggregate_failures, feature_category: :database do # rubocop:disable Layout/LineLength let(:schema) { :main } let(:connection) { Gitlab::Database.database_base_models[schema].connection } @@ -19,8 +19,12 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: let(:prometheus_client) { instance_double(Gitlab::PrometheusClient) } let(:context) do - Gitlab::Database::BackgroundMigration::HealthStatus::Context - .new(connection, ['users'], gitlab_schema) + Gitlab::Database::HealthStatus::Context.new( + described_class, + connection, + ['users'], + gitlab_schema + ) end let(:gitlab_schema) { "gitlab_#{schema}" } @@ -61,7 +65,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: it 'returns NoSignal signal in case the feature flag is disabled' do stub_feature_flags(batched_migrations_health_status_patroni_apdex: false) - expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::NotAvailable) + expect(evaluate).to be_a(Gitlab::Database::HealthStatus::Signals::NotAvailable) expect(evaluate.reason).to include('indicator disabled') end @@ -69,7 +73,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: let(:database_apdex_settings) { nil } it 'returns Unknown signal' do - expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Unknown) + expect(evaluate).to be_a(Gitlab::Database::HealthStatus::Signals::Unknown) expect(evaluate.reason).to include('Patroni Apdex Settings not configured') end end @@ -78,7 +82,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: let(:client_ready) { false } it 'returns Unknown signal' do - expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Unknown) + expect(evaluate).to be_a(Gitlab::Database::HealthStatus::Signals::Unknown) expect(evaluate.reason).to include('Prometheus client is not ready') end end @@ -87,7 +91,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: let(:"database_apdex_sli_query_#{schema}") { nil } it 'returns Unknown signal' do - expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Unknown) + expect(evaluate).to be_a(Gitlab::Database::HealthStatus::Signals::Unknown) expect(evaluate.reason).to include('Apdex SLI query is not configured') end end @@ -96,7 +100,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: let(:"database_apdex_slo_#{schema}") { nil } it 'returns Unknown signal' do - expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Unknown) + expect(evaluate).to be_a(Gitlab::Database::HealthStatus::Signals::Unknown) expect(evaluate.reason).to include('Apdex SLO is not configured') end end @@ -105,7 +109,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: expect(prometheus_client).to receive(:query) .with(send("database_apdex_sli_query_#{schema}")) .and_return([{ "value" => [1662423310.878, apdex_slo_above_sli[schema]] }]) - expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Normal) + expect(evaluate).to be_a(Gitlab::Database::HealthStatus::Signals::Normal) expect(evaluate.reason).to include('Patroni service apdex is above SLO') end @@ -113,7 +117,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: expect(prometheus_client).to receive(:query) .with(send("database_apdex_sli_query_#{schema}")) .and_return([{ "value" => [1662423310.878, apdex_slo_below_sli[schema]] }]) - expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Stop) + expect(evaluate).to be_a(Gitlab::Database::HealthStatus::Signals::Stop) expect(evaluate.reason).to include('Patroni service apdex is below SLO') end @@ -131,7 +135,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: with_them do it 'returns Unknown signal' do expect(prometheus_client).to receive(:query).and_return(result) - expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Unknown) + expect(evaluate).to be_a(Gitlab::Database::HealthStatus::Signals::Unknown) expect(evaluate.reason).to include('Patroni service apdex can not be calculated') end end diff --git a/spec/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log_spec.rb b/spec/lib/gitlab/database/health_status/indicators/write_ahead_log_spec.rb index 650f11e3cd5..aa2aee4f94a 100644 --- a/spec/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log_spec.rb +++ b/spec/lib/gitlab/database/health_status/indicators/write_ahead_log_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators::WriteAheadLog do +RSpec.describe Gitlab::Database::HealthStatus::Indicators::WriteAheadLog, feature_category: :database do let(:connection) { Gitlab::Database.database_base_models[:main].connection } around do |example| @@ -14,7 +14,14 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: describe '#evaluate' do let(:tables) { [table] } let(:table) { 'users' } - let(:context) { Gitlab::Database::BackgroundMigration::HealthStatus::Context.new(connection, tables) } + let(:context) do + Gitlab::Database::HealthStatus::Context.new( + described_class, + connection, + tables, + :gitlab_main + ) + end subject(:evaluate) { described_class.new(context).evaluate } @@ -25,14 +32,14 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: it 'returns NoSignal signal in case the feature flag is disabled' do stub_feature_flags(batched_migrations_health_status_wal: false) - expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::NotAvailable) + expect(evaluate).to be_a(Gitlab::Database::HealthStatus::Signals::NotAvailable) expect(evaluate.reason).to include('indicator disabled') end it 'returns NoSignal signal when WAL archive queue can not be calculated' do expect(connection).to receive(:execute).and_return([{ 'pending_wal_count' => nil }]) - expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::NotAvailable) + expect(evaluate).to be_a(Gitlab::Database::HealthStatus::Signals::NotAvailable) expect(evaluate.reason).to include('WAL archive queue can not be calculated') end @@ -45,7 +52,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: context 'when WAL archive queue size is below the limit' do it 'returns Normal signal' do expect(connection).to receive(:execute).and_return([{ 'pending_wal_count' => 1 }]) - expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Normal) + expect(evaluate).to be_a(Gitlab::Database::HealthStatus::Signals::Normal) expect(evaluate.reason).to include('WAL archive queue is within limit') end end @@ -53,7 +60,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators:: context 'when WAL archive queue size is above the limit' do it 'returns Stop signal' do expect(connection).to receive(:execute).and_return([{ 'pending_wal_count' => 420 }]) - expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Stop) + expect(evaluate).to be_a(Gitlab::Database::HealthStatus::Signals::Stop) expect(evaluate.reason).to include('WAL archive queue is too big') end end diff --git a/spec/lib/gitlab/database/health_status/logger_spec.rb b/spec/lib/gitlab/database/health_status/logger_spec.rb new file mode 100644 index 00000000000..5ae6b40cb3a --- /dev/null +++ b/spec/lib/gitlab/database/health_status/logger_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::HealthStatus::Logger, feature_category: :database do + subject { described_class.new('/dev/null') } + + it_behaves_like 'a json logger', {} + + it 'excludes context' do + expect(described_class.exclude_context?).to be(true) + end +end diff --git a/spec/lib/gitlab/database/health_status/signals_spec.rb b/spec/lib/gitlab/database/health_status/signals_spec.rb new file mode 100644 index 00000000000..5bfd8ffb91e --- /dev/null +++ b/spec/lib/gitlab/database/health_status/signals_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::HealthStatus::Signals, feature_category: :database do + shared_examples 'health status signal' do |subclass, stop_signal, log_signal| + let(:indicator) { instance_double('Gitlab::Database::HealthStatus::Indicators::PatroniApdex') } + let(:reason) { 'Test reason' } + + subject { subclass.new(indicator, reason: reason) } + + describe '#log_info?' do + it 'returns the log signal' do + expect(subject.log_info?).to eq(log_signal) + end + end + + describe '#stop?' do + it 'returns the stop signal' do + expect(subject.stop?).to eq(stop_signal) + end + end + end + + context 'with Stop signal it should stop and log' do + it_behaves_like 'health status signal', described_class::Stop, true, true + end + + context 'with Normal signal it should not stop and log' do + it_behaves_like 'health status signal', described_class::Normal, false, false + end + + context 'with NotAvailable signal it should not stop and log' do + it_behaves_like 'health status signal', described_class::NotAvailable, false, false + end + + context 'with Unknown signal it should only log and not stop' do + it_behaves_like 'health status signal', described_class::Unknown, false, true + end +end diff --git a/spec/lib/gitlab/database/background_migration/health_status_spec.rb b/spec/lib/gitlab/database/health_status_spec.rb index 4d6c729f080..8d7717beaff 100644 --- a/spec/lib/gitlab/database/background_migration/health_status_spec.rb +++ b/spec/lib/gitlab/database/health_status_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus, feature_category: :database do +RSpec.describe Gitlab::Database::HealthStatus, feature_category: :database do let(:connection) { Gitlab::Database.database_base_models[:main].connection } around do |example| @@ -12,11 +12,11 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus, feature_cate end describe '.evaluate' do - subject(:evaluate) { described_class.evaluate(migration, [autovacuum_indicator_class]) } + subject(:evaluate) { described_class.evaluate(migration.health_context, [autovacuum_indicator_class]) } let(:migration) { build(:batched_background_migration, :active) } - let(:health_status) { Gitlab::Database::BackgroundMigration::HealthStatus } + let(:health_status) { described_class } let(:autovacuum_indicator_class) { health_status::Indicators::AutovacuumActiveOnTable } let(:wal_indicator_class) { health_status::Indicators::WriteAheadLog } let(:patroni_apdex_indicator_class) { health_status::Indicators::PatroniApdex } @@ -29,7 +29,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus, feature_cate end context 'with default indicators' do - subject(:evaluate) { described_class.evaluate(migration) } + subject(:evaluate) { described_class.evaluate(migration.health_context) } it 'returns a collection of signals' do normal_signal = instance_double("#{health_status}::Signals::Normal", log_info?: false) @@ -65,8 +65,10 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus, feature_cate expect(autovacuum_indicator).to receive(:evaluate).and_return(signal) - expect(Gitlab::BackgroundMigration::Logger).to receive(:info).with( - migration_id: migration.id, + expect(Gitlab::Database::HealthStatus::Logger).to receive(:info).with( + status_checker_id: migration.id, + status_checker_type: 'Gitlab::Database::BackgroundMigration::BatchedMigration', + job_class_name: migration.job_class_name, health_status_indicator: autovacuum_indicator_class.to_s, indicator_signal: 'Stop', signal_reason: 'Test Exception', @@ -89,7 +91,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus, feature_cate let(:error) { RuntimeError.new('everything broken') } before do - expect(autovacuum_indicator).to receive(:evaluate).and_raise(error) + allow(autovacuum_indicator).to receive(:evaluate).and_raise(error) end it 'does not fail' do @@ -99,13 +101,18 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus, feature_cate it 'returns Unknown signal' do signal = evaluate.first - expect(signal).to be_an_instance_of(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Unknown) + expect(signal).to be_an_instance_of(Gitlab::Database::HealthStatus::Signals::Unknown) expect(signal.reason).to eq("unexpected error: everything broken (RuntimeError)") end it 'reports the exception to error tracking' do expect(Gitlab::ErrorTracking).to receive(:track_exception) - .with(error, migration_id: migration.id, job_class_name: migration.job_class_name) + .with( + error, + status_checker_id: migration.id, + status_checker_type: 'Gitlab::Database::BackgroundMigration::BatchedMigration', + job_class_name: migration.job_class_name + ) evaluate end diff --git a/spec/migrations/20230523101514_finalize_user_type_migration_spec.rb b/spec/migrations/20230523101514_finalize_user_type_migration_spec.rb new file mode 100644 index 00000000000..abf3a506748 --- /dev/null +++ b/spec/migrations/20230523101514_finalize_user_type_migration_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe FinalizeUserTypeMigration, feature_category: :devops_reports do + it 'finalizes MigrateHumanUserType migration' do + expect(described_class).to be_finalize_background_migration_of('MigrateHumanUserType') + + migrate! + end +end diff --git a/spec/support/shared_examples/workers/batched_background_migration_worker_shared_examples.rb b/spec/support/shared_examples/workers/batched_background_migration_worker_shared_examples.rb index 975c7a7447c..e7385f9abb6 100644 --- a/spec/support/shared_examples/workers/batched_background_migration_worker_shared_examples.rb +++ b/spec/support/shared_examples/workers/batched_background_migration_worker_shared_examples.rb @@ -331,8 +331,8 @@ RSpec.shared_examples 'it runs batched background migration jobs' do |tracking_d end it 'puts migration on hold when the pending WAL count is above the limit' do - sql = Gitlab::Database::BackgroundMigration::HealthStatus::Indicators::WriteAheadLog::PENDING_WAL_COUNT_SQL - limit = Gitlab::Database::BackgroundMigration::HealthStatus::Indicators::WriteAheadLog::LIMIT + sql = Gitlab::Database::HealthStatus::Indicators::WriteAheadLog::PENDING_WAL_COUNT_SQL + limit = Gitlab::Database::HealthStatus::Indicators::WriteAheadLog::LIMIT expect(connection).to receive(:execute).with(sql).and_return([{ 'pending_wal_count' => limit + 1 }]) diff --git a/storybook/.env.template b/storybook/.env.template new file mode 100644 index 00000000000..ed4d39132e3 --- /dev/null +++ b/storybook/.env.template @@ -0,0 +1,2 @@ +API_ACCESS_TOKEN="api-token" +GITLAB_URL="http://gdk.test:3000" diff --git a/storybook/.eslintrc.yml b/storybook/.eslintrc.yml new file mode 100644 index 00000000000..f3bbec8f26d --- /dev/null +++ b/storybook/.eslintrc.yml @@ -0,0 +1,8 @@ +rules: + '@gitlab/require-i18n-strings': off + import/no-extraneous-dependencies: off + import/no-commonjs: off + import/no-nodejs-modules: off + filenames/match-regex: off + no-console: off + import/no-unresolved: off diff --git a/storybook/.gitignore b/storybook/.gitignore index 18d5e871aaa..d636a68c7a4 100644 --- a/storybook/.gitignore +++ b/storybook/.gitignore @@ -1,2 +1,3 @@ node_modules/ -public/
\ No newline at end of file +public/ +.env diff --git a/storybook/config/addons/gitlab_api_access/constants.js b/storybook/config/addons/gitlab_api_access/constants.js new file mode 100644 index 00000000000..a925557bf62 --- /dev/null +++ b/storybook/config/addons/gitlab_api_access/constants.js @@ -0,0 +1,5 @@ +export const ADDON_ID = 'gitlab-api-access'; +export const STATE_ID = `${ADDON_ID}/state`; +export const PANEL_ID = `${ADDON_ID}/panel`; + +export const GITLAB_API_ACCESS_UPDATE_EVENT = 'gitlab-api-access.update'; diff --git a/storybook/config/addons/gitlab_api_access/manager.js b/storybook/config/addons/gitlab_api_access/manager.js new file mode 100644 index 00000000000..77d97c76ee2 --- /dev/null +++ b/storybook/config/addons/gitlab_api_access/manager.js @@ -0,0 +1,69 @@ +import React from 'react'; +import { addons, types } from '@storybook/addons'; +import { useAddonState } from '@storybook/api'; +import { AddonPanel, Form } from '@storybook/components'; +import { ADDON_ID, STATE_ID, PANEL_ID, GITLAB_API_ACCESS_UPDATE_EVENT } from './constants'; + +/** + * GitLab API Access is a Storybook extension that allows testing + * UI components that depend on GitLab's REST or GraphQL APIs. + * + * Read https://docs.gitlab.com/ee/development/fe_guide/storybook + * for more information. + */ +const h = React.createElement.bind(React); + +// give a unique name for the panel +const GitLabAPIParametersPanel = () => { + const channel = addons.getChannel(); + const [state, setState] = useAddonState(STATE_ID, { + gitlabURL: process.env.GITLAB_URL, + accessToken: process.env.API_ACCESS_TOKEN, + }); + const updateState = (params) => { + const newState = { + ...state, + ...params, + }; + + setState(newState); + + channel.emit(GITLAB_API_ACCESS_UPDATE_EVENT, newState); + }; + + const updateGitLabURL = (e) => { + updateState({ gitlabURL: e.target.value }); + }; + + const updateAccessToken = (e) => { + updateState({ accessToken: e.target.value }); + }; + + channel.emit(GITLAB_API_ACCESS_UPDATE_EVENT, state); + + return h('div', {}, [ + h(Form.Field, { label: 'GitLab URL' }, [ + h(Form.Input, { + type: 'text', + value: state.gitlabURL, + placeholder: 'https://gitlab.com', + onChange: (e) => updateGitLabURL(e), + }), + ]), + h(Form.Field, { label: 'GitLab access token' }, [ + h(Form.Input, { + type: 'password', + value: state.accessToken, + onChange: (e) => updateAccessToken(e), + }), + ]), + ]); +}; + +addons.register(ADDON_ID, () => { + addons.add(PANEL_ID, { + type: types.PANEL, + title: 'GitLab API Access', + render: ({ active, key }) => h(AddonPanel, { active, key }, [h(GitLabAPIParametersPanel)]), + }); +}); diff --git a/storybook/config/addons/gitlab_api_access/preview.js b/storybook/config/addons/gitlab_api_access/preview.js new file mode 100644 index 00000000000..6daeedd0179 --- /dev/null +++ b/storybook/config/addons/gitlab_api_access/preview.js @@ -0,0 +1,83 @@ +import { addons } from '@storybook/addons'; +import { FORCE_REMOUNT } from '@storybook/core-events'; +import axios from '~/lib/utils/axios_utils'; +import createDefaultClient from '~/lib/graphql'; +import VueApollo from 'vue-apollo'; +import { GITLAB_API_ACCESS_UPDATE_EVENT } from './constants'; + +/** + * GitLab API Access is a Storybook extension that allows testing + * UI components that depend on GitLab's REST or GraphQL APIs. + * + * Read https://docs.gitlab.com/ee/development/fe_guide/storybook + * for more information. + */ +const channel = addons.getChannel(); +let gitlabApiAccessParams; +let refreshApolloClient = false; +let apolloClient = null; + +const setGitLabAPIAccessParams = ({ gitlabURL, accessToken }) => { + window.gon.relative_url_root = gitlabURL; + + axios.defaults.headers.common['PRIVATE-TOKEN'] = accessToken; + gitlabApiAccessParams = { gitlabURL, accessToken }; + refreshApolloClient = true; +}; + +const createVueApollo = (resolvers = {}, config = {}) => { + // Avoids creating a new Apollo client every time that the story rerenders + if (!apolloClient || refreshApolloClient) { + refreshApolloClient = false; + apolloClient = new VueApollo({ + defaultClient: createDefaultClient( + { + ...resolvers, + }, + { + ...config, + httpHeaders: { + Authorization: `Bearer ${gitlabApiAccessParams.accessToken}`, + }, + }, + ), + }); + } + + return apolloClient; +}; + +channel.addListener(GITLAB_API_ACCESS_UPDATE_EVENT, (params) => { + setGitLabAPIAccessParams(params); + + const storyId = new URLSearchParams(window.location.search).get('id'); + + // If we don’t force remount, Vue Apollo is not updated with the new parameters + addons.channel.emit(FORCE_REMOUNT, { storyId }); +}); + +/* + * Story decorator used to inject a VueApollo client factory + * that contains the GitLab API access parameters. + */ +export const withGitLabAPIAccess = (story, context) => { + Object.assign(context, { createVueApollo }); + + return { + components: { + story, + }, + template: '<story />', + }; +}; + +/* + * Initializes the GitLab API access parameters + * with values coming from the environment. + */ +export const initializeGitLabAPIAccess = () => { + setGitLabAPIAccessParams({ + gitlabURL: process.env.GITLAB_URL, + accessToken: process.env.API_ACCESS_TOKEN, + }); +}; diff --git a/storybook/config/gon.js b/storybook/config/gon.js new file mode 100644 index 00000000000..d85ae3d611b --- /dev/null +++ b/storybook/config/gon.js @@ -0,0 +1,5 @@ +window.gon = { + user_color_scheme: 'white', + api_version: 'v4', + relative_url_root: '', +}; diff --git a/storybook/config/main.js b/storybook/config/main.js index 59aa9deb3b5..794a5e20344 100644 --- a/storybook/config/main.js +++ b/storybook/config/main.js @@ -5,5 +5,5 @@ module.exports = { '../../app/assets/javascripts/**/*.stories.js', IS_EE && '../../ee/app/assets/javascripts/**/*.stories.js', ].filter(Boolean), - addons: ['@storybook/addon-essentials', '@storybook/addon-a11y', 'storybook-mirage'], + addons: ['@storybook/addon-essentials', '@storybook/addon-a11y'], }; diff --git a/storybook/config/manager.js b/storybook/config/manager.js new file mode 100644 index 00000000000..010f0caf61d --- /dev/null +++ b/storybook/config/manager.js @@ -0,0 +1 @@ +import './addons/gitlab_api_access/manager'; diff --git a/storybook/config/preview.js b/storybook/config/preview.js index 6f3b8190742..70c8041bb3c 100644 --- a/storybook/config/preview.js +++ b/storybook/config/preview.js @@ -1,7 +1,8 @@ -import { withServer } from 'storybook-mirage'; // eslint-disable-line import/no-unresolved +// Some modules read window.gon on initialization thus we need to define this object before anything else +import './gon'; import Vue from 'vue'; -import { createMockServer } from 'test_helpers/mock_server'; import translateMixin from '~/vue_shared/translate'; +import { withGitLabAPIAccess, initializeGitLabAPIAccess } from './addons/gitlab_api_access/preview'; const stylesheetsRequireCtx = require.context( '../../app/assets/stylesheets', @@ -9,13 +10,12 @@ const stylesheetsRequireCtx = require.context( /(application|application_utilities|highlight\/themes\/white)\.scss$/, ); -window.gon = { - user_color_scheme: 'white', -}; +initializeGitLabAPIAccess(); + translateMixin(Vue); stylesheetsRequireCtx('./application.scss'); stylesheetsRequireCtx('./application_utilities.scss'); stylesheetsRequireCtx('./highlight/themes/white.scss'); -export const decorators = [withServer(createMockServer)]; +export const decorators = [withGitLabAPIAccess]; diff --git a/storybook/package.json b/storybook/package.json index c6e47bf6b5f..ec3590dea13 100644 --- a/storybook/package.json +++ b/storybook/package.json @@ -9,16 +9,20 @@ "vue": "https://gitlab.com/gitlab-org/gitlab/-/issues/340511" }, "devDependencies": { + "react": "16.14.0", + "@storybook/addons": "^6.5.10", + "@storybook/api": "^6.5.10", + "@storybook/components": "^6.5.10", + "@storybook/core-events": "^6.5.10", "@storybook/addon-a11y": "^6.5.10", "@storybook/addon-actions": "^6.5.10", "@storybook/addon-controls": "^6.5.10", "@storybook/addon-essentials": "^6.5.10", - "@storybook/vue": "6.5.10", + "@storybook/vue": "^6.5.10", "graphql-tag": "^2.12.5", "postcss-loader": "3.0.0", "sass": "^1.49.9", - "sass-loader": "^7.1.0", - "storybook-mirage": "^0.0.4" + "sass-loader": "^7.1.0" }, "resolutions": { "chokidar": "^3.5.2" diff --git a/storybook/yarn.lock b/storybook/yarn.lock index f960b7e1de9..0e51671b2f9 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -1473,6 +1473,23 @@ global "^4.4.0" regenerator-runtime "^0.13.7" +"@storybook/addons@6.5.16", "@storybook/addons@^6.5.10": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.5.16.tgz#07e8f2205f86fa4c9dada719e3e096cb468e3cdd" + integrity sha512-p3DqQi+8QRL5k7jXhXmJZLsE/GqHqyY6PcoA1oNTJr0try48uhTGUOYkgzmqtDaa/qPFO5LP+xCPzZXckGtquQ== + dependencies: + "@storybook/api" "6.5.16" + "@storybook/channels" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/core-events" "6.5.16" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/router" "6.5.16" + "@storybook/theming" "6.5.16" + "@types/webpack-env" "^1.16.0" + core-js "^3.8.2" + global "^4.4.0" + regenerator-runtime "^0.13.7" + "@storybook/api@6.5.10": version "6.5.10" resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.5.10.tgz#215623844648f0da2ac646fdcdd1345c2e1a8490" @@ -1496,28 +1513,51 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/builder-webpack4@6.5.10": - version "6.5.10" - resolved "https://registry.yarnpkg.com/@storybook/builder-webpack4/-/builder-webpack4-6.5.10.tgz#79e95323577a37349ab3c81193fa249ac5c50173" - integrity sha512-AoKjsCNoQQoZXYwBDxO8s+yVEd5FjBJAaysEuUTHq2fb81jwLrGcEOo6hjw4jqfugZQIzYUEjPazlvubS78zpw== +"@storybook/api@6.5.16", "@storybook/api@^6.5.10": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.5.16.tgz#897915b76de05587fd702951d5d836f708043662" + integrity sha512-HOsuT8iomqeTMQJrRx5U8nsC7lJTwRr1DhdD0SzlqL4c80S/7uuCy4IZvOt4sYQjOzW5fOo/kamcoBXyLproTA== + dependencies: + "@storybook/channels" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/core-events" "6.5.16" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/router" "6.5.16" + "@storybook/semver" "^7.3.2" + "@storybook/theming" "6.5.16" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.21" + memoizerific "^1.11.3" + regenerator-runtime "^0.13.7" + store2 "^2.12.0" + telejson "^6.0.8" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + +"@storybook/builder-webpack4@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/builder-webpack4/-/builder-webpack4-6.5.16.tgz#ac468d244835a7f3bd01936398fee47244da35c1" + integrity sha512-YqDIrVNsUo8r9xc6AxsYDLxVYtMgl5Bxk+8/h1adsOko+jAFhdg6hOcAVxEmoSI0TMASOOVMFlT2hr23ppN2rQ== dependencies: "@babel/core" "^7.12.10" - "@storybook/addons" "6.5.10" - "@storybook/api" "6.5.10" - "@storybook/channel-postmessage" "6.5.10" - "@storybook/channels" "6.5.10" - "@storybook/client-api" "6.5.10" - "@storybook/client-logger" "6.5.10" - "@storybook/components" "6.5.10" - "@storybook/core-common" "6.5.10" - "@storybook/core-events" "6.5.10" - "@storybook/node-logger" "6.5.10" - "@storybook/preview-web" "6.5.10" - "@storybook/router" "6.5.10" + "@storybook/addons" "6.5.16" + "@storybook/api" "6.5.16" + "@storybook/channel-postmessage" "6.5.16" + "@storybook/channels" "6.5.16" + "@storybook/client-api" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/components" "6.5.16" + "@storybook/core-common" "6.5.16" + "@storybook/core-events" "6.5.16" + "@storybook/node-logger" "6.5.16" + "@storybook/preview-web" "6.5.16" + "@storybook/router" "6.5.16" "@storybook/semver" "^7.3.2" - "@storybook/store" "6.5.10" - "@storybook/theming" "6.5.10" - "@storybook/ui" "6.5.10" + "@storybook/store" "6.5.16" + "@storybook/theming" "6.5.16" + "@storybook/ui" "6.5.16" "@types/node" "^14.0.10 || ^16.0.0" "@types/webpack" "^4.41.26" autoprefixer "^9.8.6" @@ -1562,13 +1602,26 @@ qs "^6.10.0" telejson "^6.0.8" -"@storybook/channel-websocket@6.5.10": - version "6.5.10" - resolved "https://registry.yarnpkg.com/@storybook/channel-websocket/-/channel-websocket-6.5.10.tgz#bd1316a9b555229b215e5054a76b57c503dd8adc" - integrity sha512-RTXMZbMWCS3xU+4GVIdfnUXsKcwg/WTozy88/5OxaKjGw6KgRedqLAQJKJ6Y5XlnwIcWelirkHj/COwTTXhbPg== +"@storybook/channel-postmessage@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.5.16.tgz#06167c0a66c06b2b5f8ff01d1dd436fff8119a15" + integrity sha512-fZZSN29dsUArWOx7e7lTdMA9+7zijVwCwbvi2Fo4fqhRLh1DsTb/VXfz1FKMCWAjNlcX7QQvV25tnxbqsD6lyw== dependencies: - "@storybook/channels" "6.5.10" - "@storybook/client-logger" "6.5.10" + "@storybook/channels" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/core-events" "6.5.16" + core-js "^3.8.2" + global "^4.4.0" + qs "^6.10.0" + telejson "^6.0.8" + +"@storybook/channel-websocket@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/channel-websocket/-/channel-websocket-6.5.16.tgz#41f69ca9444a4dfbf72580b4696900c5b1d2b817" + integrity sha512-wJg2lpBjmRC2GJFzmhB9kxlh109VE58r/0WhFtLbwKvPqsvGf82xkBEl6BtBCvIQ4stzYnj/XijjA8qSi2zpOg== + dependencies: + "@storybook/channels" "6.5.16" + "@storybook/client-logger" "6.5.16" core-js "^3.8.2" global "^4.4.0" telejson "^6.0.8" @@ -1582,18 +1635,27 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-api@6.5.10": - version "6.5.10" - resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.5.10.tgz#0bc3f68ce014ce1ffd560472a893ba04be370f09" - integrity sha512-3wBWZl3NvMFgMovgEh+euiARAT2FXzpvTF4Q1gerGMNNDlrGxHnFvSuy4FHg/irtOGLa4yLz43ULFbYtpKw0Lg== +"@storybook/channels@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.5.16.tgz#3fb9a3b5666ecb951a2d0cf8b0699b084ef2d3c6" + integrity sha512-VylzaWQZaMozEwZPJdyJoz+0jpDa8GRyaqu9TGG6QGv+KU5POoZaGLDkRE7TzWkyyP0KQLo80K99MssZCpgSeg== dependencies: - "@storybook/addons" "6.5.10" - "@storybook/channel-postmessage" "6.5.10" - "@storybook/channels" "6.5.10" - "@storybook/client-logger" "6.5.10" - "@storybook/core-events" "6.5.10" + core-js "^3.8.2" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + +"@storybook/client-api@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.5.16.tgz#13e5a7c3d1f0f951ec4ef51cfcf2c5aafb560e12" + integrity sha512-i3UwkzzUFw8I+E6fOcgB5sc4oU2fhvaKnqC1mpd9IYGJ9JN9MnGIaVl3Ko28DtFItu/QabC9JsLIJVripFLktQ== + dependencies: + "@storybook/addons" "6.5.16" + "@storybook/channel-postmessage" "6.5.16" + "@storybook/channels" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/core-events" "6.5.16" "@storybook/csf" "0.0.2--canary.4566f4d.1" - "@storybook/store" "6.5.10" + "@storybook/store" "6.5.16" "@types/qs" "^6.9.5" "@types/webpack-env" "^1.16.0" core-js "^3.8.2" @@ -1616,6 +1678,14 @@ core-js "^3.8.2" global "^4.4.0" +"@storybook/client-logger@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.5.16.tgz#955cc46b389e7151c9eb1585a75e6a0605af61a1" + integrity sha512-pxcNaCj3ItDdicPTXTtmYJE3YC1SjxFrBmHcyrN+nffeNyiMuViJdOOZzzzucTUG0wcOOX8jaSyak+nnHg5H1Q== + dependencies: + core-js "^3.8.2" + global "^4.4.0" + "@storybook/components@6.5.10": version "6.5.10" resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.5.10.tgz#268e1269bc3d262f7dcec13f96c3b844919687b8" @@ -1630,21 +1700,35 @@ regenerator-runtime "^0.13.7" util-deprecate "^1.0.2" -"@storybook/core-client@6.5.10": - version "6.5.10" - resolved "https://registry.yarnpkg.com/@storybook/core-client/-/core-client-6.5.10.tgz#90c86923236c8efff33d454a0dc552f6df4346b1" - integrity sha512-THsIjNrOrampTl0Lgfjvfjk1JnktKb4CQLOM80KpQb4cjDqorBjJmErzUkUQ2y3fXvrDmQ/kUREkShET4XEdtA== +"@storybook/components@6.5.16", "@storybook/components@^6.5.10": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.5.16.tgz#f8dc51213bc08fe32154be964e1e8b0e2f670ed6" + integrity sha512-LzBOFJKITLtDcbW9jXl0/PaG+4xAz25PK8JxPZpIALbmOpYWOAPcO6V9C2heX6e6NgWFMUxjplkULEk9RCQMNA== dependencies: - "@storybook/addons" "6.5.10" - "@storybook/channel-postmessage" "6.5.10" - "@storybook/channel-websocket" "6.5.10" - "@storybook/client-api" "6.5.10" - "@storybook/client-logger" "6.5.10" - "@storybook/core-events" "6.5.10" + "@storybook/client-logger" "6.5.16" "@storybook/csf" "0.0.2--canary.4566f4d.1" - "@storybook/preview-web" "6.5.10" - "@storybook/store" "6.5.10" - "@storybook/ui" "6.5.10" + "@storybook/theming" "6.5.16" + core-js "^3.8.2" + memoizerific "^1.11.3" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + util-deprecate "^1.0.2" + +"@storybook/core-client@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/core-client/-/core-client-6.5.16.tgz#ed2328fd38c6111fe887f6a91b28d9dc2b17092a" + integrity sha512-14IRaDrVtKrQ+gNWC0wPwkCNfkZOKghYV/swCUnQX3rP99defsZK8Hc7xHIYoAiOP5+sc3sweRAxgmFiJeQ1Ig== + dependencies: + "@storybook/addons" "6.5.16" + "@storybook/channel-postmessage" "6.5.16" + "@storybook/channel-websocket" "6.5.16" + "@storybook/client-api" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/core-events" "6.5.16" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/preview-web" "6.5.16" + "@storybook/store" "6.5.16" + "@storybook/ui" "6.5.16" airbnb-js-shims "^2.2.1" ansi-to-html "^0.6.11" core-js "^3.8.2" @@ -1712,6 +1796,62 @@ util-deprecate "^1.0.2" webpack "4" +"@storybook/core-common@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/core-common/-/core-common-6.5.16.tgz#db80aa6f220a576a83db821f720e103190a914ae" + integrity sha512-2qtnKP3TTOzt2cp6LXKRTh7XrI9z5VanMnMTgeoFcA5ebnndD4V6BExQUdYPClE/QooLx6blUWNgS9dFEpjSqQ== + dependencies: + "@babel/core" "^7.12.10" + "@babel/plugin-proposal-class-properties" "^7.12.1" + "@babel/plugin-proposal-decorators" "^7.12.12" + "@babel/plugin-proposal-export-default-from" "^7.12.1" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" + "@babel/plugin-proposal-object-rest-spread" "^7.12.1" + "@babel/plugin-proposal-optional-chaining" "^7.12.7" + "@babel/plugin-proposal-private-methods" "^7.12.1" + "@babel/plugin-proposal-private-property-in-object" "^7.12.1" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.12.1" + "@babel/plugin-transform-block-scoping" "^7.12.12" + "@babel/plugin-transform-classes" "^7.12.1" + "@babel/plugin-transform-destructuring" "^7.12.1" + "@babel/plugin-transform-for-of" "^7.12.1" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-transform-shorthand-properties" "^7.12.1" + "@babel/plugin-transform-spread" "^7.12.1" + "@babel/preset-env" "^7.12.11" + "@babel/preset-react" "^7.12.10" + "@babel/preset-typescript" "^7.12.7" + "@babel/register" "^7.12.1" + "@storybook/node-logger" "6.5.16" + "@storybook/semver" "^7.3.2" + "@types/node" "^14.0.10 || ^16.0.0" + "@types/pretty-hrtime" "^1.0.0" + babel-loader "^8.0.0" + babel-plugin-macros "^3.0.1" + babel-plugin-polyfill-corejs3 "^0.1.0" + chalk "^4.1.0" + core-js "^3.8.2" + express "^4.17.1" + file-system-cache "^1.0.5" + find-up "^5.0.0" + fork-ts-checker-webpack-plugin "^6.0.4" + fs-extra "^9.0.1" + glob "^7.1.6" + handlebars "^4.7.7" + interpret "^2.2.0" + json5 "^2.2.3" + lazy-universal-dotenv "^3.0.1" + picomatch "^2.3.0" + pkg-dir "^5.0.0" + pretty-hrtime "^1.0.3" + resolve-from "^5.0.0" + slash "^3.0.0" + telejson "^6.0.8" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + webpack "4" + "@storybook/core-events@6.5.10": version "6.5.10" resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.5.10.tgz#66d87c8ea18db8e448018a16a3d0198ddbcbc683" @@ -1719,23 +1859,30 @@ dependencies: core-js "^3.8.2" -"@storybook/core-server@6.5.10": - version "6.5.10" - resolved "https://registry.yarnpkg.com/@storybook/core-server/-/core-server-6.5.10.tgz#ada3d647833c02cb8c742281c1f314ff866f96f8" - integrity sha512-jqwpA0ccA8X5ck4esWBid04+cEIVqirdAcqJeNb9IZAD+bRreO4Im8ilzr7jc5AmQ9fkqHs2NByFKh9TITp8NQ== +"@storybook/core-events@6.5.16", "@storybook/core-events@^6.5.10": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.5.16.tgz#b1c265dac755007dae172d9d4b72656c9e5d7bb3" + integrity sha512-qMZQwmvzpH5F2uwNUllTPg6eZXr2OaYZQRRN8VZJiuorZzDNdAFmiVWMWdkThwmyLEJuQKXxqCL8lMj/7PPM+g== + dependencies: + core-js "^3.8.2" + +"@storybook/core-server@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/core-server/-/core-server-6.5.16.tgz#f40de3413de49388129d29c74e5e48321af03f12" + integrity sha512-/3NPfmNyply395Dm0zaVZ8P9aruwO+tPx4D6/jpw8aqrRSwvAMndPMpoMCm0NXcpSm5rdX+Je4S3JW6JcggFkA== dependencies: "@discoveryjs/json-ext" "^0.5.3" - "@storybook/builder-webpack4" "6.5.10" - "@storybook/core-client" "6.5.10" - "@storybook/core-common" "6.5.10" - "@storybook/core-events" "6.5.10" + "@storybook/builder-webpack4" "6.5.16" + "@storybook/core-client" "6.5.16" + "@storybook/core-common" "6.5.16" + "@storybook/core-events" "6.5.16" "@storybook/csf" "0.0.2--canary.4566f4d.1" - "@storybook/csf-tools" "6.5.10" - "@storybook/manager-webpack4" "6.5.10" - "@storybook/node-logger" "6.5.10" + "@storybook/csf-tools" "6.5.16" + "@storybook/manager-webpack4" "6.5.16" + "@storybook/node-logger" "6.5.16" "@storybook/semver" "^7.3.2" - "@storybook/store" "6.5.10" - "@storybook/telemetry" "6.5.10" + "@storybook/store" "6.5.16" + "@storybook/telemetry" "6.5.16" "@types/node" "^14.0.10 || ^16.0.0" "@types/node-fetch" "^2.5.7" "@types/pretty-hrtime" "^1.0.0" @@ -1770,18 +1917,18 @@ ws "^8.2.3" x-default-browser "^0.4.0" -"@storybook/core@6.5.10": - version "6.5.10" - resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.5.10.tgz#15ec8be85943251e25c2c24e80e20dcacc4fed65" - integrity sha512-K86yYa0tYlMxADlwQTculYvPROokQau09SCVqpsLg3wJCTvYFL4+SIqcYoyBSbFmHOdnYbJgPydjN33MYLiOZQ== +"@storybook/core@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.5.16.tgz#ae994f01327fe81b6e652963c35bac7a74f0da06" + integrity sha512-CEF3QFTsm/VMnMKtRNr4rRdLeIkIG0g1t26WcmxTdSThNPBd8CsWzQJ7Jqu7CKiut+MU4A1LMOwbwCE5F2gmyA== dependencies: - "@storybook/core-client" "6.5.10" - "@storybook/core-server" "6.5.10" + "@storybook/core-client" "6.5.16" + "@storybook/core-server" "6.5.16" -"@storybook/csf-tools@6.5.10": - version "6.5.10" - resolved "https://registry.yarnpkg.com/@storybook/csf-tools/-/csf-tools-6.5.10.tgz#ae6f1ebd4951e8978c8fe3e08ddd2bd269bf922b" - integrity sha512-H77kZQEisu7+skzeIbNZwmE09OqLjwJTeFhLN1pcjxKVa30LEI3pBHcNBxVKqgxl+Yg3KkB7W/ArLO2N+i2ohw== +"@storybook/csf-tools@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/csf-tools/-/csf-tools-6.5.16.tgz#367889a3ddb33c93261129104ec2958215ec5459" + integrity sha512-+WD4sH/OwAfXZX3IN6/LOZ9D9iGEFcN+Vvgv9wOsLRgsAZ10DG/NK6c1unXKDM/ogJtJYccNI8Hd+qNE/GFV6A== dependencies: "@babel/core" "^7.12.10" "@babel/generator" "^7.12.11" @@ -1818,20 +1965,33 @@ lodash "^4.17.21" regenerator-runtime "^0.13.7" -"@storybook/manager-webpack4@6.5.10": - version "6.5.10" - resolved "https://registry.yarnpkg.com/@storybook/manager-webpack4/-/manager-webpack4-6.5.10.tgz#41bae252b863484f293954ef2d2dc80bf3e028f1" - integrity sha512-N/TlNDhuhARuFipR/ZJ/xEVESz23iIbCsZ4VNehLHm8PpiGlQUehk+jMjWmz5XV0bJItwjRclY+CU3GjZKblfQ== +"@storybook/docs-tools@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/docs-tools/-/docs-tools-6.5.16.tgz#1ec5433eeab63a214d37ffc4660cdaec9704ac39" + integrity sha512-o+rAWPRGifjBF5xZzTKOqnHN3XQWkl0QFJYVDIiJYJrVll7ExCkpEq/PahOGzIBBV+tpMstJgmKM3lr/lu/jmg== + dependencies: + "@babel/core" "^7.12.10" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/store" "6.5.16" + core-js "^3.8.2" + doctrine "^3.0.0" + lodash "^4.17.21" + regenerator-runtime "^0.13.7" + +"@storybook/manager-webpack4@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/manager-webpack4/-/manager-webpack4-6.5.16.tgz#7033228d38f048ceff3d403ba918d7f206b926a5" + integrity sha512-5VJZwmQU6AgdsBPsYdu886UKBHQ9SJEnFMaeUxKEclXk+iRsmbzlL4GHKyVd6oGX/ZaecZtcHPR6xrzmA4Ziew== dependencies: "@babel/core" "^7.12.10" "@babel/plugin-transform-template-literals" "^7.12.1" "@babel/preset-react" "^7.12.10" - "@storybook/addons" "6.5.10" - "@storybook/core-client" "6.5.10" - "@storybook/core-common" "6.5.10" - "@storybook/node-logger" "6.5.10" - "@storybook/theming" "6.5.10" - "@storybook/ui" "6.5.10" + "@storybook/addons" "6.5.16" + "@storybook/core-client" "6.5.16" + "@storybook/core-common" "6.5.16" + "@storybook/node-logger" "6.5.16" + "@storybook/theming" "6.5.16" + "@storybook/ui" "6.5.16" "@types/node" "^14.0.10 || ^16.0.0" "@types/webpack" "^4.41.26" babel-loader "^8.0.0" @@ -1887,6 +2047,17 @@ npmlog "^5.0.1" pretty-hrtime "^1.0.3" +"@storybook/node-logger@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.5.16.tgz#d57fd6204c2abfbc297551d98ad5475dd73207cc" + integrity sha512-YjhBKrclQtjhqFNSO+BZK+RXOx6EQypAELJKoLFaawg331e8VUfvUuRCNB3fcEWp8G9oH13PQQte0OTjLyyOYg== + dependencies: + "@types/npmlog" "^4.1.2" + chalk "^4.1.0" + core-js "^3.8.2" + npmlog "^5.0.1" + pretty-hrtime "^1.0.3" + "@storybook/postinstall@6.5.10": version "6.5.10" resolved "https://registry.yarnpkg.com/@storybook/postinstall/-/postinstall-6.5.10.tgz#b25378da036bce7b318c6732733aa5ad43449f37" @@ -1916,6 +2087,28 @@ unfetch "^4.2.0" util-deprecate "^1.0.2" +"@storybook/preview-web@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/preview-web/-/preview-web-6.5.16.tgz#1d32a72be25776f9597e33ffc1914f3430fae689" + integrity sha512-IJnvfe2sKCfk7apN9Fu9U8qibbarrPX5JB55ZzK1amSHVmSDuYk5MIMc/U3NnSQNnvd1DO5v/zMcGgj563hrtg== + dependencies: + "@storybook/addons" "6.5.16" + "@storybook/channel-postmessage" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/core-events" "6.5.16" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/store" "6.5.16" + ansi-to-html "^0.6.11" + core-js "^3.8.2" + global "^4.4.0" + lodash "^4.17.21" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + synchronous-promise "^2.0.15" + ts-dedent "^2.0.0" + unfetch "^4.2.0" + util-deprecate "^1.0.2" + "@storybook/router@6.5.10": version "6.5.10" resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.5.10.tgz#b0c342e080c1d2b5344603bc43a6c75734a4a879" @@ -1927,6 +2120,17 @@ qs "^6.10.0" regenerator-runtime "^0.13.7" +"@storybook/router@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.5.16.tgz#28fb4d34e8219351a40bee1fc94dcacda6e1bd8b" + integrity sha512-ZgeP8a5YV/iuKbv31V8DjPxlV4AzorRiR8OuSt/KqaiYXNXlOoQDz/qMmiNcrshrfLpmkzoq7fSo4T8lWo2UwQ== + dependencies: + "@storybook/client-logger" "6.5.16" + core-js "^3.8.2" + memoizerific "^1.11.3" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + "@storybook/semver@^7.3.2": version "7.3.2" resolved "https://registry.yarnpkg.com/@storybook/semver/-/semver-7.3.2.tgz#f3b9c44a1c9a0b933c04e66d0048fcf2fa10dac0" @@ -1972,13 +2176,34 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/telemetry@6.5.10": - version "6.5.10" - resolved "https://registry.yarnpkg.com/@storybook/telemetry/-/telemetry-6.5.10.tgz#742b05a55dfe8470ce4cb371f3f3f2c02f96e816" - integrity sha512-+M5HILDFS8nDumLxeSeAwi1MTzIuV6UWzV4yB2wcsEXOBTdplcl9oYqFKtlst78oOIdGtpPYxYfivDlqxC2K4g== +"@storybook/store@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/store/-/store-6.5.16.tgz#b308701293a3a11bfcc766770584495874fd17da" + integrity sha512-g+bVL5hmMq/9cM51K04e37OviUPHT0rHHrRm5wj/hrf18Kd9120b3sxdQ5Dc+HZ292yuME0n+cyrQPTYx9Epmw== dependencies: - "@storybook/client-logger" "6.5.10" - "@storybook/core-common" "6.5.10" + "@storybook/addons" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/core-events" "6.5.16" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.21" + memoizerific "^1.11.3" + regenerator-runtime "^0.13.7" + slash "^3.0.0" + stable "^0.1.8" + synchronous-promise "^2.0.15" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + +"@storybook/telemetry@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/telemetry/-/telemetry-6.5.16.tgz#b13c8133e02c28e37b7716c987e7414b1ddc5363" + integrity sha512-CWr5Uko1l9jJW88yTXsZTj/3GTabPvw0o7pDPOXPp8JRZiJTxv1JFaFCafhK9UzYbgcRuGfCC8kEWPZims7iKA== + dependencies: + "@storybook/client-logger" "6.5.16" + "@storybook/core-common" "6.5.16" chalk "^4.1.0" core-js "^3.8.2" detect-package-manager "^2.0.1" @@ -2000,38 +2225,48 @@ memoizerific "^1.11.3" regenerator-runtime "^0.13.7" -"@storybook/ui@6.5.10": - version "6.5.10" - resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.5.10.tgz#f56095a1a39ae5a203f2ac7f3dba86341a5927d5" - integrity sha512-6iaoaRAiTqB1inTw35vao+5hjcDE0Qa0A3a9ZIeNa6yHvpB1k0lO/N/0PMrRdVvySYpXVD1iry4z4QYdo1rU+w== +"@storybook/theming@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.5.16.tgz#b999bdb98945b605b93b9dfdf7408535b701e2aa" + integrity sha512-hNLctkjaYLRdk1+xYTkC1mg4dYz2wSv6SqbLpcKMbkPHTE0ElhddGPHQqB362md/w9emYXNkt1LSMD8Xk9JzVQ== dependencies: - "@storybook/addons" "6.5.10" - "@storybook/api" "6.5.10" - "@storybook/channels" "6.5.10" - "@storybook/client-logger" "6.5.10" - "@storybook/components" "6.5.10" - "@storybook/core-events" "6.5.10" - "@storybook/router" "6.5.10" + "@storybook/client-logger" "6.5.16" + core-js "^3.8.2" + memoizerific "^1.11.3" + regenerator-runtime "^0.13.7" + +"@storybook/ui@6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.5.16.tgz#c73bf456e672ecf2370b4365070088487fc0ce57" + integrity sha512-rHn/n12WM8BaXtZ3IApNZCiS+C4Oc5+Lkl4MoctX8V7QSml0SxZBB5hsJ/AiWkgbRxjQpa/L/Nt7/Qw0FjTH/A== + dependencies: + "@storybook/addons" "6.5.16" + "@storybook/api" "6.5.16" + "@storybook/channels" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/components" "6.5.16" + "@storybook/core-events" "6.5.16" + "@storybook/router" "6.5.16" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.5.10" + "@storybook/theming" "6.5.16" core-js "^3.8.2" memoizerific "^1.11.3" qs "^6.10.0" regenerator-runtime "^0.13.7" resolve-from "^5.0.0" -"@storybook/vue@6.5.10": - version "6.5.10" - resolved "https://registry.yarnpkg.com/@storybook/vue/-/vue-6.5.10.tgz#9074ba517d9dbf7587319b9d3c600c2fbd6c087a" - integrity sha512-4MYYvRPkqTBqQUjCNXiTM/PJ6qfzKaECFtEe0H7TG+WP+TuKCCfTY2u1q4ru2qjf8BcSXUfpIWPlfEpZh7wdaQ== +"@storybook/vue@^6.5.10": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/vue/-/vue-6.5.16.tgz#e548995f468e1503a00c324814e3ab76cfee2c82" + integrity sha512-CFpBTAnOC4RZUKf5ZXQXj098D4HgZ+RyB4u45OhFbJFCDXnJQpRk0ANkJ2lyGPYr7/TgfsfZlq2FN8ilPqkk5A== dependencies: - "@storybook/addons" "6.5.10" - "@storybook/client-logger" "6.5.10" - "@storybook/core" "6.5.10" - "@storybook/core-common" "6.5.10" + "@storybook/addons" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/core" "6.5.16" + "@storybook/core-common" "6.5.16" "@storybook/csf" "0.0.2--canary.4566f4d.1" - "@storybook/docs-tools" "6.5.10" - "@storybook/store" "6.5.10" + "@storybook/docs-tools" "6.5.16" + "@storybook/store" "6.5.16" "@types/node" "^14.14.20 || ^16.0.0" "@types/webpack-env" "^1.16.0" core-js "^3.8.2" @@ -5839,6 +6074,11 @@ json5@^2.1.2, json5@^2.1.3: dependencies: minimist "^1.2.5" +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" @@ -8335,11 +8575,6 @@ store2@^2.12.0: resolved "https://registry.yarnpkg.com/store2/-/store2-2.12.0.tgz#e1f1b7e1a59b6083b2596a8d067f6ee88fd4d3cf" integrity sha512-7t+/wpKLanLzSnQPX8WAcuLCCeuSHoWdQuh9SB3xD0kNOM38DNf+0Oa+wmvxmYueRzkmh6IcdKFtvTa+ecgPDw== -storybook-mirage@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/storybook-mirage/-/storybook-mirage-0.0.4.tgz#572e5d310ad8f0dd963e5c341aa2402f8ed07749" - integrity sha512-oGjsxyxmedXQtsVW1DDwKM1RocAD5zClFeOFtAhK46NcGXLJ31m2WQg5kL7YqrsriorrCZq4vvSy05DVCD7BKQ== - stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" |