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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.codeclimate.yml1
-rw-r--r--.eslintignore1
-rw-r--r--.gitignore1
-rw-r--r--.gitlab/CODEOWNERS2
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml35
-rw-r--r--.gitlab/ci/pages.gitlab-ci.yml2
-rw-r--r--.gitlab/issue_templates/Experiment Rollout.md (renamed from .gitlab/issue_templates/experiment_tracking_template.md)90
-rw-r--r--.rubocop_manual_todo.yml33
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js8
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js23
-rw-r--r--app/services/projects/update_pages_service.rb104
-rw-r--r--app/views/admin/application_settings/_files_limits.html.haml34
-rw-r--r--app/views/admin/application_settings/network.html.haml11
-rw-r--r--babel.config.js2
-rw-r--r--config/feature_flags/development/files_api_throttling.yml (renamed from config/feature_flags/development/skip_pages_deploy_to_legacy_storage.yml)10
-rw-r--r--config/karma.config.js203
-rw-r--r--config/webpack.config.js3
-rw-r--r--danger/karma/Dangerfile51
-rw-r--r--db/post_migrate/20210818185845_backfill_projects_with_coverage.rb32
-rw-r--r--db/schema_migrations/202108181858451
-rw-r--r--doc/administration/pages/index.md3
-rw-r--r--doc/api/graphql/reference/index.md192
-rw-r--r--doc/development/experiment_guide/index.md26
-rw-r--r--doc/development/internal_api.md50
-rw-r--r--doc/development/pipelines.md9
-rw-r--r--doc/development/rake_tasks.md1
-rw-r--r--doc/development/testing_guide/frontend_testing.md181
-rw-r--r--doc/development/testing_guide/index.md4
-rw-r--r--doc/development/testing_guide/testing_levels.md11
-rw-r--r--doc/user/project/clusters/index.md2
-rw-r--r--doc/user/project/pages/redirects.md264
-rw-r--r--doc/user/project/repository/repository_mirroring.md10
-rw-r--r--jest.config.js12
-rw-r--r--lib/backup/pages.rb6
-rw-r--r--lib/gitlab/background_migration/backfill_projects_with_coverage.rb41
-rw-r--r--lib/gitlab/database/load_balancing.rb7
-rw-r--r--lib/gitlab/database/load_balancing/connection_proxy.rb29
-rw-r--r--lib/gitlab/database/load_balancing/load_balancer.rb19
-rw-r--r--lib/gitlab/database/load_balancing/primary_host.rb82
-rw-r--r--lib/gitlab/instrumentation/redis_interceptor.rb5
-rw-r--r--lib/tasks/karma.rake19
-rw-r--r--locale/gitlab.pot6
-rw-r--r--package.json14
-rw-r--r--rubocop/cop/migration/prevent_index_creation.rb33
-rwxr-xr-xscripts/frontend/check_no_partial_karma_jest.sh44
-rwxr-xr-xscripts/frontend/file_test_coverage.js2
-rwxr-xr-xscripts/static-analysis3
-rw-r--r--spec/factories/clusters/agents.rb1
-rw-r--r--spec/features/admin/admin_settings_spec.rb14
-rw-r--r--spec/javascripts/.eslintrc.yml39
-rw-r--r--spec/javascripts/fixtures/.gitignore2
-rw-r--r--spec/javascripts/fly_out_nav_browser_spec.js334
-rw-r--r--spec/javascripts/lib/utils/mock_data.js1
-rw-r--r--spec/javascripts/test_bundle.js145
-rw-r--r--spec/javascripts/test_constants.js1
-rw-r--r--spec/lib/gitlab/background_migration/backfill_projects_with_coverage_spec.rb94
-rw-r--r--spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb37
-rw-r--r--spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb22
-rw-r--r--spec/lib/gitlab/database/load_balancing/primary_host_spec.rb123
-rw-r--r--spec/lib/gitlab/database/load_balancing_spec.rb19
-rw-r--r--spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb26
-rw-r--r--spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb71
-rw-r--r--spec/rubocop/cop/migration/prevent_index_creation_spec.rb77
-rw-r--r--spec/services/projects/update_pages_service_spec.rb142
-rw-r--r--spec/support/database_load_balancing.rb4
-rw-r--r--spec/support/shared_contexts/pages_zip_with_spoofed_size_shared_context.rb41
-rw-r--r--spec/tooling/danger/project_helper_spec.rb4
-rw-r--r--tooling/danger/project_helper.rb1
-rw-r--r--vendor/assets/javascripts/jasmine-jquery.js854
-rw-r--r--vendor/aws/cloudformation/eks_cluster.yaml2
-rw-r--r--yarn.lock629
71 files changed, 1255 insertions, 3150 deletions
diff --git a/.codeclimate.yml b/.codeclimate.yml
index ccc09fcc775..c479454285e 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -36,6 +36,5 @@ exclude_paths:
- webpack-report/
- log/
- backups/
- - coverage-javascript/
- plugins/
- file_hooks/
diff --git a/.eslintignore b/.eslintignore
index 7ca59654678..d5f89284b53 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -2,7 +2,6 @@
/builds/
/coverage/
/coverage-frontend/
-/coverage-javascript/
/node_modules/
/public/
/tmp/
diff --git a/.gitignore b/.gitignore
index 7dbfe96cebb..f753a247563 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,7 +50,6 @@ eslint-report.html
/config/sidekiq.yml
/config/registry.key
/coverage/*
-/coverage-javascript/
/db/*.sqlite3
/db/*.sqlite3-journal
/db/data.yml
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index c62380cb5c8..d884f61291e 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -152,8 +152,6 @@
*.js @gitlab-org/maintainers/frontend
/app/assets/ @gitlab-org/maintainers/frontend
/ee/app/assets/ @gitlab-org/maintainers/frontend
-/spec/javascripts/ @gitlab-org/maintainers/frontend
-/ee/spec/javascripts/ @gitlab-org/maintainers/frontend
/spec/frontend/ @gitlab-org/maintainers/frontend
/ee/spec/frontend/ @gitlab-org/maintainers/frontend
/spec/frontend_integration/ @gitlab-org/maintainers/frontend
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 40c55893d0f..48424910a6a 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -184,41 +184,6 @@ eslint-as-if-foss:
- *yarn-install
- run_timed_command "yarn run lint:eslint:all"
-.karma-base:
- extends: .frontend-test-base
- script:
- - export BABEL_ENV=coverage CHROME_LOG_FILE=chrome_debug.log
- - *yarn-install
- - run_timed_command "yarn karma"
-
-karma:
- extends:
- - .karma-base
- - .frontend:rules:default-frontend-jobs
- needs:
- - job: "rspec frontend_fixture"
- - job: "rspec-ee frontend_fixture"
- optional: true
- coverage: '/^Statements *: (\d+\.\d+%)/'
- artifacts:
- name: coverage-javascript
- expire_in: 31d
- when: always
- paths:
- - chrome_debug.log
- - coverage-javascript/
- - tmp/tests/frontend/
- reports:
- junit: junit_karma.xml
- cobertura: coverage-javascript/cobertura-coverage.xml
-
-karma-as-if-foss:
- extends:
- - .karma-base
- - .frontend:rules:default-frontend-jobs-as-if-foss
- - .as-if-foss
- needs: ["rspec frontend_fixture as-if-foss"]
-
.jest-base:
extends: .frontend-test-base
script:
diff --git a/.gitlab/ci/pages.gitlab-ci.yml b/.gitlab/ci/pages.gitlab-ci.yml
index 2f43e974cf6..6f96d84b8e3 100644
--- a/.gitlab/ci/pages.gitlab-ci.yml
+++ b/.gitlab/ci/pages.gitlab-ci.yml
@@ -12,7 +12,6 @@ pages:
needs:
- job: "rspec:coverage"
- job: "coverage-frontend"
- - job: "karma"
- job: "compile-production-assets"
- job: "compile-storybook"
# `update-tests-metadata` only runs on GitLab.com's EE schedules pipelines
@@ -27,7 +26,6 @@ pages:
- mkdir -p public/$(dirname "$KNAPSACK_RSPEC_SUITE_REPORT_PATH") public/$(dirname "$FLAKY_RSPEC_SUITE_REPORT_PATH") public/$(dirname "$RSPEC_PACKED_TESTS_MAPPING_PATH")
- mv coverage/ public/coverage-ruby/ || true
- mv coverage-frontend/ public/coverage-frontend/ || true
- - mv coverage-javascript/ public/coverage-javascript/ || true
- mv storybook/public public/storybook || true
- cp .public/assets/application-*.css public/application.css || true
- mv $KNAPSACK_RSPEC_SUITE_REPORT_PATH public/$KNAPSACK_RSPEC_SUITE_REPORT_PATH || true
diff --git a/.gitlab/issue_templates/experiment_tracking_template.md b/.gitlab/issue_templates/Experiment Rollout.md
index c653a3a2d40..c5fdc739943 100644
--- a/.gitlab/issue_templates/experiment_tracking_template.md
+++ b/.gitlab/issue_templates/Experiment Rollout.md
@@ -1,16 +1,14 @@
-<!-- Title suggestion: [Experiment Tracking] experiment-key - description of experiment -->
+<!-- Title suggestion: [Experiment Rollout] experiment-key - description of experiment -->
-## What
+## Summary
-Track the status of an experiment through to removal.
+This issue tracks the rollout and status of an experiment through to removal.
-1. Experiment key: `<experiment-key>`
-1. Framework: `experimentation.rb` | `gitlab_experiment`
-1. Feature flag name: <experiment-key>_experiment_percentage` | `<experiment-key>`
-
-This is an experiment tracking issue for: `<issue or epic link>`
-using the scoped [experiment label](https://about.gitlab.com/handbook/engineering/development/growth/#experiment-tracking-issue).
+1. Experiment key / feature flag name: `<experiment-key>`
+1. Epic or issue link: `<issue or epic link>`
+This is an experiment rollout issue
+using the scoped [experiment label](https://about.gitlab.com/handbook/engineering/development/growth/experimentation/#experiment-rollout-issue).
As well as defining the experiment rollout and cleanup, this issue incorporates the relevant
[`Feature Flag Roll Out`](https://gitlab.com/gitlab-org/gitlab/-/edit/master/.gitlab/issue_templates/Feature%20Flag%20Roll%20Out.md) steps.
@@ -19,49 +17,65 @@ As well as defining the experiment rollout and cleanup, this issue incorporates
- Team: `group::TEAM_NAME`
- Most appropriate slack channel to reach out to: `#g_TEAM_NAME`
- Best individual to reach out to: NAME
+- Product manager (PM): NAME
+
+### Stakeholders
+
+<!--
+Are there any other stages or teams involved that need to be kept in the loop?
+
+- PM: Name
+- Group: `group::TEAM_NAME`
+- The Support Team
+- The Delivery Team
+-->
## Expectations
### What are we expecting to happen?
+<!-- Describe the expected outcome when rolling out this experiment. -->
+
### What might happen if this goes wrong?
+<!-- Any MRs that need to be rolled back? Communication that needs to happen? What are some things you can think of that could go wrong - data loss or broken pages? -->
+
### What can we monitor to detect problems with this?
-<!-- Which dashboards from https://dashboards.gitlab.net are most relevant? Sentry errors reports can also be useful to review -->
-### Tracked data
+<!-- Which dashboards from https://dashboards.gitlab.net are most relevant? -->
+
+## Tracked data
<!-- brief description or link to issue or Sisense dashboard -->
-
- Note: you can utilize [CXL calculator](https://cxl.com/ab-test-calculator/) to determine if your experiment has reached signifigance, it also includes an estimate for how much longer an experiment will need to run for before reaching signifigance.
-### Staging Test
-<!-- For experiments using `experimentation.rb`: To force this experiment on staging use `?force_experiment=<experiment-key>` -->
-<!-- list any steps required to setup this experiment, and link to a separate Staging environment test issue is applicable -->
+Note: you can use the [CXL calculator](https://cxl.com/ab-test-calculator/) to determine if your experiment has reached significance. The calculator includes an estimate for how much longer an experiment must run for before reaching significance.
-<!-- uncomment if testing with specific groups/projects on GitLab.com
-## Beta groups/projects
+## Rollout plan
+<!-- Add an overview and method for modifying the feature flag -->
-If applicable, any groups/projects that are happy to have this feature turned on early. Some organizations may wish to test big changes they are interested in with a small subset of users ahead of time for example.
+- Runtime in days, or until we expect to reach statistical significance: `30`
+- We will roll this out behind a feature flag and expose this to `<rollout-percentage>`% of actors to start then ramp it up from there.
-- `gitlab-org/gitlab` project
-- `gitlab-org`/`gitlab-com` groups
-- ...
--->
+`/chatops run feature set <experiment-key> <rollout-percentage> --actors`
-### Experiment tracking log
-<!-- Add an overview and method for modifying the feature flag
+### Status
-* Runtime: 30 days or until we reach statistical significance
-* We will roll this out behind a feature flag and expose this to 20% of users to start then ramp it up from there.
-* feature flag based on experiment key `<experiment-key>` (see `experimentation.rb` in GitLab, append '_experiment_percentage')
-`/chatops run feature set <experiment-key>_experiment_percentage <INITIAL_PERCENTAGE>`
--->
-<!-- Add bullet points to track changes to the rollout of this experiment (feature flag changes)
+#### Preferred workflow
-* YYYY-MM-DD UTC - initial rollout to 20% of users
-* TBD - review - increase to 50% of users
--->
+The issue should be assigned to the Product manager (PM) or Engineer (Eng) as follows:
+
+1. PM determines and manages the status of the experiment (assign this issue to the PM)
+1. PM asks for initial rollout on production, or changes to the status (assign to an Eng)
+1. Eng changes the status using `chatops` (reassign to the PM)
+1. When concluded, PM updates the 'Roll Out Steps' and adds a milestone (assigns to an Eng)
+
+The current status and history can be viewed using the:
+
+- [API](https://gitlab.com/api/v4/experiments) (GitLab team members)
+- [Feature flag log](https://gitlab.com/gitlab-com/gl-infra/feature-flag-log/-/issues?scope=all&utf8=%E2%9C%93&state=all) (GitLab team members)
+- [Experiment rollout board](https://gitlab.com/groups/gitlab-org/-/boards/1352542)
+
+In this rollout issue, ensure the scoped `experiment::` label is kept accurate.
### Experiment Results
<!-- update when experiment in/validated, set the scoped `~experiment::` status accordingly -->
@@ -69,7 +83,7 @@ If applicable, any groups/projects that are happy to have this feature turned on
## Roll Out Steps
- [ ] Confirm that QA tests pass with the feature flag enabled (if you're unsure how, contact the relevant [stable counterpart in the Quality department](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors))
-- [ ] Enable on staging (`/chatops run feature set feature_name true --staging`)
+- [ ] Enable on staging (`/chatops run feature set <experiment-key> true --staging`)
- [ ] Test on staging
- [ ] Ensure that documentation has been updated
- [ ] Enable on GitLab.com for individual groups/projects listed above and verify behaviour (`/chatops run feature set --project=gitlab-org/gitlab feature_name true`)
@@ -88,8 +102,8 @@ If applicable, any groups/projects that are happy to have this feature turned on
- [ ] This feature can be disabled by running the following Chatops command:
```
-/chatops run feature set feature_name false
+/chatops run feature set <experiment-key> false
```
-/label ~"feature flag" ~"devops::growth" ~"growth experiment" ~"experiment tracking" ~Engineering ~"workflow::scheduling" ~"experiment::pending"
-
+/label ~"feature flag" ~"devops::growth" ~"growth experiment" ~"experiment-rollout" ~Engineering ~"workflow::scheduling" ~"experiment::pending"
+/milestone %"Next 1-3 releases"
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index cf4227ab552..703f54c9bdc 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -23,39 +23,6 @@ Graphql/Descriptions:
- 'ee/app/graphql/types/vulnerability_severity_enum.rb'
- 'ee/app/graphql/types/vulnerability_state_enum.rb'
- 'ee/app/graphql/types/vulnerability_confidence_enum.rb'
- - 'ee/app/graphql/mutations/epic_tree/reorder.rb'
- - 'ee/app/graphql/mutations/epics/add_issue.rb'
- - 'ee/app/graphql/mutations/epics/base.rb'
- - 'ee/app/graphql/mutations/epics/create.rb'
- - 'ee/app/graphql/mutations/epics/set_subscription.rb'
- - 'ee/app/graphql/mutations/gitlab_subscriptions/activate.rb'
- - 'ee/app/graphql/mutations/incident_management/escalation_policy/base.rb'
- - 'ee/app/graphql/mutations/incident_management/escalation_policy/create.rb'
- - 'ee/app/graphql/mutations/incident_management/escalation_policy/destroy.rb'
- - 'ee/app/graphql/mutations/incident_management/escalation_policy/update.rb'
- - 'ee/app/graphql/mutations/incident_management/oncall_rotation/base.rb'
- - 'ee/app/graphql/mutations/incident_management/oncall_rotation/create.rb'
- - 'ee/app/graphql/mutations/incident_management/oncall_rotation/destroy.rb'
- - 'ee/app/graphql/mutations/incident_management/oncall_rotation/update.rb'
- - 'ee/app/graphql/mutations/incident_management/oncall_schedule/create.rb'
- - 'ee/app/graphql/mutations/incident_management/oncall_schedule/destroy.rb'
- - 'ee/app/graphql/mutations/incident_management/oncall_schedule/oncall_schedule_base.rb'
- - 'ee/app/graphql/mutations/incident_management/oncall_schedule/update.rb'
- - 'ee/app/graphql/mutations/issues/common_ee_mutation_arguments.rb'
- - 'ee/app/graphql/mutations/issues/promote_to_epic.rb'
- - 'ee/app/graphql/mutations/issues/set_iteration.rb'
- - 'ee/app/graphql/mutations/iterations/cadences/create.rb'
- - 'ee/app/graphql/mutations/iterations/cadences/update.rb'
- - 'ee/app/graphql/mutations/iterations/create.rb'
- - 'ee/app/graphql/mutations/namespaces/base.rb'
- - 'ee/app/graphql/mutations/quality_management/test_cases/create.rb'
- - 'ee/app/graphql/mutations/requirements_management/update_requirement.rb'
- - 'ee/app/graphql/mutations/vulnerabilities/confirm.rb'
- - 'ee/app/graphql/mutations/vulnerabilities/create_external_issue_link.rb'
- - 'ee/app/graphql/mutations/vulnerabilities/destroy_external_issue_link.rb'
- - 'ee/app/graphql/mutations/vulnerabilities/dismiss.rb'
- - 'ee/app/graphql/mutations/vulnerabilities/resolve.rb'
- - 'ee/app/graphql/mutations/vulnerabilities/revert_to_detected.rb'
- 'ee/app/graphql/resolvers/dora_metrics_resolver.rb'
- 'ee/app/graphql/resolvers/geo/geo_node_resolver.rb'
- 'ee/app/graphql/resolvers/network_policy_resolver.rb'
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index 8f86fd55d6e..db6834c4084 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -564,7 +564,7 @@ export const addSelectOnFocusBehaviour = (selector = '.js-select-on-focus') => {
*
* Eg; roundOffFloat(3.141592, 3) = 3.142
*
- * Refer to spec/javascripts/lib/utils/common_utils_spec.js for
+ * Refer to spec/frontend/lib/utils/common_utils_spec.js for
* more supported examples.
*
* @param {Float} number
@@ -581,7 +581,7 @@ export const roundOffFloat = (number, precision = 0) => {
*
* Eg; roundToNearestHalf(3.141592) = 3, roundToNearestHalf(3.41592) = 3.5
*
- * Refer to spec/javascripts/lib/utils/common_utils_spec.js for
+ * Refer to spec/frontend/lib/utils/common_utils_spec.js for
* more supported examples.
*
* @param {Float} number
@@ -595,7 +595,7 @@ export const roundToNearestHalf = (num) => Math.round(num * 2).toFixed() / 2;
*
* Eg; roundDownFloat(3.141592, 3) = 3.141
*
- * Refer to spec/javascripts/lib/utils/common_utils_spec.js for
+ * Refer to spec/frontend/lib/utils/common_utils_spec.js for
* more supported examples.
*
* @param {Float} number
@@ -645,7 +645,7 @@ export const NavigationType = {
* matched with our query.
*
* You can learn more about behaviour of this method by referring to tests
- * within `spec/javascripts/lib/utils/common_utils_spec.js`.
+ * within `spec/frontend/lib/utils/common_utils_spec.js`.
*
* @param {string} query String to search for
* @param {object} searchSpace Object containing properties to search in for `query`
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
index 4a7149ed9ae..1df65d0a666 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
@@ -1,4 +1,3 @@
-/* eslint-disable @gitlab/require-string-literal-i18n-helpers */
import { __ } from '~/locale';
export const DEBOUNCE_DELAY = 200;
@@ -21,28 +20,24 @@ export const OPERATOR_IS_ONLY = [{ value: OPERATOR_IS, description: OPERATOR_IS_
export const OPERATOR_IS_NOT_ONLY = [{ value: OPERATOR_IS_NOT, description: OPERATOR_IS_NOT_TEXT }];
export const OPERATOR_IS_AND_IS_NOT = [...OPERATOR_IS_ONLY, ...OPERATOR_IS_NOT_ONLY];
-export const DEFAULT_LABEL_NONE = {
- value: FILTER_NONE,
- text: __(FILTER_NONE),
- title: __(FILTER_NONE),
-};
-export const DEFAULT_LABEL_ANY = { value: FILTER_ANY, text: __(FILTER_ANY), title: __(FILTER_ANY) };
+export const DEFAULT_LABEL_NONE = { value: FILTER_NONE, text: __('None'), title: __('None') };
+export const DEFAULT_LABEL_ANY = { value: FILTER_ANY, text: __('Any'), title: __('Any') };
export const DEFAULT_NONE_ANY = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
export const DEFAULT_ITERATIONS = DEFAULT_NONE_ANY.concat([
- { value: FILTER_CURRENT, text: __(FILTER_CURRENT) },
+ { value: FILTER_CURRENT, text: __('Current') },
]);
export const DEFAULT_MILESTONES = DEFAULT_NONE_ANY.concat([
- { value: FILTER_UPCOMING, text: __(FILTER_UPCOMING), title: __(FILTER_UPCOMING) },
- { value: FILTER_STARTED, text: __(FILTER_STARTED), title: __(FILTER_STARTED) },
+ { value: FILTER_UPCOMING, text: __('Upcoming'), title: __('Upcoming') },
+ { value: FILTER_STARTED, text: __('Started'), title: __('Started') },
]);
export const DEFAULT_MILESTONES_GRAPHQL = [
- { value: 'any', text: __(FILTER_ANY), title: __(FILTER_ANY) },
- { value: 'none', text: __(FILTER_NONE), title: __(FILTER_NONE) },
- { value: '#upcoming', text: __(FILTER_UPCOMING), title: __(FILTER_UPCOMING) },
- { value: '#started', text: __(FILTER_STARTED), title: __(FILTER_STARTED) },
+ { value: 'any', text: __('Any'), title: __('Any') },
+ { value: 'none', text: __('None'), title: __('None') },
+ { value: '#upcoming', text: __('Upcoming'), title: __('Upcoming') },
+ { value: '#started', text: __('Started'), title: __('Started') },
];
export const SortDirection = {
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
index f96a6ee1255..dc75fe1014a 100644
--- a/app/services/projects/update_pages_service.rb
+++ b/app/services/projects/update_pages_service.rb
@@ -3,18 +3,9 @@
module Projects
class UpdatePagesService < BaseService
InvalidStateError = Class.new(StandardError)
- FailedToExtractError = Class.new(StandardError)
- ExclusiveLeaseTaken = Class.new(StandardError)
-
- include ::Pages::LegacyStorageLease
-
BLOCK_SIZE = 32.kilobytes
PUBLIC_DIR = 'public'
- # this has to be invalid group name,
- # as it shares the namespace with groups
- TMP_EXTRACT_PATH = '@pages.tmp'
-
# old deployment can be cached by pages daemon
# so we need to give pages daemon some time update cache
# 10 minutes is enough, but 30 feels safer
@@ -42,7 +33,6 @@ module Projects
validate_max_entries!
build.artifacts_file.use_file do |artifacts_path|
- deploy_to_legacy_storage(artifacts_path)
create_pages_deployment(artifacts_path, build)
success
end
@@ -78,70 +68,6 @@ module Projects
)
end
- def deploy_to_legacy_storage(artifacts_path)
- # path today used by one project can later be used by another
- # so we can't really scope this feature flag by project or group
- return unless ::Settings.pages.local_store.enabled
-
- return if Feature.enabled?(:skip_pages_deploy_to_legacy_storage, project, default_enabled: :yaml)
-
- # Create temporary directory in which we will extract the artifacts
- make_secure_tmp_dir(tmp_path) do |tmp_path|
- extract_archive!(artifacts_path, tmp_path)
-
- # Check if we did extract public directory
- archive_public_path = File.join(tmp_path, PUBLIC_DIR)
-
- raise InvalidStateError, 'pages miss the public folder' unless Dir.exist?(archive_public_path)
-
- validate_outdated_sha!
-
- deploy_page!(archive_public_path)
- end
- end
-
- def extract_archive!(artifacts_path, temp_path)
- if artifacts.ends_with?('.zip')
- extract_zip_archive!(artifacts_path, temp_path)
- else
- raise InvalidStateError, 'unsupported artifacts format'
- end
- end
-
- def extract_zip_archive!(artifacts_path, temp_path)
- SafeZip::Extract.new(artifacts_path)
- .extract(directories: [PUBLIC_DIR], to: temp_path)
- rescue SafeZip::Extract::Error => e
- raise FailedToExtractError, e.message
- end
-
- def deploy_page!(archive_public_path)
- deployed = try_obtain_lease do
- deploy_page_unsafe!(archive_public_path)
- true
- end
-
- unless deployed
- raise ExclusiveLeaseTaken, "Failed to deploy pages - other deployment is in progress"
- end
- end
-
- def deploy_page_unsafe!(archive_public_path)
- # Do atomic move of pages
- # Move and removal may not be atomic, but they are significantly faster then extracting and removal
- # 1. We move deployed public to previous public path (file removal is slow)
- # 2. We move temporary public to be deployed public
- # 3. We remove previous public path
- FileUtils.mkdir_p(pages_path)
- begin
- FileUtils.move(public_path, previous_public_path)
- rescue StandardError
- end
- FileUtils.move(archive_public_path, public_path)
- ensure
- FileUtils.rm_r(previous_public_path, force: true)
- end
-
def create_pages_deployment(artifacts_path, build)
sha256 = build.job_artifacts_archive.file_sha256
@@ -165,22 +91,6 @@ module Projects
)
end
- def tmp_path
- @tmp_path ||= File.join(::Settings.pages.path, TMP_EXTRACT_PATH)
- end
-
- def pages_path
- @pages_path ||= project.pages_path
- end
-
- def public_path
- @public_path ||= File.join(pages_path, PUBLIC_DIR)
- end
-
- def previous_public_path
- @previous_public_path ||= File.join(pages_path, "#{PUBLIC_DIR}.#{SecureRandom.hex}")
- end
-
def ref
build.ref
end
@@ -216,20 +126,6 @@ module Projects
@pages_deployments_failed_total_counter ||= Gitlab::Metrics.counter(:pages_deployments_failed_total, "Counter of GitLab Pages deployments which failed")
end
- def make_secure_tmp_dir(tmp_path)
- FileUtils.mkdir_p(tmp_path)
- path = Dir.mktmpdir(tmp_dir_prefix, tmp_path)
- begin
- yield(path)
- ensure
- FileUtils.remove_entry_secure(path)
- end
- end
-
- def tmp_dir_prefix
- "project-#{project.id}-build-#{build.id}-"
- end
-
def validate_state!
raise InvalidStateError, 'missing pages artifacts' unless build.artifacts?
raise InvalidStateError, 'missing artifacts metadata' unless build.artifacts_metadata?
diff --git a/app/views/admin/application_settings/_files_limits.html.haml b/app/views/admin/application_settings/_files_limits.html.haml
new file mode 100644
index 00000000000..9cd12fa1caa
--- /dev/null
+++ b/app/views/admin/application_settings/_files_limits.html.haml
@@ -0,0 +1,34 @@
+= gitlab_ui_form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-files-limits-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_errors(@application_setting)
+
+ %fieldset
+ %legend.h5.gl-border-none
+ = _('Unauthenticated API request rate limit')
+ .form-group
+ = f.gitlab_ui_checkbox_component :throttle_unauthenticated_files_api_enabled,
+ _('Enable unauthenticated API request rate limit'),
+ help_text: _('Helps reduce request volume (e.g. from crawlers or abusive bots)'),
+ checkbox_options: { data: { qa_selector: 'throttle_unauthenticated_files_api_checkbox' } }
+ .form-group
+ = f.label :throttle_unauthenticated_files_api_requests_per_period, 'Max unauthenticated API requests per period per IP', class: 'label-bold'
+ = f.number_field :throttle_unauthenticated_files_api_requests_per_period, class: 'form-control gl-form-input'
+ .form-group
+ = f.label :throttle_unauthenticated_files_api_period_in_seconds, 'Unauthenticated API rate limit period in seconds', class: 'label-bold'
+ = f.number_field :throttle_unauthenticated_files_api_period_in_seconds, class: 'form-control gl-form-input'
+
+ %fieldset
+ %legend.h5.gl-border-none
+ = _('Authenticated API request rate limit')
+ .form-group
+ = f.gitlab_ui_checkbox_component :throttle_authenticated_files_api_enabled,
+ _('Enable authenticated API request rate limit'),
+ help_text: _('Helps reduce request volume (e.g. from crawlers or abusive bots)'),
+ checkbox_options: { data: { qa_selector: 'throttle_authenticated_files_api_checkbox' } }
+ .form-group
+ = f.label :throttle_authenticated_files_api_requests_per_period, 'Max authenticated API requests per period per user', class: 'label-bold'
+ = f.number_field :throttle_authenticated_files_api_requests_per_period, class: 'form-control gl-form-input'
+ .form-group
+ = f.label :throttle_authenticated_files_api_period_in_seconds, 'Authenticated API rate limit period in seconds', class: 'label-bold'
+ = f.number_field :throttle_authenticated_files_api_period_in_seconds, class: 'form-control gl-form-input'
+
+ = f.submit 'Save changes', class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml
index 0fb07d2ef17..1bb8a278f2b 100644
--- a/app/views/admin/application_settings/network.html.haml
+++ b/app/views/admin/application_settings/network.html.haml
@@ -34,6 +34,17 @@
= _('Configure specific limits for Packages API requests that supersede the general user and IP rate limits.')
.settings-content
= render 'package_registry_limits'
+- if Feature.enabled?(:files_api_throttling, default_enabled: :yaml)
+ %section.settings.as-files-limits.no-animate#js-files-limits-settings{ class: ('expanded' if expanded_by_default?), data: { testid: 'files-limits-settings' } }
+ .settings-header
+ %h4
+ = _('Files API Rate Limits')
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
+ = expanded_by_default? ? _('Collapse') : _('Expand')
+ %p
+ = _('Configure specific limits for Files API requests that supersede the general user and IP rate limits.')
+ .settings-content
+ = render 'files_limits'
%section.settings.as-git-lfs-limits.no-animate#js-git-lfs-limits-settings{ class: ('expanded' if expanded_by_default?), data: { qa_selector: 'git_lfs_limits_content' } }
.settings-header
diff --git a/babel.config.js b/babel.config.js
index d10de05258b..39bb7858087 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -31,7 +31,7 @@ if (BABEL_ENV === 'coverage') {
plugins.push([
'babel-plugin-istanbul',
{
- exclude: ['spec/javascripts/**/*', 'app/assets/javascripts/locale/**/app.js'],
+ exclude: ['app/assets/javascripts/locale/**/app.js'],
},
]);
}
diff --git a/config/feature_flags/development/skip_pages_deploy_to_legacy_storage.yml b/config/feature_flags/development/files_api_throttling.yml
index a324a6e5ab1..a106c2cb980 100644
--- a/config/feature_flags/development/skip_pages_deploy_to_legacy_storage.yml
+++ b/config/feature_flags/development/files_api_throttling.yml
@@ -1,8 +1,8 @@
---
-name: skip_pages_deploy_to_legacy_storage
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59298
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/327725
-milestone: '13.11'
+name: files_api_throttling
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68560
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338903
+milestone: '14.3'
type: development
-group: group::release
+group: group::source code
default_enabled: false
diff --git a/config/karma.config.js b/config/karma.config.js
deleted file mode 100644
index 39c9dbe264c..00000000000
--- a/config/karma.config.js
+++ /dev/null
@@ -1,203 +0,0 @@
-/* eslint-disable no-inner-declarations, no-param-reassign */
-const path = require('path');
-const chalk = require('chalk');
-const argumentsParser = require('commander');
-const glob = require('glob');
-const webpack = require('webpack');
-const IS_EE = require('./helpers/is_ee_env');
-const webpackConfig = require('./webpack.config');
-
-const ROOT_PATH = path.resolve(__dirname, '..');
-const SPECS_PATH = /^(?:\.[\\/])?(ee[\\/])?spec[\\/]javascripts[\\/]/;
-
-function exitError(message) {
- console.error(chalk.red(`\nError: ${message}\n`));
- process.exit(1);
-}
-
-function exitWarn(message) {
- console.error(chalk.yellow(`\nWarn: ${message}\n`));
- process.exit(0);
-}
-
-function exit(message, isError = true) {
- const fn = isError ? exitError : exitWarn;
-
- fn(message);
-}
-
-// disable problematic options
-webpackConfig.entry = undefined;
-webpackConfig.mode = 'development';
-webpackConfig.optimization.nodeEnv = false;
-webpackConfig.optimization.runtimeChunk = false;
-webpackConfig.optimization.splitChunks = false;
-
-// use quicker sourcemap option
-webpackConfig.devtool = 'cheap-inline-source-map';
-
-// set BABEL_ENV to indicate when we're running code coverage
-webpackConfig.plugins.push(
- new webpack.DefinePlugin({
- 'process.env.BABEL_ENV': JSON.stringify(process.env.BABEL_ENV || process.env.NODE_ENV || null),
- }),
-);
-
-const options = argumentsParser
- .option('--no-fail-on-empty-test-suite')
- .option(
- '-f, --filter-spec [filter]',
- 'Filter run spec files by path. Multiple filters are like a logical OR.',
- (filter, memo) => {
- memo.push(filter, filter.replace(/\/?$/, '/**/*.js'));
- return memo;
- },
- [],
- )
- .parse(process.argv);
-
-const specFilters = options.filterSpec;
-
-const createContext = (specFiles, regex, suffix) => {
- const newContext = specFiles.reduce((context, file) => {
- const relativePath = file.replace(SPECS_PATH, '');
- context[file] = `./${relativePath}`;
- return context;
- }, {});
-
- webpackConfig.plugins.push(
- new webpack.ContextReplacementPlugin(regex, path.join(ROOT_PATH, suffix), newContext),
- );
-};
-
-if (specFilters.length) {
- // resolve filters
- let filteredSpecFiles = specFilters.map((filter) =>
- glob
- .sync(filter, {
- root: ROOT_PATH,
- matchBase: true,
- })
- .filter((filePath) => filePath.endsWith('spec.js')),
- );
-
- // flatten
- filteredSpecFiles = Array.prototype.concat.apply([], filteredSpecFiles);
-
- // remove duplicates
- filteredSpecFiles = [...new Set(filteredSpecFiles)];
-
- if (filteredSpecFiles.length < 1) {
- const isError = options.failOnEmptyTestSuite;
-
- exit('Your filter did not match any test files.', isError);
- }
-
- if (!filteredSpecFiles.every((file) => SPECS_PATH.test(file))) {
- exitError('Test files must be located within /spec/javascripts.');
- }
-
- const CE_FILES = filteredSpecFiles.filter((file) => !file.startsWith('ee'));
- createContext(CE_FILES, /[^e]{2}[\\/]spec[\\/]javascripts$/, 'spec/javascripts');
-
- const EE_FILES = filteredSpecFiles.filter((file) => file.startsWith('ee'));
- createContext(EE_FILES, /ee[\\/]spec[\\/]javascripts$/, 'ee/spec/javascripts');
-}
-
-// Karma configuration
-module.exports = (config) => {
- process.env.TZ = 'Etc/UTC';
-
- const fixturesPath = `tmp/tests/frontend/fixtures${IS_EE ? '-ee' : ''}`;
- const staticFixturesPath = 'spec/frontend/fixtures/static';
-
- const karmaConfig = {
- basePath: ROOT_PATH,
- browsers: ['ChromeHeadlessCustom'],
- client: {
- color: !process.env.CI,
- },
- customLaunchers: {
- ChromeHeadlessCustom: {
- base: 'ChromeHeadless',
- displayName: 'Chrome',
- flags: [
- // chrome cannot run in sandboxed mode inside a docker container unless it is run with
- // escalated kernel privileges (e.g. docker run --cap-add=CAP_SYS_ADMIN)
- '--no-sandbox',
- // https://bugs.chromium.org/p/chromedriver/issues/detail?id=2870
- '--enable-features=NetworkService,NetworkServiceInProcess',
- ],
- },
- },
- frameworks: ['jasmine'],
- files: [
- { pattern: 'spec/javascripts/test_bundle.js', watched: false },
- { pattern: `${fixturesPath}/**/*`, included: false },
- { pattern: `${staticFixturesPath}/**/*`, included: false },
- ],
- proxies: {
- '/fixtures/': `/base/${fixturesPath}/`,
- '/fixtures/static/': `/base/${staticFixturesPath}/`,
- },
- preprocessors: {
- 'spec/javascripts/**/*.js': ['webpack', 'sourcemap'],
- 'ee/spec/javascripts/**/*.js': ['webpack', 'sourcemap'],
- },
- reporters: ['mocha'],
- webpack: webpackConfig,
- webpackMiddleware: { stats: 'errors-only' },
- plugins: [
- 'karma-chrome-launcher',
- 'karma-coverage-istanbul-reporter',
- 'karma-jasmine',
- 'karma-junit-reporter',
- 'karma-mocha-reporter',
- 'karma-sourcemap-loader',
- 'karma-webpack',
- ],
- };
-
- if (process.env.CI) {
- karmaConfig.reporters.push('junit');
- karmaConfig.junitReporter = {
- outputFile: 'junit_karma.xml',
- useBrowserName: false,
- };
- } else {
- // ignore 404s in local environment because we are not fixing them and they bloat the log
- function ignore404() {
- return (request, response /* next */) => {
- response.writeHead(404);
- return response.end('NOT FOUND');
- };
- }
-
- karmaConfig.middleware = ['ignore-404'];
- karmaConfig.plugins.push({
- 'middleware:ignore-404': ['factory', ignore404],
- });
- }
-
- if (process.env.BABEL_ENV === 'coverage' || process.env.NODE_ENV === 'coverage') {
- karmaConfig.reporters.push('coverage-istanbul');
- karmaConfig.coverageIstanbulReporter = {
- reports: ['html', 'text-summary', 'cobertura'],
- dir: 'coverage-javascript/',
- subdir: '.',
- fixWebpackSourcePaths: true,
- };
- karmaConfig.browserNoActivityTimeout = 60000; // 60 seconds
- }
-
- if (process.env.DEBUG) {
- karmaConfig.logLevel = config.LOG_DEBUG;
- process.env.CHROME_LOG_FILE = process.env.CHROME_LOG_FILE || 'chrome_debug.log';
- }
-
- if (process.env.CHROME_LOG_FILE) {
- karmaConfig.customLaunchers.ChromeHeadlessCustom.flags.push('--enable-logging', '--v=1');
- }
-
- config.set(karmaConfig);
-};
diff --git a/config/webpack.config.js b/config/webpack.config.js
index f5cd0b154e4..d09d9f51605 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -154,7 +154,6 @@ const alias = {
vendor: path.join(ROOT_PATH, 'vendor/assets/javascripts'),
vue$: 'vue/dist/vue.esm.js',
jquery$: 'jquery/dist/jquery.slim.js',
- spec: path.join(ROOT_PATH, 'spec/javascripts'),
jest: path.join(ROOT_PATH, 'spec/frontend'),
shared_queries: path.join(ROOT_PATH, 'app/graphql/queries'),
@@ -178,7 +177,6 @@ if (IS_EE) {
ee_empty_states: path.join(ROOT_PATH, 'ee/app/views/shared/empty_states'),
ee_icons: path.join(ROOT_PATH, 'ee/app/views/shared/icons'),
ee_images: path.join(ROOT_PATH, 'ee/app/assets/images'),
- ee_spec: path.join(ROOT_PATH, 'ee/spec/javascripts'),
ee_jest: path.join(ROOT_PATH, 'ee/spec/frontend'),
ee_else_ce: path.join(ROOT_PATH, 'ee/app/assets/javascripts'),
});
@@ -191,7 +189,6 @@ if (IS_JH) {
jh_empty_states: path.join(ROOT_PATH, 'jh/app/views/shared/empty_states'),
jh_icons: path.join(ROOT_PATH, 'jh/app/views/shared/icons'),
jh_images: path.join(ROOT_PATH, 'jh/app/assets/images'),
- jh_spec: path.join(ROOT_PATH, 'jh/spec/javascripts'),
jh_jest: path.join(ROOT_PATH, 'jh/spec/frontend'),
jh_else_ce: path.join(ROOT_PATH, 'jh/app/assets/javascripts'),
});
diff --git a/danger/karma/Dangerfile b/danger/karma/Dangerfile
deleted file mode 100644
index e05bd86313f..00000000000
--- a/danger/karma/Dangerfile
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/SignalException
-
-def get_karma_files(files)
- files.select do |file|
- file.start_with?('ee/spec/javascripts', 'spec/javascripts') &&
- file.end_with?('_spec.js') &&
- !file.end_with?('browser_spec.js')
- end
-end
-
-new_karma_files = get_karma_files(git.added_files.to_a)
-
-unless new_karma_files.empty?
-
- if helper.ci?
- markdown(<<~MARKDOWN)
- ## New karma spec file
-
- New frontend specs ([except `browser_specs`](https://gitlab.com/gitlab-org/gitlab/blob/3b6fe2f1077eedb0b8aff02a7350234f0b7dc4f9/spec/javascripts/lib/utils/browser_spec.js#L2)) should be
- [written in jest](https://docs.gitlab.com/ee/development/testing_guide/frontend_testing.html#jest).
-
- You have created the following tests, please migrate them over to jest:
-
- * #{new_karma_files.map { |path| "`#{path}`" }.join("\n* ")}
- MARKDOWN
- end
-
- fail "You have created a new karma spec file"
-
-end
-
-changed_karma_files = get_karma_files(helper.all_changed_files) - new_karma_files
-
-return if changed_karma_files.empty?
-
-warn 'You have edited karma spec files. Please consider migrating them to jest.'
-
-if helper.ci?
- markdown(<<~MARKDOWN)
- ## Edited karma files
-
- You have edited the following karma spec files. Please consider migrating them to jest:
-
- * #{changed_karma_files.map { |path| "`#{path}`" }.join("\n* ")}
-
- In order to align with our Iteration value, migration can also be done as a follow-up.
-
- For more information: [Jestodus epic](https://gitlab.com/groups/gitlab-org/-/epics/895)
- MARKDOWN
-end
diff --git a/db/post_migrate/20210818185845_backfill_projects_with_coverage.rb b/db/post_migrate/20210818185845_backfill_projects_with_coverage.rb
new file mode 100644
index 00000000000..003b7536767
--- /dev/null
+++ b/db/post_migrate/20210818185845_backfill_projects_with_coverage.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class BackfillProjectsWithCoverage < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ MIGRATION = 'BackfillProjectsWithCoverage'
+ DELAY_INTERVAL = 2.minutes
+ BATCH_SIZE = 10_000
+ SUB_BATCH_SIZE = 1_000
+
+ disable_ddl_transaction!
+
+ class CiDailyBuildGroupReportResult < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'ci_daily_build_group_report_results'
+ end
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ CiDailyBuildGroupReportResult,
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ other_job_arguments: [SUB_BATCH_SIZE]
+ )
+ end
+
+ def down
+ # noop
+ end
+end
diff --git a/db/schema_migrations/20210818185845 b/db/schema_migrations/20210818185845
new file mode 100644
index 00000000000..7ed2204aeb6
--- /dev/null
+++ b/db/schema_migrations/20210818185845
@@ -0,0 +1 @@
+dc8ca347fb0c87e1a66389fd9f37fa9702f8bd53237ada40192bb0a875dbe940 \ No newline at end of file
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 54fb13c566a..b0672f29b65 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -298,7 +298,8 @@ control over how the Pages daemon runs and serves content in your environment.
| `pages_path` | The directory on disk where pages are stored, defaults to `GITLAB-RAILS/shared/pages`. |
| **`pages_nginx[]`** | |
| `enable` | Include a virtual host `server{}` block for Pages inside NGINX. Needed for NGINX to proxy traffic back to the Pages daemon. Set to `false` if the Pages daemon should directly receive all requests, for example, when using [custom domains](index.md#custom-domains). |
-| `FF_ENABLE_REDIRECTS` | Feature flag to disable redirects (enabled by default). Read the [redirects documentation](../../user/project/pages/redirects.md#disable-redirects) for more information. |
+| `FF_ENABLE_REDIRECTS` | Feature flag to enable/disable redirects (enabled by default). Read the [redirects documentation](../../user/project/pages/redirects.md#feature-flag-for-redirects) for more information. |
+| `FF_ENABLE_PLACEHOLDERS` | Feature flag to enable/disable rewrites (disabled by default). Read the [redirects documentation](../../user/project/pages/redirects.md#feature-flag-for-rewrites) for more information. |
| `use_legacy_storage` | Temporarily-introduced parameter allowing to use legacy domain configuration source and storage. [Will be removed in GitLab 14.3](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6166). |
---
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 5f202858361..95ae5720f2b 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -1221,7 +1221,7 @@ Input type: `CreateEpicInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationcreateepicclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationcreateepicepic"></a>`epic` | [`Epic`](#epic) | The created epic. |
+| <a id="mutationcreateepicepic"></a>`epic` | [`Epic`](#epic) | Created epic. |
| <a id="mutationcreateepicerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.createImageDiffNote`
@@ -1262,7 +1262,7 @@ Input type: `CreateIssueInput`
| <a id="mutationcreateissuediscussiontoresolve"></a>`discussionToResolve` | [`String`](#string) | ID of a discussion to resolve. Also pass `merge_request_to_resolve_discussions_of`. |
| <a id="mutationcreateissueduedate"></a>`dueDate` | [`ISO8601Date`](#iso8601date) | Due date of the issue. |
| <a id="mutationcreateissueepicid"></a>`epicId` | [`EpicID`](#epicid) | ID of an epic to associate the issue with. |
-| <a id="mutationcreateissuehealthstatus"></a>`healthStatus` | [`HealthStatus`](#healthstatus) | The desired health status. |
+| <a id="mutationcreateissuehealthstatus"></a>`healthStatus` | [`HealthStatus`](#healthstatus) | Desired health status. |
| <a id="mutationcreateissueiid"></a>`iid` | [`Int`](#int) | IID (internal ID) of a project issue. Only admins and project owners can modify. |
| <a id="mutationcreateissuelabelids"></a>`labelIds` | [`[LabelID!]`](#labelid) | IDs of labels to be added to the issue. |
| <a id="mutationcreateissuelabels"></a>`labels` | [`[String!]`](#string) | Labels of the issue. |
@@ -1272,7 +1272,7 @@ Input type: `CreateIssueInput`
| <a id="mutationcreateissueprojectpath"></a>`projectPath` | [`ID!`](#id) | Project full path the issue is associated with. |
| <a id="mutationcreateissuetitle"></a>`title` | [`String!`](#string) | Title of the issue. |
| <a id="mutationcreateissuetype"></a>`type` | [`IssueType`](#issuetype) | Type of the issue. |
-| <a id="mutationcreateissueweight"></a>`weight` | [`Int`](#int) | The weight of the issue. |
+| <a id="mutationcreateissueweight"></a>`weight` | [`Int`](#int) | Weight of the issue. |
#### Fields
@@ -1295,13 +1295,13 @@ Input type: `CreateIterationInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationcreateiterationclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationcreateiterationdescription"></a>`description` | [`String`](#string) | The description of the iteration. |
-| <a id="mutationcreateiterationduedate"></a>`dueDate` | [`String`](#string) | The end date of the iteration. |
+| <a id="mutationcreateiterationdescription"></a>`description` | [`String`](#string) | Description of the iteration. |
+| <a id="mutationcreateiterationduedate"></a>`dueDate` | [`String`](#string) | End date of the iteration. |
| <a id="mutationcreateiterationgrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
| <a id="mutationcreateiterationiterationscadenceid"></a>`iterationsCadenceId` | [`IterationsCadenceID`](#iterationscadenceid) | Global ID of the iterations cadence to be assigned to newly created iteration. |
| <a id="mutationcreateiterationprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
-| <a id="mutationcreateiterationstartdate"></a>`startDate` | [`String`](#string) | The start date of the iteration. |
-| <a id="mutationcreateiterationtitle"></a>`title` | [`String`](#string) | The title of the iteration. |
+| <a id="mutationcreateiterationstartdate"></a>`startDate` | [`String`](#string) | Start date of the iteration. |
+| <a id="mutationcreateiterationtitle"></a>`title` | [`String`](#string) | Title of the iteration. |
#### Fields
@@ -1309,7 +1309,7 @@ Input type: `CreateIterationInput`
| ---- | ---- | ----------- |
| <a id="mutationcreateiterationclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcreateiterationerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationcreateiterationiteration"></a>`iteration` | [`Iteration`](#iteration) | The created iteration. |
+| <a id="mutationcreateiterationiteration"></a>`iteration` | [`Iteration`](#iteration) | Created iteration. |
### `Mutation.createNote`
@@ -1393,10 +1393,10 @@ Input type: `CreateTestCaseInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationcreatetestcaseclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationcreatetestcasedescription"></a>`description` | [`String`](#string) | The test case description. |
-| <a id="mutationcreatetestcaselabelids"></a>`labelIds` | [`[ID!]`](#id) | The IDs of labels to be added to the test case. |
-| <a id="mutationcreatetestcaseprojectpath"></a>`projectPath` | [`ID!`](#id) | The project full path to create the test case. |
-| <a id="mutationcreatetestcasetitle"></a>`title` | [`String!`](#string) | The test case title. |
+| <a id="mutationcreatetestcasedescription"></a>`description` | [`String`](#string) | Test case description. |
+| <a id="mutationcreatetestcaselabelids"></a>`labelIds` | [`[ID!]`](#id) | IDs of labels to be added to the test case. |
+| <a id="mutationcreatetestcaseprojectpath"></a>`projectPath` | [`ID!`](#id) | Project full path to create the test case in. |
+| <a id="mutationcreatetestcasetitle"></a>`title` | [`String!`](#string) | Test case title. |
#### Fields
@@ -1404,7 +1404,7 @@ Input type: `CreateTestCaseInput`
| ---- | ---- | ----------- |
| <a id="mutationcreatetestcaseclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcreatetestcaseerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationcreatetestcasetestcase"></a>`testCase` | [`Issue`](#issue) | The test case created. |
+| <a id="mutationcreatetestcasetestcase"></a>`testCase` | [`Issue`](#issue) | Test case created. |
### `Mutation.dastOnDemandScanCreate`
@@ -2109,18 +2109,18 @@ Input type: `EpicAddIssueInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationepicaddissueclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationepicaddissuegrouppath"></a>`groupPath` | [`ID!`](#id) | The group the epic to mutate belongs to. |
-| <a id="mutationepicaddissueiid"></a>`iid` | [`ID!`](#id) | The IID of the epic to mutate. |
-| <a id="mutationepicaddissueissueiid"></a>`issueIid` | [`String!`](#string) | The IID of the issue to be added. |
-| <a id="mutationepicaddissueprojectpath"></a>`projectPath` | [`ID!`](#id) | The full path of the project the issue belongs to. |
+| <a id="mutationepicaddissuegrouppath"></a>`groupPath` | [`ID!`](#id) | Group the epic to mutate belongs to. |
+| <a id="mutationepicaddissueiid"></a>`iid` | [`ID!`](#id) | IID of the epic to mutate. |
+| <a id="mutationepicaddissueissueiid"></a>`issueIid` | [`String!`](#string) | IID of the issue to be added. |
+| <a id="mutationepicaddissueprojectpath"></a>`projectPath` | [`ID!`](#id) | Full path of the project the issue belongs to. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationepicaddissueclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationepicaddissueepic"></a>`epic` | [`Epic`](#epic) | The epic after mutation. |
-| <a id="mutationepicaddissueepicissue"></a>`epicIssue` | [`EpicIssue`](#epicissue) | The epic-issue relation. |
+| <a id="mutationepicaddissueepic"></a>`epic` | [`Epic`](#epic) | Epic after mutation. |
+| <a id="mutationepicaddissueepicissue"></a>`epicIssue` | [`EpicIssue`](#epicissue) | Epic-issue relationship. |
| <a id="mutationepicaddissueerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.epicBoardCreate`
@@ -2246,16 +2246,16 @@ Input type: `EpicSetSubscriptionInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationepicsetsubscriptionclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationepicsetsubscriptiongrouppath"></a>`groupPath` | [`ID!`](#id) | The group the epic to mutate belongs to. |
-| <a id="mutationepicsetsubscriptioniid"></a>`iid` | [`ID!`](#id) | The IID of the epic to mutate. |
-| <a id="mutationepicsetsubscriptionsubscribedstate"></a>`subscribedState` | [`Boolean!`](#boolean) | The desired state of the subscription. |
+| <a id="mutationepicsetsubscriptiongrouppath"></a>`groupPath` | [`ID!`](#id) | Group the epic to mutate belongs to. |
+| <a id="mutationepicsetsubscriptioniid"></a>`iid` | [`ID!`](#id) | IID of the epic to mutate. |
+| <a id="mutationepicsetsubscriptionsubscribedstate"></a>`subscribedState` | [`Boolean!`](#boolean) | Desired state of the subscription. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationepicsetsubscriptionclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationepicsetsubscriptionepic"></a>`epic` | [`Epic`](#epic) | The epic after mutation. |
+| <a id="mutationepicsetsubscriptionepic"></a>`epic` | [`Epic`](#epic) | Epic after mutation. |
| <a id="mutationepicsetsubscriptionerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.epicTreeReorder`
@@ -2266,7 +2266,7 @@ Input type: `EpicTreeReorderInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationepictreereorderbaseepicid"></a>`baseEpicId` | [`EpicID!`](#epicid) | The ID of the base epic of the tree. |
+| <a id="mutationepictreereorderbaseepicid"></a>`baseEpicId` | [`EpicID!`](#epicid) | ID of the base epic of the tree. |
| <a id="mutationepictreereorderclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationepictreereordermoved"></a>`moved` | [`EpicTreeNodeFieldsInputType!`](#epictreenodefieldsinputtype) | Parameters for updating the tree positions. |
@@ -2286,10 +2286,10 @@ Input type: `EscalationPolicyCreateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationescalationpolicycreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationescalationpolicycreatedescription"></a>`description` | [`String`](#string) | The description of the escalation policy. |
-| <a id="mutationescalationpolicycreatename"></a>`name` | [`String!`](#string) | The name of the escalation policy. |
-| <a id="mutationescalationpolicycreateprojectpath"></a>`projectPath` | [`ID!`](#id) | The project to create the escalation policy for. |
-| <a id="mutationescalationpolicycreaterules"></a>`rules` | [`[EscalationRuleInput!]!`](#escalationruleinput) | The steps of the escalation policy. |
+| <a id="mutationescalationpolicycreatedescription"></a>`description` | [`String`](#string) | Description of the escalation policy. |
+| <a id="mutationescalationpolicycreatename"></a>`name` | [`String!`](#string) | Name of the escalation policy. |
+| <a id="mutationescalationpolicycreateprojectpath"></a>`projectPath` | [`ID!`](#id) | Project to create the escalation policy for. |
+| <a id="mutationescalationpolicycreaterules"></a>`rules` | [`[EscalationRuleInput!]!`](#escalationruleinput) | Steps of the escalation policy. |
#### Fields
@@ -2297,7 +2297,7 @@ Input type: `EscalationPolicyCreateInput`
| ---- | ---- | ----------- |
| <a id="mutationescalationpolicycreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationescalationpolicycreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationescalationpolicycreateescalationpolicy"></a>`escalationPolicy` | [`EscalationPolicyType`](#escalationpolicytype) | The escalation policy. |
+| <a id="mutationescalationpolicycreateescalationpolicy"></a>`escalationPolicy` | [`EscalationPolicyType`](#escalationpolicytype) | Escalation policy. |
### `Mutation.escalationPolicyDestroy`
@@ -2308,7 +2308,7 @@ Input type: `EscalationPolicyDestroyInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationescalationpolicydestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationescalationpolicydestroyid"></a>`id` | [`IncidentManagementEscalationPolicyID!`](#incidentmanagementescalationpolicyid) | The escalation policy internal ID to remove. |
+| <a id="mutationescalationpolicydestroyid"></a>`id` | [`IncidentManagementEscalationPolicyID!`](#incidentmanagementescalationpolicyid) | Escalation policy internal ID to remove. |
#### Fields
@@ -2316,7 +2316,7 @@ Input type: `EscalationPolicyDestroyInput`
| ---- | ---- | ----------- |
| <a id="mutationescalationpolicydestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationescalationpolicydestroyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationescalationpolicydestroyescalationpolicy"></a>`escalationPolicy` | [`EscalationPolicyType`](#escalationpolicytype) | The escalation policy. |
+| <a id="mutationescalationpolicydestroyescalationpolicy"></a>`escalationPolicy` | [`EscalationPolicyType`](#escalationpolicytype) | Escalation policy. |
### `Mutation.escalationPolicyUpdate`
@@ -2327,10 +2327,10 @@ Input type: `EscalationPolicyUpdateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationescalationpolicyupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationescalationpolicyupdatedescription"></a>`description` | [`String`](#string) | The description of the escalation policy. |
-| <a id="mutationescalationpolicyupdateid"></a>`id` | [`IncidentManagementEscalationPolicyID!`](#incidentmanagementescalationpolicyid) | The ID of the on-call schedule to create the on-call rotation in. |
-| <a id="mutationescalationpolicyupdatename"></a>`name` | [`String`](#string) | The name of the escalation policy. |
-| <a id="mutationescalationpolicyupdaterules"></a>`rules` | [`[EscalationRuleInput!]`](#escalationruleinput) | The steps of the escalation policy. |
+| <a id="mutationescalationpolicyupdatedescription"></a>`description` | [`String`](#string) | Description of the escalation policy. |
+| <a id="mutationescalationpolicyupdateid"></a>`id` | [`IncidentManagementEscalationPolicyID!`](#incidentmanagementescalationpolicyid) | ID of the on-call schedule to create the on-call rotation in. |
+| <a id="mutationescalationpolicyupdatename"></a>`name` | [`String`](#string) | Name of the escalation policy. |
+| <a id="mutationescalationpolicyupdaterules"></a>`rules` | [`[EscalationRuleInput!]`](#escalationruleinput) | Steps of the escalation policy. |
#### Fields
@@ -2338,7 +2338,7 @@ Input type: `EscalationPolicyUpdateInput`
| ---- | ---- | ----------- |
| <a id="mutationescalationpolicyupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationescalationpolicyupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationescalationpolicyupdateescalationpolicy"></a>`escalationPolicy` | [`EscalationPolicyType`](#escalationpolicytype) | The escalation policy. |
+| <a id="mutationescalationpolicyupdateescalationpolicy"></a>`escalationPolicy` | [`EscalationPolicyType`](#escalationpolicytype) | Escalation policy. |
### `Mutation.exportRequirements`
@@ -2380,7 +2380,7 @@ Input type: `GitlabSubscriptionActivateInput`
| ---- | ---- | ----------- |
| <a id="mutationgitlabsubscriptionactivateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationgitlabsubscriptionactivateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationgitlabsubscriptionactivatelicense"></a>`license` | [`CurrentLicense`](#currentlicense) | The current license. |
+| <a id="mutationgitlabsubscriptionactivatelicense"></a>`license` | [`CurrentLicense`](#currentlicense) | Current license. |
### `Mutation.groupUpdate`
@@ -2628,7 +2628,7 @@ Input type: `IssueSetIterationInput`
| ---- | ---- | ----------- |
| <a id="mutationissuesetiterationclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationissuesetiterationiid"></a>`iid` | [`String!`](#string) | IID of the issue to mutate. |
-| <a id="mutationissuesetiterationiterationid"></a>`iterationId` | [`IterationID`](#iterationid) | The iteration to assign to the issue. |
+| <a id="mutationissuesetiterationiterationid"></a>`iterationId` | [`IterationID`](#iterationid) | Iteration to assign to the issue. |
| <a id="mutationissuesetiterationprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the issue to mutate is in. |
#### Fields
@@ -2736,7 +2736,7 @@ Input type: `IterationCadenceCreateInput`
| <a id="mutationiterationcadencecreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationiterationcadencecreatedescription"></a>`description` | [`String`](#string) | Description of the iteration cadence. Maximum length is 5000 characters. |
| <a id="mutationiterationcadencecreatedurationinweeks"></a>`durationInWeeks` | [`Int`](#int) | Duration in weeks of the iterations within this cadence. |
-| <a id="mutationiterationcadencecreategrouppath"></a>`groupPath` | [`ID!`](#id) | The group where the iteration cadence is created. |
+| <a id="mutationiterationcadencecreategrouppath"></a>`groupPath` | [`ID!`](#id) | Group where the iteration cadence is created. |
| <a id="mutationiterationcadencecreateiterationsinadvance"></a>`iterationsInAdvance` | [`Int`](#int) | Future iterations to be created when iteration cadence is set to automatic. |
| <a id="mutationiterationcadencecreaterollover"></a>`rollOver` | [`Boolean`](#boolean) | Whether the iteration cadence should roll over issues to the next iteration or not. |
| <a id="mutationiterationcadencecreatestartdate"></a>`startDate` | [`Time`](#time) | Timestamp of the iteration cadence start date. |
@@ -2748,7 +2748,7 @@ Input type: `IterationCadenceCreateInput`
| ---- | ---- | ----------- |
| <a id="mutationiterationcadencecreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationiterationcadencecreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationiterationcadencecreateiterationcadence"></a>`iterationCadence` | [`IterationCadence`](#iterationcadence) | The created iteration cadence. |
+| <a id="mutationiterationcadencecreateiterationcadence"></a>`iterationCadence` | [`IterationCadence`](#iterationcadence) | Created iteration cadence. |
### `Mutation.iterationCadenceDestroy`
@@ -2794,7 +2794,7 @@ Input type: `IterationCadenceUpdateInput`
| ---- | ---- | ----------- |
| <a id="mutationiterationcadenceupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationiterationcadenceupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationiterationcadenceupdateiterationcadence"></a>`iterationCadence` | [`IterationCadence`](#iterationcadence) | The updated iteration cadence. |
+| <a id="mutationiterationcadenceupdateiterationcadence"></a>`iterationCadence` | [`IterationCadence`](#iterationcadence) | Updated iteration cadence. |
### `Mutation.iterationCreate`
@@ -2805,13 +2805,13 @@ Input type: `iterationCreateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationiterationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationiterationcreatedescription"></a>`description` | [`String`](#string) | The description of the iteration. |
-| <a id="mutationiterationcreateduedate"></a>`dueDate` | [`String`](#string) | The end date of the iteration. |
+| <a id="mutationiterationcreatedescription"></a>`description` | [`String`](#string) | Description of the iteration. |
+| <a id="mutationiterationcreateduedate"></a>`dueDate` | [`String`](#string) | End date of the iteration. |
| <a id="mutationiterationcreategrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
| <a id="mutationiterationcreateiterationscadenceid"></a>`iterationsCadenceId` | [`IterationsCadenceID`](#iterationscadenceid) | Global ID of the iterations cadence to be assigned to newly created iteration. |
| <a id="mutationiterationcreateprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
-| <a id="mutationiterationcreatestartdate"></a>`startDate` | [`String`](#string) | The start date of the iteration. |
-| <a id="mutationiterationcreatetitle"></a>`title` | [`String`](#string) | The title of the iteration. |
+| <a id="mutationiterationcreatestartdate"></a>`startDate` | [`String`](#string) | Start date of the iteration. |
+| <a id="mutationiterationcreatetitle"></a>`title` | [`String`](#string) | Title of the iteration. |
#### Fields
@@ -2819,7 +2819,7 @@ Input type: `iterationCreateInput`
| ---- | ---- | ----------- |
| <a id="mutationiterationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationiterationcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationiterationcreateiteration"></a>`iteration` | [`Iteration`](#iteration) | The created iteration. |
+| <a id="mutationiterationcreateiteration"></a>`iteration` | [`Iteration`](#iteration) | Created iteration. |
### `Mutation.iterationDelete`
@@ -3263,7 +3263,7 @@ Input type: `NamespaceIncreaseStorageTemporarilyInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationnamespaceincreasestoragetemporarilyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationnamespaceincreasestoragetemporarilyid"></a>`id` | [`NamespaceID!`](#namespaceid) | The global ID of the namespace to mutate. |
+| <a id="mutationnamespaceincreasestoragetemporarilyid"></a>`id` | [`NamespaceID!`](#namespaceid) | Global ID of the namespace to mutate. |
#### Fields
@@ -3271,7 +3271,7 @@ Input type: `NamespaceIncreaseStorageTemporarilyInput`
| ---- | ---- | ----------- |
| <a id="mutationnamespaceincreasestoragetemporarilyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationnamespaceincreasestoragetemporarilyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationnamespaceincreasestoragetemporarilynamespace"></a>`namespace` | [`Namespace`](#namespace) | The namespace after mutation. |
+| <a id="mutationnamespaceincreasestoragetemporarilynamespace"></a>`namespace` | [`Namespace`](#namespace) | Namespace after mutation. |
### `Mutation.oncallRotationCreate`
@@ -3281,15 +3281,15 @@ Input type: `OncallRotationCreateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationoncallrotationcreateactiveperiod"></a>`activePeriod` | [`OncallRotationActivePeriodInputType`](#oncallrotationactiveperiodinputtype) | The active period of time that the on-call rotation should take place. |
+| <a id="mutationoncallrotationcreateactiveperiod"></a>`activePeriod` | [`OncallRotationActivePeriodInputType`](#oncallrotationactiveperiodinputtype) | Active period of time that the on-call rotation should take place. |
| <a id="mutationoncallrotationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationoncallrotationcreateendsat"></a>`endsAt` | [`OncallRotationDateInputType`](#oncallrotationdateinputtype) | The end date and time of the on-call rotation, in the timezone of the on-call schedule. |
-| <a id="mutationoncallrotationcreatename"></a>`name` | [`String!`](#string) | The name of the on-call rotation. |
-| <a id="mutationoncallrotationcreateparticipants"></a>`participants` | [`[OncallUserInputType!]!`](#oncalluserinputtype) | The usernames of users participating in the on-call rotation. A maximum limit of 100 participants applies. |
-| <a id="mutationoncallrotationcreateprojectpath"></a>`projectPath` | [`ID!`](#id) | The project to create the on-call schedule in. |
-| <a id="mutationoncallrotationcreaterotationlength"></a>`rotationLength` | [`OncallRotationLengthInputType!`](#oncallrotationlengthinputtype) | The rotation length of the on-call rotation. |
-| <a id="mutationoncallrotationcreatescheduleiid"></a>`scheduleIid` | [`String!`](#string) | The IID of the on-call schedule to create the on-call rotation in. |
-| <a id="mutationoncallrotationcreatestartsat"></a>`startsAt` | [`OncallRotationDateInputType!`](#oncallrotationdateinputtype) | The start date and time of the on-call rotation, in the timezone of the on-call schedule. |
+| <a id="mutationoncallrotationcreateendsat"></a>`endsAt` | [`OncallRotationDateInputType`](#oncallrotationdateinputtype) | End date and time of the on-call rotation, in the timezone of the on-call schedule. |
+| <a id="mutationoncallrotationcreatename"></a>`name` | [`String!`](#string) | Name of the on-call rotation. |
+| <a id="mutationoncallrotationcreateparticipants"></a>`participants` | [`[OncallUserInputType!]!`](#oncalluserinputtype) | Usernames of users participating in the on-call rotation. A maximum limit of 100 participants applies. |
+| <a id="mutationoncallrotationcreateprojectpath"></a>`projectPath` | [`ID!`](#id) | Project to create the on-call schedule in. |
+| <a id="mutationoncallrotationcreaterotationlength"></a>`rotationLength` | [`OncallRotationLengthInputType!`](#oncallrotationlengthinputtype) | Rotation length of the on-call rotation. |
+| <a id="mutationoncallrotationcreatescheduleiid"></a>`scheduleIid` | [`String!`](#string) | IID of the on-call schedule to create the on-call rotation in. |
+| <a id="mutationoncallrotationcreatestartsat"></a>`startsAt` | [`OncallRotationDateInputType!`](#oncallrotationdateinputtype) | Start date and time of the on-call rotation, in the timezone of the on-call schedule. |
#### Fields
@@ -3297,7 +3297,7 @@ Input type: `OncallRotationCreateInput`
| ---- | ---- | ----------- |
| <a id="mutationoncallrotationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationoncallrotationcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationoncallrotationcreateoncallrotation"></a>`oncallRotation` | [`IncidentManagementOncallRotation`](#incidentmanagementoncallrotation) | The on-call rotation. |
+| <a id="mutationoncallrotationcreateoncallrotation"></a>`oncallRotation` | [`IncidentManagementOncallRotation`](#incidentmanagementoncallrotation) | On-call rotation. |
### `Mutation.oncallRotationDestroy`
@@ -3308,9 +3308,9 @@ Input type: `OncallRotationDestroyInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationoncallrotationdestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationoncallrotationdestroyid"></a>`id` | [`IncidentManagementOncallRotationID!`](#incidentmanagementoncallrotationid) | The ID of the on-call rotation to remove. |
-| <a id="mutationoncallrotationdestroyprojectpath"></a>`projectPath` | [`ID!`](#id) | The project to remove the on-call schedule from. |
-| <a id="mutationoncallrotationdestroyscheduleiid"></a>`scheduleIid` | [`String!`](#string) | The IID of the on-call schedule to the on-call rotation belongs to. |
+| <a id="mutationoncallrotationdestroyid"></a>`id` | [`IncidentManagementOncallRotationID!`](#incidentmanagementoncallrotationid) | ID of the on-call rotation to remove. |
+| <a id="mutationoncallrotationdestroyprojectpath"></a>`projectPath` | [`ID!`](#id) | Project to remove the on-call schedule from. |
+| <a id="mutationoncallrotationdestroyscheduleiid"></a>`scheduleIid` | [`String!`](#string) | IID of the on-call schedule to the on-call rotation belongs to. |
#### Fields
@@ -3318,7 +3318,7 @@ Input type: `OncallRotationDestroyInput`
| ---- | ---- | ----------- |
| <a id="mutationoncallrotationdestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationoncallrotationdestroyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationoncallrotationdestroyoncallrotation"></a>`oncallRotation` | [`IncidentManagementOncallRotation`](#incidentmanagementoncallrotation) | The on-call rotation. |
+| <a id="mutationoncallrotationdestroyoncallrotation"></a>`oncallRotation` | [`IncidentManagementOncallRotation`](#incidentmanagementoncallrotation) | On-call rotation. |
### `Mutation.oncallRotationUpdate`
@@ -3328,14 +3328,14 @@ Input type: `OncallRotationUpdateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationoncallrotationupdateactiveperiod"></a>`activePeriod` | [`OncallRotationActivePeriodInputType`](#oncallrotationactiveperiodinputtype) | The active period of time that the on-call rotation should take place. |
+| <a id="mutationoncallrotationupdateactiveperiod"></a>`activePeriod` | [`OncallRotationActivePeriodInputType`](#oncallrotationactiveperiodinputtype) | Active period of time that the on-call rotation should take place. |
| <a id="mutationoncallrotationupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationoncallrotationupdateendsat"></a>`endsAt` | [`OncallRotationDateInputType`](#oncallrotationdateinputtype) | The end date and time of the on-call rotation, in the timezone of the on-call schedule. |
-| <a id="mutationoncallrotationupdateid"></a>`id` | [`IncidentManagementOncallRotationID!`](#incidentmanagementoncallrotationid) | The ID of the on-call schedule to create the on-call rotation in. |
-| <a id="mutationoncallrotationupdatename"></a>`name` | [`String`](#string) | The name of the on-call rotation. |
-| <a id="mutationoncallrotationupdateparticipants"></a>`participants` | [`[OncallUserInputType!]`](#oncalluserinputtype) | The usernames of users participating in the on-call rotation. A maximum limit of 100 participants applies. |
-| <a id="mutationoncallrotationupdaterotationlength"></a>`rotationLength` | [`OncallRotationLengthInputType`](#oncallrotationlengthinputtype) | The rotation length of the on-call rotation. |
-| <a id="mutationoncallrotationupdatestartsat"></a>`startsAt` | [`OncallRotationDateInputType`](#oncallrotationdateinputtype) | The start date and time of the on-call rotation, in the timezone of the on-call schedule. |
+| <a id="mutationoncallrotationupdateendsat"></a>`endsAt` | [`OncallRotationDateInputType`](#oncallrotationdateinputtype) | End date and time of the on-call rotation, in the timezone of the on-call schedule. |
+| <a id="mutationoncallrotationupdateid"></a>`id` | [`IncidentManagementOncallRotationID!`](#incidentmanagementoncallrotationid) | ID of the on-call schedule to create the on-call rotation in. |
+| <a id="mutationoncallrotationupdatename"></a>`name` | [`String`](#string) | Name of the on-call rotation. |
+| <a id="mutationoncallrotationupdateparticipants"></a>`participants` | [`[OncallUserInputType!]`](#oncalluserinputtype) | Usernames of users participating in the on-call rotation. A maximum limit of 100 participants applies. |
+| <a id="mutationoncallrotationupdaterotationlength"></a>`rotationLength` | [`OncallRotationLengthInputType`](#oncallrotationlengthinputtype) | Rotation length of the on-call rotation. |
+| <a id="mutationoncallrotationupdatestartsat"></a>`startsAt` | [`OncallRotationDateInputType`](#oncallrotationdateinputtype) | Start date and time of the on-call rotation, in the timezone of the on-call schedule. |
#### Fields
@@ -3343,7 +3343,7 @@ Input type: `OncallRotationUpdateInput`
| ---- | ---- | ----------- |
| <a id="mutationoncallrotationupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationoncallrotationupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationoncallrotationupdateoncallrotation"></a>`oncallRotation` | [`IncidentManagementOncallRotation`](#incidentmanagementoncallrotation) | The on-call rotation. |
+| <a id="mutationoncallrotationupdateoncallrotation"></a>`oncallRotation` | [`IncidentManagementOncallRotation`](#incidentmanagementoncallrotation) | On-call rotation. |
### `Mutation.oncallScheduleCreate`
@@ -3354,10 +3354,10 @@ Input type: `OncallScheduleCreateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationoncallschedulecreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationoncallschedulecreatedescription"></a>`description` | [`String`](#string) | The description of the on-call schedule. |
-| <a id="mutationoncallschedulecreatename"></a>`name` | [`String!`](#string) | The name of the on-call schedule. |
-| <a id="mutationoncallschedulecreateprojectpath"></a>`projectPath` | [`ID!`](#id) | The project to create the on-call schedule in. |
-| <a id="mutationoncallschedulecreatetimezone"></a>`timezone` | [`String!`](#string) | The timezone of the on-call schedule. |
+| <a id="mutationoncallschedulecreatedescription"></a>`description` | [`String`](#string) | Description of the on-call schedule. |
+| <a id="mutationoncallschedulecreatename"></a>`name` | [`String!`](#string) | Name of the on-call schedule. |
+| <a id="mutationoncallschedulecreateprojectpath"></a>`projectPath` | [`ID!`](#id) | Project to create the on-call schedule in. |
+| <a id="mutationoncallschedulecreatetimezone"></a>`timezone` | [`String!`](#string) | Timezone of the on-call schedule. |
#### Fields
@@ -3365,7 +3365,7 @@ Input type: `OncallScheduleCreateInput`
| ---- | ---- | ----------- |
| <a id="mutationoncallschedulecreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationoncallschedulecreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationoncallschedulecreateoncallschedule"></a>`oncallSchedule` | [`IncidentManagementOncallSchedule`](#incidentmanagementoncallschedule) | The on-call schedule. |
+| <a id="mutationoncallschedulecreateoncallschedule"></a>`oncallSchedule` | [`IncidentManagementOncallSchedule`](#incidentmanagementoncallschedule) | On-call schedule. |
### `Mutation.oncallScheduleDestroy`
@@ -3376,8 +3376,8 @@ Input type: `OncallScheduleDestroyInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationoncallscheduledestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationoncallscheduledestroyiid"></a>`iid` | [`String!`](#string) | The on-call schedule internal ID to remove. |
-| <a id="mutationoncallscheduledestroyprojectpath"></a>`projectPath` | [`ID!`](#id) | The project to remove the on-call schedule from. |
+| <a id="mutationoncallscheduledestroyiid"></a>`iid` | [`String!`](#string) | On-call schedule internal ID to remove. |
+| <a id="mutationoncallscheduledestroyprojectpath"></a>`projectPath` | [`ID!`](#id) | Project to remove the on-call schedule from. |
#### Fields
@@ -3385,7 +3385,7 @@ Input type: `OncallScheduleDestroyInput`
| ---- | ---- | ----------- |
| <a id="mutationoncallscheduledestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationoncallscheduledestroyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationoncallscheduledestroyoncallschedule"></a>`oncallSchedule` | [`IncidentManagementOncallSchedule`](#incidentmanagementoncallschedule) | The on-call schedule. |
+| <a id="mutationoncallscheduledestroyoncallschedule"></a>`oncallSchedule` | [`IncidentManagementOncallSchedule`](#incidentmanagementoncallschedule) | On-call schedule. |
### `Mutation.oncallScheduleUpdate`
@@ -3396,11 +3396,11 @@ Input type: `OncallScheduleUpdateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationoncallscheduleupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationoncallscheduleupdatedescription"></a>`description` | [`String`](#string) | The description of the on-call schedule. |
-| <a id="mutationoncallscheduleupdateiid"></a>`iid` | [`String!`](#string) | The on-call schedule internal ID to update. |
-| <a id="mutationoncallscheduleupdatename"></a>`name` | [`String`](#string) | The name of the on-call schedule. |
-| <a id="mutationoncallscheduleupdateprojectpath"></a>`projectPath` | [`ID!`](#id) | The project to update the on-call schedule in. |
-| <a id="mutationoncallscheduleupdatetimezone"></a>`timezone` | [`String`](#string) | The timezone of the on-call schedule. |
+| <a id="mutationoncallscheduleupdatedescription"></a>`description` | [`String`](#string) | Description of the on-call schedule. |
+| <a id="mutationoncallscheduleupdateiid"></a>`iid` | [`String!`](#string) | On-call schedule internal ID to update. |
+| <a id="mutationoncallscheduleupdatename"></a>`name` | [`String`](#string) | Name of the on-call schedule. |
+| <a id="mutationoncallscheduleupdateprojectpath"></a>`projectPath` | [`ID!`](#id) | Project to update the on-call schedule in. |
+| <a id="mutationoncallscheduleupdatetimezone"></a>`timezone` | [`String`](#string) | Timezone of the on-call schedule. |
#### Fields
@@ -3408,7 +3408,7 @@ Input type: `OncallScheduleUpdateInput`
| ---- | ---- | ----------- |
| <a id="mutationoncallscheduleupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationoncallscheduleupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationoncallscheduleupdateoncallschedule"></a>`oncallSchedule` | [`IncidentManagementOncallSchedule`](#incidentmanagementoncallschedule) | The on-call schedule. |
+| <a id="mutationoncallscheduleupdateoncallschedule"></a>`oncallSchedule` | [`IncidentManagementOncallSchedule`](#incidentmanagementoncallschedule) | On-call schedule. |
### `Mutation.pipelineCancel`
@@ -3578,7 +3578,7 @@ Input type: `PromoteToEpicInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationpromotetoepicclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationpromotetoepicgrouppath"></a>`groupPath` | [`ID`](#id) | The group the promoted epic will belong to. |
+| <a id="mutationpromotetoepicgrouppath"></a>`groupPath` | [`ID`](#id) | Group the promoted epic will belong to. |
| <a id="mutationpromotetoepiciid"></a>`iid` | [`String!`](#string) | IID of the issue to mutate. |
| <a id="mutationpromotetoepicprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the issue to mutate is in. |
@@ -3587,7 +3587,7 @@ Input type: `PromoteToEpicInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationpromotetoepicclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationpromotetoepicepic"></a>`epic` | [`Epic`](#epic) | The epic after issue promotion. |
+| <a id="mutationpromotetoepicepic"></a>`epic` | [`Epic`](#epic) | Epic after issue promotion. |
| <a id="mutationpromotetoepicerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationpromotetoepicissue"></a>`issue` | [`Issue`](#issue) | Issue after mutation. |
@@ -4193,7 +4193,7 @@ Input type: `UpdateEpicInput`
| <a id="mutationupdateepicduedatefixed"></a>`dueDateFixed` | [`String`](#string) | End date of the epic. |
| <a id="mutationupdateepicduedateisfixed"></a>`dueDateIsFixed` | [`Boolean`](#boolean) | Indicates end date should be sourced from due_date_fixed field not the issue milestones. |
| <a id="mutationupdateepicgrouppath"></a>`groupPath` | [`ID!`](#id) | Group the epic to mutate is in. |
-| <a id="mutationupdateepiciid"></a>`iid` | [`ID!`](#id) | The IID of the epic to mutate. |
+| <a id="mutationupdateepiciid"></a>`iid` | [`ID!`](#id) | IID of the epic to mutate. |
| <a id="mutationupdateepicremovelabelids"></a>`removeLabelIds` | [`[ID!]`](#id) | IDs of labels to be removed from the epic. |
| <a id="mutationupdateepicstartdatefixed"></a>`startDateFixed` | [`String`](#string) | Start date of the epic. |
| <a id="mutationupdateepicstartdateisfixed"></a>`startDateIsFixed` | [`Boolean`](#boolean) | Indicates start date should be sourced from start_date_fixed field not the issue milestones. |
@@ -4205,7 +4205,7 @@ Input type: `UpdateEpicInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationupdateepicclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationupdateepicepic"></a>`epic` | [`Epic`](#epic) | The epic after mutation. |
+| <a id="mutationupdateepicepic"></a>`epic` | [`Epic`](#epic) | Epic after mutation. |
| <a id="mutationupdateepicerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.updateEpicBoardList`
@@ -4269,7 +4269,7 @@ Input type: `UpdateIssueInput`
| <a id="mutationupdateissuedescription"></a>`description` | [`String`](#string) | Description of the issue. |
| <a id="mutationupdateissueduedate"></a>`dueDate` | [`ISO8601Date`](#iso8601date) | Due date of the issue. |
| <a id="mutationupdateissueepicid"></a>`epicId` | [`EpicID`](#epicid) | ID of the parent epic. NULL when removing the association. |
-| <a id="mutationupdateissuehealthstatus"></a>`healthStatus` | [`HealthStatus`](#healthstatus) | The desired health status. |
+| <a id="mutationupdateissuehealthstatus"></a>`healthStatus` | [`HealthStatus`](#healthstatus) | Desired health status. |
| <a id="mutationupdateissueiid"></a>`iid` | [`String!`](#string) | IID of the issue to mutate. |
| <a id="mutationupdateissuelabelids"></a>`labelIds` | [`[ID!]`](#id) | IDs of labels to be set. Replaces existing issue labels. |
| <a id="mutationupdateissuelocked"></a>`locked` | [`Boolean`](#boolean) | Indicates discussion is locked on the issue. |
@@ -4279,7 +4279,7 @@ Input type: `UpdateIssueInput`
| <a id="mutationupdateissuestateevent"></a>`stateEvent` | [`IssueStateEvent`](#issuestateevent) | Close or reopen an issue. |
| <a id="mutationupdateissuetitle"></a>`title` | [`String`](#string) | Title of the issue. |
| <a id="mutationupdateissuetype"></a>`type` | [`IssueType`](#issuetype) | Type of the issue. |
-| <a id="mutationupdateissueweight"></a>`weight` | [`Int`](#int) | The weight of the issue. |
+| <a id="mutationupdateissueweight"></a>`weight` | [`Int`](#int) | Weight of the issue. |
#### Fields
@@ -4372,7 +4372,7 @@ Input type: `UpdateRequirementInput`
| ---- | ---- | ----------- |
| <a id="mutationupdaterequirementclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationupdaterequirementdescription"></a>`description` | [`String`](#string) | Description of the requirement. |
-| <a id="mutationupdaterequirementiid"></a>`iid` | [`String!`](#string) | The IID of the requirement to update. |
+| <a id="mutationupdaterequirementiid"></a>`iid` | [`String!`](#string) | IID of the requirement to update. |
| <a id="mutationupdaterequirementlasttestreportstate"></a>`lastTestReportState` | [`TestReportState`](#testreportstate) | Creates a test report for the requirement with the given state. |
| <a id="mutationupdaterequirementprojectpath"></a>`projectPath` | [`ID!`](#id) | Full project path the requirement is associated with. |
| <a id="mutationupdaterequirementstate"></a>`state` | [`RequirementState`](#requirementstate) | State of the requirement. |
@@ -4451,7 +4451,7 @@ Input type: `VulnerabilityConfirmInput`
| ---- | ---- | ----------- |
| <a id="mutationvulnerabilityconfirmclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationvulnerabilityconfirmerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationvulnerabilityconfirmvulnerability"></a>`vulnerability` | [`Vulnerability`](#vulnerability) | The vulnerability after state change. |
+| <a id="mutationvulnerabilityconfirmvulnerability"></a>`vulnerability` | [`Vulnerability`](#vulnerability) | Vulnerability after state change. |
### `Mutation.vulnerabilityCreate`
@@ -4504,7 +4504,7 @@ Input type: `VulnerabilityDismissInput`
| ---- | ---- | ----------- |
| <a id="mutationvulnerabilitydismissclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationvulnerabilitydismisserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationvulnerabilitydismissvulnerability"></a>`vulnerability` | [`Vulnerability`](#vulnerability) | The vulnerability after dismissal. |
+| <a id="mutationvulnerabilitydismissvulnerability"></a>`vulnerability` | [`Vulnerability`](#vulnerability) | Vulnerability after dismissal. |
### `Mutation.vulnerabilityExternalIssueLinkCreate`
@@ -4525,7 +4525,7 @@ Input type: `VulnerabilityExternalIssueLinkCreateInput`
| ---- | ---- | ----------- |
| <a id="mutationvulnerabilityexternalissuelinkcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationvulnerabilityexternalissuelinkcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationvulnerabilityexternalissuelinkcreateexternalissuelink"></a>`externalIssueLink` | [`VulnerabilityExternalIssueLink`](#vulnerabilityexternalissuelink) | The created external issue link. |
+| <a id="mutationvulnerabilityexternalissuelinkcreateexternalissuelink"></a>`externalIssueLink` | [`VulnerabilityExternalIssueLink`](#vulnerabilityexternalissuelink) | Created external issue link. |
### `Mutation.vulnerabilityExternalIssueLinkDestroy`
@@ -4536,7 +4536,7 @@ Input type: `VulnerabilityExternalIssueLinkDestroyInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationvulnerabilityexternalissuelinkdestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationvulnerabilityexternalissuelinkdestroyid"></a>`id` | [`VulnerabilitiesExternalIssueLinkID!`](#vulnerabilitiesexternalissuelinkid) | The global ID of the vulnerability external issue link. |
+| <a id="mutationvulnerabilityexternalissuelinkdestroyid"></a>`id` | [`VulnerabilitiesExternalIssueLinkID!`](#vulnerabilitiesexternalissuelinkid) | Global ID of the vulnerability external issue link. |
#### Fields
@@ -4562,7 +4562,7 @@ Input type: `VulnerabilityResolveInput`
| ---- | ---- | ----------- |
| <a id="mutationvulnerabilityresolveclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationvulnerabilityresolveerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationvulnerabilityresolvevulnerability"></a>`vulnerability` | [`Vulnerability`](#vulnerability) | The vulnerability after state change. |
+| <a id="mutationvulnerabilityresolvevulnerability"></a>`vulnerability` | [`Vulnerability`](#vulnerability) | Vulnerability after state change. |
### `Mutation.vulnerabilityRevertToDetected`
@@ -4581,7 +4581,7 @@ Input type: `VulnerabilityRevertToDetectedInput`
| ---- | ---- | ----------- |
| <a id="mutationvulnerabilityreverttodetectedclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationvulnerabilityreverttodetectederrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationvulnerabilityreverttodetectedvulnerability"></a>`vulnerability` | [`Vulnerability`](#vulnerability) | The vulnerability after revert. |
+| <a id="mutationvulnerabilityreverttodetectedvulnerability"></a>`vulnerability` | [`Vulnerability`](#vulnerability) | Vulnerability after revert. |
## Connections
diff --git a/doc/development/experiment_guide/index.md b/doc/development/experiment_guide/index.md
index e4a97091a81..cf8342db198 100644
--- a/doc/development/experiment_guide/index.md
+++ b/doc/development/experiment_guide/index.md
@@ -8,11 +8,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Experiments can be conducted by any GitLab team, most often the teams from the [Growth Sub-department](https://about.gitlab.com/handbook/engineering/development/growth/). Experiments are not tied to releases because they primarily target GitLab.com.
-Experiments are run as an A/B/n test, and are behind a feature flag to turn the test on or off. Based on the data the experiment generates, the team decides if the experiment had a positive impact and should be made the new default, or rolled back.
+Experiments are run as an A/B/n test, and are behind an [experiment feature flag](../feature_flags/#experiment-type) to turn the test on or off. Based on the data the experiment generates, the team decides if the experiment had a positive impact and should be made the new default, or rolled back.
-## Experiment tracking issue
+## Experiment rollout issue
-Each experiment should have an [Experiment tracking](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&state=opened&label_name[]=growth%20experiment&search=%22Experiment+tracking%22) issue to track the experiment from roll-out through to cleanup/removal. The tracking issue is similar to a feature flag rollout issue, and is also used to track the status of an experiment. Immediately after an experiment is deployed, the due date of the issue should be set (this depends on the experiment but can be up to a few weeks in the future).
+Each experiment should have an [experiment rollout](https://gitlab.com/groups/gitlab-org/-/boards/1352542) issue to track the experiment from rollout through to cleanup and removal.
+The rollout issue is similar to a feature flag rollout issue, and is also used to track the status of an experiment.
+When an experiment is deployed, the due date of the issue should be set (this depends on the experiment but can be up to a few weeks in the future).
After the deadline, the issue needs to be resolved and either:
- It was successful and the experiment becomes the new default.
@@ -38,22 +40,14 @@ addressed.
## Implementing an experiment
-There are currently two options when implementing an experiment.
+[`GLEX`](https://gitlab.com/gitlab-org/gitlab-experiment) - or `Gitlab::Experiment`, the `gitlab-experiment` gem - is the preferred option for implementing an experiment in GitLab.
-One is built into GitLab directly and has been around for a while (this is called
-`Exerimentation Module`), and the other is provided by
-[`gitlab-experiment`](https://gitlab.com/gitlab-org/gitlab-experiment) and is referred
-to as `Gitlab::Experiment` -- GLEX for short.
+For more information, see [Implementing an A/B/n experiment using GLEX](gitlab_experiment.md).
-Both approaches use [experiment](../feature_flags/index.md#experiment-type)
-feature flags. We recommend using GLEX rather than `Experimentation Module` for new experiments.
+There are still some longer running experiments using the [`Exerimentation Module`](experimentation.md).
-- [Implementing an A/B/n experiment using GLEX](gitlab_experiment.md)
-- [Implementing an A/B experiment using `Experimentation Module`](experimentation.md)
-
-Historical Context: `Experimentation Module` was built iteratively with the needs that
-appeared while implementing Growth sub-department experiments, while GLEX was built
-with the findings of the team and an easier to use API.
+Both approaches use [experiment](../feature_flags/index.md#experiment-type) feature flags.
+`GLEX` is the preferred option for new experiments.
### Add new icons and illustrations for experiments
diff --git a/doc/development/internal_api.md b/doc/development/internal_api.md
index c7fc4bed38c..e3fb93c6dbf 100644
--- a/doc/development/internal_api.md
+++ b/doc/development/internal_api.md
@@ -501,6 +501,56 @@ curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" \
"http://localhost:3000/api/v4/internal/kubernetes/modules/cilium_alert"
```
+### Create Starboard vulnerability
+
+Called from the GitLab Kubernetes Agent Server (`kas`) to create a security vulnerability
+from a Starboard vulnerability report. This request is idempotent. Multiple requests with the same data
+create a single vulnerability.
+
+| Attribute | Type | Required | Description |
+|:----------------|:-------|:---------|:------------|
+| `vulnerability` | Hash | yes | Vulnerability data matching the security report schema [`vulnerability` field](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/src/security-report-format.json). |
+| `scanner` | Hash | yes | Scanner data matching the security report schmea [`scanner` field](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/src/security-report-format.json). |
+
+```plaintext
+PUT internal/kubernetes/modules/starboard_vulnerability
+```
+
+Example Request:
+
+```shell
+curl --request PUT --header "Gitlab-Kas-Api-Request: <JWT token>" \
+ --header "Authorization: Bearer <agent token>" --header "Content-Type: application/json" \
+ --url "http://localhost:3000/api/v4/internal/kubernetes/modules/starboard_vulnerability" \
+ --data '{
+ "vulnerability": {
+ "name": "CVE-123-4567 in libc",
+ "severity": "high",
+ "confidence": "unknown",
+ "location": {
+ "kubernetes_resource": {
+ "namespace": "production",
+ "kind": "deployment",
+ "name": "nginx",
+ "container": "nginx"
+ }
+ },
+ "identifiers": [
+ {
+ "type": "cve",
+ "name": "CVE-123-4567",
+ "value": "CVE-123-4567"
+ }
+ ]
+ },
+ "scanner": {
+ "id": "starboard_trivy",
+ "name": "Trivy (via Starboard Operator)",
+ "vendor": "GitLab"
+ }
+}'
+```
+
## Subscriptions
The subscriptions endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`)
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
index 820299a426b..e64583396c0 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -155,10 +155,8 @@ graph RL;
3_1-1["jest (16 minutes)"];
class 3_1-1 criticalPath;
click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0"
- 3_1-2["karma (2 minutes)"];
- click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914200&udv=0"
subgraph "Needs `rspec frontend_fixture/rspec-ee frontend_fixture`";
- 3_1-1 & 3_1-2 --> 2_2-2;
+ 3_1-1 --> 2_2-2;
end
3_2-1["rspec:coverage (5.3 minutes)"];
@@ -268,10 +266,8 @@ graph RL;
3_1-1["jest (16 minutes)"];
class 3_1-1 criticalPath;
click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0"
- 3_1-2["karma (2 minutes)"];
- click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914200&udv=0"
subgraph "Needs `rspec frontend_fixture/rspec-ee frontend_fixture`";
- 3_1-1 & 3_1-2 --> 2_2-2;
+ 3_1-1 --> 2_2-2;
end
3_2-1["rspec:coverage (5.3 minutes)"];
@@ -627,7 +623,6 @@ that is deployed in stage `review`.
the `qa` stage's jobs (for example, Review App performance report).
- `pages`: This stage includes a job that deploys the various reports as
GitLab Pages (for example, [`coverage-ruby`](https://gitlab-org.gitlab.io/gitlab/coverage-ruby/),
- [`coverage-javascript`](https://gitlab-org.gitlab.io/gitlab/coverage-javascript/),
and `webpack-report` (found at `https://gitlab-org.gitlab.io/gitlab/webpack-report/`, but there is
[an issue with the deployment](https://gitlab.com/gitlab-org/gitlab/-/issues/233458)).
- `notify`: This stage includes jobs that notify various failures to Slack.
diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md
index 6b2b941a0c1..b7301260d2a 100644
--- a/doc/development/rake_tasks.md
+++ b/doc/development/rake_tasks.md
@@ -128,7 +128,6 @@ In order to run the test you can use the following commands:
- `bin/rake spec:unit` to run only the unit tests
- `bin/rake spec:integration` to run only the integration tests
- `bin/rake spec:system` to run only the system tests
-- `bin/rake karma` to run the Karma test suite
`bin/rake spec` takes significant time to pass.
Instead of running the full test suite locally, you can save a lot of time by running
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index 3af806d8f57..c70d796dfec 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Frontend testing standards and style guidelines
There are two types of test suites encountered while developing frontend code
-at GitLab. We use Karma with Jasmine and Jest for JavaScript unit and integration testing,
+at GitLab. We use Jest for JavaScript unit and integration testing,
and RSpec feature tests with Capybara for e2e (end-to-end) integration testing.
Unit and feature tests need to be written for all new features.
@@ -28,46 +28,9 @@ If you are looking for a guide on Vue component testing, you can jump right away
We use Jest to write frontend unit and integration tests.
Jest tests can be found in `/spec/frontend` and `/ee/spec/frontend` in EE.
-## Karma test suite
-
-While GitLab has switched over to [Jest](https://jestjs.io), Karma tests still exist in our
-application because some of our specs require a browser and can't be easily migrated to Jest.
-Those specs intend to eventually drop Karma in favor of either Jest or RSpec. You can track this migration
-in the [related epic](https://gitlab.com/groups/gitlab-org/-/epics/4900).
-
-[Karma](http://karma-runner.github.io/) is a test runner which uses
-[Jasmine](https://jasmine.github.io/) as its test framework. Jest also uses Jasmine as foundation,
-that's why it's looking quite similar.
-
-Karma tests live in `spec/javascripts/` and `/ee/spec/javascripts` in EE.
-
-`app/assets/javascripts/behaviors/autosize.js`
-might have a corresponding `spec/javascripts/behaviors/autosize_spec.js` file.
-
-Keep in mind that in a CI environment, these tests are run in a headless
-browser and you don't have access to certain APIs, such as
-[`Notification`](https://developer.mozilla.org/en-US/docs/Web/API/notification),
-which have to be stubbed.
-
-### Differences to Karma
-
-- Jest runs in a Node.js environment, not in a browser. [An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/26982) for running Jest tests in a browser.
-- Because Jest runs in a Node.js environment, it uses [jsdom](https://github.com/jsdom/jsdom) by default. See also its [limitations](#limitations-of-jsdom) below.
-- Jest does not have access to Webpack loaders or aliases.
- The aliases used by Jest are defined in its [own configuration](https://gitlab.com/gitlab-org/gitlab/-/blob/master/jest.config.js).
-- All calls to `setTimeout` and `setInterval` are mocked away. See also [Jest Timer Mocks](https://jestjs.io/docs/timer-mocks).
-- `rewire` is not required because Jest supports mocking modules. See also [Manual Mocks](https://jestjs.io/docs/manual-mocks).
-- No [context object](https://jasmine.github.io/tutorials/your_first_suite#section-The_%3Ccode%3Ethis%3C/code%3E_keyword) is passed to tests in Jest.
- This means sharing `this.something` between `beforeEach()` and `it()` for example does not work.
- Instead you should declare shared variables in the context that they are needed (via `const` / `let`).
-- The following cause tests to fail in Jest:
- - Unmocked requests.
- - Unhandled Promise rejections.
- - Calls to `console.warn`, including warnings from libraries like Vue.
-
### Limitations of jsdom
-As mentioned [above](#differences-to-karma), Jest uses jsdom instead of a browser for running tests.
+Jest uses jsdom instead of a browser for running tests.
This comes with a number of limitations, namely:
- [No scrolling support](https://github.com/jsdom/jsdom/blob/15.1.1/lib/jsdom/browser/Window.js#L623-L625)
@@ -387,8 +350,7 @@ Sometimes we have to test time-sensitive code. For example, recurring events tha
If the application itself is waiting for some time, mock await the waiting. In Jest this is already
[done by default](https://gitlab.com/gitlab-org/gitlab/-/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47)
-(see also [Jest Timer Mocks](https://jestjs.io/docs/timer-mocks)). In Karma you can use the
-[Jasmine mock clock](https://jasmine.github.io/api/2.9/Clock.html).
+(see also [Jest Timer Mocks](https://jestjs.io/docs/timer-mocks)).
```javascript
const doSomethingLater = () => {
@@ -409,20 +371,6 @@ it('does something', () => {
});
```
-**in Karma:**
-
-```javascript
-it('does something', () => {
- jasmine.clock().install();
-
- doSomethingLater();
- jasmine.clock().tick(4000);
-
- expect(something).toBe('done');
- jasmine.clock().uninstall();
-});
-```
-
### Mocking the current location in Jest
NOTE:
@@ -476,8 +424,7 @@ it('passes', () => {
Sometimes a test needs to wait for something to happen in the application before it continues.
Avoid using [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)
-because it makes the reason for waiting unclear and if used within Karma with a time larger than zero it slows down our test suite.
-Instead use one of the following approaches.
+because it makes the reason for waiting unclear. Instead use one of the following approaches.
#### Promises and Ajax calls
@@ -505,19 +452,6 @@ it('waits for an Ajax call', async () => {
});
```
-**in Karma:**
-
-```javascript
-it('waits for an Ajax call', done => {
- askTheServer()
- .then(() => {
- expect(something).toBe('done');
- })
- .then(done)
- .catch(done.fail);
-});
-```
-
If you are not able to register handlers to the `Promise`, for example because it is executed in a synchronous Vue life cycle hook, take a look at the [waitFor](#wait-until-axios-requests-finish) helpers or you can flush all pending `Promise`s:
**in Jest:**
@@ -548,22 +482,6 @@ it('renders something', () => {
});
```
-**in Karma:**
-
-```javascript
-it('renders something', done => {
- wrapper.setProps({ value: 'new value' });
-
- wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.text()).toBe('new value');
- })
- .then(done)
- .catch(done.fail);
-});
-```
-
#### Events
If the application triggers an event that you need to wait for in your test, register an event handler which contains
@@ -776,7 +694,7 @@ TBU
### Stubbing and Mocking
-Jasmine provides stubbing and mocking capabilities. There are some subtle differences in how to use it within Karma and Jest.
+Jasmine provides stubbing and mocking capabilities. There are some subtle differences in how to use it within Jest.
Stubs or spies are often used synonymously. In Jest it's quite easy thanks to the `.spyOn` method.
[Official docs](https://jestjs.io/docs/jest-object#jestspyonobject-methodname)
@@ -835,7 +753,6 @@ For running the frontend tests, you need the following commands:
- `rake frontend:fixtures` (re-)generates [fixtures](#frontend-test-fixtures). Make sure that
fixtures are up-to-date before running tests that require them.
- `yarn jest` runs Jest tests.
-- `yarn karma` runs Karma tests.
### Live testing and focused testing -- Jest
@@ -860,49 +777,36 @@ yarn jest ./path/to/folder/
yarn jest term
```
-### Live testing and focused testing -- Karma
+## Frontend test fixtures
-Karma allows something similar, but it's way more costly.
+Frontend fixtures are files containing responses from backend controllers. These responses can be either HTML
+generated from HAML templates or JSON payloads. Frontend tests that rely on these responses are
+often using fixtures to validate correct integration with the backend code.
-Running Karma with `yarn run karma-start` compiles the JavaScript
-assets and runs a server at `http://localhost:9876/` where it automatically
-runs the tests on any browser which connects to it. You can enter that URL on
-multiple browsers at once to have it run the tests on each in parallel.
+### Use fixtures
-While Karma is running, any changes you make instantly trigger a recompile
-and retest of the **entire test suite**, so you can see instantly if you've broken
-a test with your changes. You can use [Jasmine focused](https://jasmine.github.io/2.5/focused_specs.html) or
-excluded tests (with `fdescribe` or `xdescribe`) to get Karma to run only the
-tests you want while you're working on a specific feature, but make sure to
-remove these directives when you commit your code.
+Jest uses `spec/frontend/__helpers__/fixtures.js` to import fixtures in tests.
-It is also possible to only run Karma on specific folders or files by filtering
-the run tests via the argument `--filter-spec` or short `-f`:
+The following are examples of tests that work for Jest:
-```shell
-# Run all files
-yarn karma-start
-# Run specific spec files
-yarn karma-start --filter-spec profile/account/components/update_username_spec.js
-# Run specific spec folder
-yarn karma-start --filter-spec profile/account/components/
-# Run all specs which path contain vue_shared or vie
-yarn karma-start -f vue_shared -f vue_mr_widget
-```
+```javascript
+it('makes a request', () => {
+ const responseBody = getJSONFixture('some/fixture.json'); // loads spec/frontend/fixtures/some/fixture.json
+ axiosMock.onGet(endpoint).reply(200, responseBody);
-You can also use glob syntax to match files. Remember to put quotes around the
-glob otherwise your shell may split it into multiple arguments:
+ myButton.click();
-```shell
-# Run all specs named `file_spec` within the IDE subdirectory
-yarn karma -f 'spec/javascripts/ide/**/file_spec.js'
-```
+ // ...
+});
-## Frontend test fixtures
+it('uses some HTML element', () => {
+ loadFixtures('some/page.html'); // loads spec/frontend/fixtures/some/page.html and adds it to the DOM
-Frontend fixtures are files containing responses from backend controllers. These responses can be either HTML
-generated from HAML templates or JSON payloads. Frontend tests that rely on these responses are
-often using fixtures to validate correct integration with the backend code.
+ const element = document.getElementById('#my-id');
+
+ // ...
+});
+```
### Generate fixtures
@@ -961,34 +865,6 @@ This will create a new fixture located at
You can import the JSON fixture in a Jest test using the `getJSONFixture` method
[as described below](#use-fixtures).
-### Use fixtures
-
-Jest and Karma test suites import fixtures in different ways:
-
-- The Karma test suite are served by [jasmine-jquery](https://github.com/velesin/jasmine-jquery).
-- Jest use `spec/frontend/__helpers__/fixtures.js`.
-
-The following are examples of tests that work for both Karma and Jest:
-
-```javascript
-it('makes a request', () => {
- const responseBody = getJSONFixture('some/fixture.json'); // loads spec/frontend/fixtures/some/fixture.json
- axiosMock.onGet(endpoint).reply(200, responseBody);
-
- myButton.click();
-
- // ...
-});
-
-it('uses some HTML element', () => {
- loadFixtures('some/page.html'); // loads spec/frontend/fixtures/some/page.html and adds it to the DOM
-
- const element = document.getElementById('#my-id');
-
- // ...
-});
-```
-
## Data-driven tests
Similar to [RSpec's parameterized tests](best_practices.md#table-based--parameterized-tests),
@@ -1139,13 +1015,10 @@ Main information on frontend testing levels can be found in the [Testing Levels
Tests relevant for frontend development can be found at the following places:
-- `spec/javascripts/`, for Karma tests
- `spec/frontend/`, for Jest tests
- `spec/features/`, for RSpec tests
-RSpec runs complete [feature tests](testing_levels.md#frontend-feature-tests), while the Jest and Karma directories contain [frontend unit tests](testing_levels.md#frontend-unit-tests), [frontend component tests](testing_levels.md#frontend-component-tests), and [frontend integration tests](testing_levels.md#frontend-integration-tests).
-
-All tests in `spec/javascripts/` are intended to be migrated to `spec/frontend/` (see also [#52483](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52483)).
+RSpec runs complete [feature tests](testing_levels.md#frontend-feature-tests), while the Jest directories contain [frontend unit tests](testing_levels.md#frontend-unit-tests), [frontend component tests](testing_levels.md#frontend-component-tests), and [frontend integration tests](testing_levels.md#frontend-integration-tests).
Before May 2018, `features/` also contained feature tests run by Spinach. These tests were removed from the codebase in May 2018 ([#23036](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/23036)).
diff --git a/doc/development/testing_guide/index.md b/doc/development/testing_guide/index.md
index 889dc45d6e3..015d8a92a4d 100644
--- a/doc/development/testing_guide/index.md
+++ b/doc/development/testing_guide/index.md
@@ -19,7 +19,7 @@ importance.
GitLab is built on top of [Ruby on Rails](https://rubyonrails.org/), and we're using [RSpec](https://github.com/rspec/rspec-rails#feature-specs) for all
the backend tests, with [Capybara](https://github.com/teamcapybara/capybara) for end-to-end integration testing.
-On the frontend side, we're using [Jest](https://jestjs.io/) and [Karma](http://karma-runner.github.io/)/[Jasmine](https://jasmine.github.io/) for JavaScript unit and
+On the frontend side, we're using [Jest](https://jestjs.io/) for JavaScript unit and
integration testing.
Following are two great articles that everyone should read to understand what
@@ -40,7 +40,7 @@ system tests, parameterized tests etc.
## [Frontend testing standards and style guidelines](frontend_testing.md)
-Everything you should know about how to write good Frontend tests: Karma,
+Everything you should know about how to write good Frontend tests: Jest,
testing promises, stubbing etc.
## [Flaky tests](flaky_tests.md)
diff --git a/doc/development/testing_guide/testing_levels.md b/doc/development/testing_guide/testing_levels.md
index 3a4a28702c7..af3511dca95 100644
--- a/doc/development/testing_guide/testing_levels.md
+++ b/doc/development/testing_guide/testing_levels.md
@@ -31,7 +31,7 @@ records should use stubs/doubles as much as possible.
| Code path | Tests path | Testing engine | Notes |
| --------- | ---------- | -------------- | ----- |
-| `app/assets/javascripts/` | `spec/javascripts/`, `spec/frontend/` | Karma & Jest | More details in the [Frontend Testing guide](frontend_testing.md) section. |
+| `app/assets/javascripts/` | `spec/frontend/` | Jest | More details in the [Frontend Testing guide](frontend_testing.md) section. |
| `app/finders/` | `spec/finders/` | RSpec | |
| `app/graphql/` | `spec/graphql/` | RSpec | |
| `app/helpers/` | `spec/helpers/` | RSpec | |
@@ -233,7 +233,7 @@ They're useful to test permissions, redirections, what view is rendered etc.
| `app/controllers/` | `spec/requests/`, `spec/controllers` | RSpec | Request specs are preferred over legacy controller specs. |
| `app/mailers/` | `spec/mailers/` | RSpec | |
| `lib/api/` | `spec/requests/api/` | RSpec | |
-| `app/assets/javascripts/` | `spec/javascripts/`, `spec/frontend/` | Karma & Jest | [More details below](#frontend-integration-tests) |
+| `app/assets/javascripts/` | `spec/frontend/` | Jest | [More details below](#frontend-integration-tests) |
### Frontend integration tests
@@ -322,13 +322,6 @@ controller.instance_variable_set(:@user, user)
and use methods [deprecated in Rails 5](https://gitlab.com/gitlab-org/gitlab/-/issues/16260).
-### About Karma
-
-Karma is both in the Unit tests and the Integration tests category. Karma provides an environment to
-run JavaScript tests, so you can either run unit tests (e.g. test a single
-JavaScript method), or integration tests (e.g. test a component that is composed
-of multiple components).
-
## White-box tests at the system level (formerly known as System / Feature tests)
Formal definitions:
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index eec67904476..73a9abdfbd9 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -47,8 +47,6 @@ Kubernetes version to any supported version at any time:
- 1.19 (support ends on February 22, 2022)
- 1.18 (support ends on November 22, 2021)
- 1.17 (support ends on September 22, 2021)
-- 1.16 (support ends on July 22, 2021)
-- 1.15 (support ends on May 22, 2021)
Some GitLab features may support versions outside the range provided here.
diff --git a/doc/user/project/pages/redirects.md b/doc/user/project/pages/redirects.md
index 8ed6f214605..3deea92f56e 100644
--- a/doc/user/project/pages/redirects.md
+++ b/doc/user/project/pages/redirects.md
@@ -9,62 +9,58 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/24) in GitLab Pages 1.25.0 and GitLab 13.4 behind a feature flag, disabled by default.
> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/367) in GitLab 13.5.
-WARNING:
-This feature might not be available to you. Check the **version history** note above for details.
-
In GitLab Pages, you can configure rules to forward one URL to another using
[Netlify style](https://docs.netlify.com/routing/redirects/#syntax-for-the-redirects-file)
HTTP redirects.
-## Supported features
-
-GitLab Pages only supports the
-[`_redirects` plain text file syntax](https://docs.netlify.com/routing/redirects/#syntax-for-the-redirects-file),
-and `.toml` files are not supported.
-
-Redirects are only supported at a basic level. GitLab Pages doesn't support all
-[special options offered by Netlify](https://docs.netlify.com/routing/redirects/redirect-options/).
-
-Note that supported paths must start with a forward slash `/`.
+Not all
+[special options offered by Netlify](https://docs.netlify.com/routing/redirects/redirect-options/)
+are supported.
| Feature | Supported | Example |
| ------- | --------- | ------- |
-| Redirects (`301`, `302`) | **{check-circle}** Yes | `/wardrobe.html /narnia.html 302`
-| Rewrites (other status codes) | **{dotted-circle}** No | `/en/* /en/404.html 404` |
-| [Splats](https://docs.netlify.com/routing/redirects/redirect-options/#splats) | **{dotted-circle}** No | `/news/* /blog/:splat` |
-| Placeholders | **{dotted-circle}** No | `/news/:year/:month/:date/:slug /blog/:year/:month/:date/:slug` |
+| [Redirects (`301`, `302`)](#redirects) | **{check-circle}** Yes | `/wardrobe.html /narnia.html 302`
+| [Rewrites (`200`)](#rewrites) | **{check-circle}** Yes | `/* / 200` |
+| [Splats](#splats) | **{check-circle}** Yes | `/news/* /blog/:splat` |
+| [Placeholders](#placeholders) | **{check-circle}** Yes | `/news/:year/:month/:date /blog-:year-:month-:date.html` |
+| Rewrites (other than `200`) | **{dotted-circle}** No | `/en/* /en/404.html 404` |
| Query parameters | **{dotted-circle}** No | `/store id=:id /blog/:id 301` |
| Force ([shadowing](https://docs.netlify.com/routing/redirects/rewrites-proxies/#shadowing)) | **{dotted-circle}** No | `/app/ /app/index.html 200!` |
| Domain-level redirects | **{dotted-circle}** No | `http://blog.example.com/* https://www.example.com/blog/:splat 301` |
| Redirect by country or language | **{dotted-circle}** No | `/ /anz 302 Country=au,nz` |
| Redirect by role | **{dotted-circle}** No | `/admin/* 200! Role=admin` |
+NOTE:
+The [matching behavior test cases](https://gitlab.com/gitlab-org/gitlab-pages/-/blob/master/internal/redirects/matching_test.go)
+are a good resource for understanding how GitLab implements rule matching in
+detail. Community contributions are welcome for any edge cases that aren't included in
+this test suite!
+
## Create redirects
-To create redirects,
-create a configuration file named `_redirects` in the `public/` directory of your
-GitLab Pages site.
+To create redirects, create a configuration file named `_redirects` in the
+`public/` directory of your GitLab Pages site.
-If your GitLab Pages site uses the default domain name (such as
-`namespace.gitlab.io/projectname`) you must prefix every rule with the project name:
+Note that:
-```plaintext
-/projectname/redirect-portal.html /projectname/magic-land.html 301
-/projectname/cake-portal.html /projectname/still-alive.html 302
-/projectname/wardrobe.html /projectname/narnia.html 302
-/projectname/pit.html /projectname/spikes.html 302
-```
+- All paths must start with a forward slash `/`.
+- A default status code of `301` is applied if no [status code](#http-status-codes) is provided.
+- The `_redirects` file has a file size limit of 64KB and a maximum of 1,000 rules per project.
+ Only the first 1,000 rules are processed.
+- If your GitLab Pages site uses the default domain name (such as
+ `namespace.gitlab.io/projectname`) you must prefix every rule with the project name:
-If your GitLab Pages site uses [custom domains](custom_domains_ssl_tls_certification/index.md),
-no project name prefix is needed. For example, if your custom domain is `example.com`,
-your `_redirect` file would look like:
+ ```plaintext
+ /projectname/wardrobe.html /projectname/narnia.html 302
+ ```
-```plaintext
-/redirect-portal.html /magic-land.html 301
-/cake-portal.html /still-alive.html 302
-/wardrobe.html /narnia.html 302
-/pit.html /spikes.html 302
-```
+- If your GitLab Pages site uses [custom domains](custom_domains_ssl_tls_certification/index.md),
+ no project name prefix is needed. For example, if your custom domain is `example.com`,
+ your `_redirects` file would look like:
+
+ ```plaintext
+ /wardrobe.html /narnia.html 302
+ ```
## Files override redirects
@@ -81,6 +77,132 @@ GitLab doesn't support Netlify's
[force option](https://docs.netlify.com/routing/redirects/rewrites-proxies/#shadowing)
to change this behavior.
+## HTTP status codes
+
+A default status code of `301` is applied if no status code is provided, but
+you can explicitly set your own. The following HTTP codes are supported:
+
+- **301**: Permanent redirect.
+- **302**: Temporary redirect.
+- **200**: Standard response for successful HTTP requests. Pages
+ serves the content in the `to` rule if it exists, without changing the URL in
+ the address bar.
+
+## Redirects
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/458) in GitLab 14.3.
+> - Enabled on GitLab.com.
+> - Enabled by default in self-managed GitLab behind the [`FF_ENABLE_REDIRECTS` feature flag](#feature-flag-for-redirects).
+
+To create a redirect, add a rule that includes a `from` path, a `to` path,
+and an [HTTP status code](#http-status-codes):
+
+```plaintext
+# 301 permanent redirect
+/old/file.html /new/file.html 301
+
+# 302 temporary redirect
+/old/another_file.html /new/another_file.html 302
+```
+
+## Rewrites
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/458) in GitLab 14.3.
+> - Enabled on GitLab.com.
+> - Disabled by default in self-managed GitLab behind the [`FF_ENABLE_PLACEHOLDERS` feature flag](#feature-flag-for-rewrites).
+
+Provide a status code of `200` to serve the content of the `to` path when the
+request matches the `from`:
+
+```plaintext
+/old/file.html /new/file.html 200
+```
+
+This status code can be used in combination with [splat rules](#splats) to dynamically
+rewrite the URL.
+
+## Splats
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/458) in GitLab 14.3.
+
+A rule with an asterisk (`*`) in its `from` path, known as a splat, matches
+anything at the start, middle, or end of the requested path. This example
+matches anything after `/old/` and rewrites it to `/new/file.html`:
+
+```plaintext
+/old/* /new/file.html 200
+```
+
+### Splat placeholders
+
+The content matched by a `*` in a rule's `from` path can be injected into the
+`to` path using the `:splat` placeholder:
+
+```plaintext
+/old/* /new/:splat 200
+```
+
+In this example, a request to `/old/file.html` serves the contents of `/new/file.html`
+with a `200` status code.
+
+If a rule's `from` path includes multiple splats, the value of the first splat
+match replaces any `:splat`s in the `to` path.
+
+### Splat matching behavior
+
+Splats are "greedy" and match as many characters as possible:
+
+```plaintext
+/old/*/file /new/:splat/file 301
+```
+
+In this example, the rule redirects `/old/a/b/c/file` to `/new/a/b/c/file`.
+
+Splats also match empty strings, so the previous rule redirects
+`/old/file` to `/new/file`.
+
+### Rewrite all requests to a root `index.html`
+
+Single page applications (SPAs) often perform their own routing using
+client-side routes. For these applications, it's important that _all_ requests
+are rewritten to the root `index.html` so that the routing logic can be handled
+by the JavaScript application. You can do this with a `_redirects`
+rule like:
+
+```plaintext
+/* /index.html 200
+```
+
+## Placeholders
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/458) in GitLab 14.3.
+
+Use placeholders in rules to match portions of the requested URL and use these
+matches when rewriting or redirecting to a new URL.
+
+A placehold is formatted as a `:` character followed by a string of letters
+(`[a-zA-Z]+`) in both the `from` and `to` paths:
+
+```plaintext
+/news/:year/:month/:date/:slug /blog/:year-:month-:date-:slug 200
+```
+
+This rule instructs Pages to respond to a request for `/news/2021/08/12/file.html` by
+serving the content of `/blog/2021-08-12-file.html` with a `200`.
+
+### Placeholder matching behavior
+
+Compared to [splats](#splats), placeholders are more limited in how much content
+they match. Placeholders match text between forward slashes
+(`/`), so use placeholders to match single path segments.
+
+In addition, placeholders do not match empty strings. A rule like the following
+would **not** match a request URL like `/old/file`:
+
+```plaintext
+/old/:path /new/:path
+```
+
## Debug redirect rules
If a redirect isn't working as expected, or you want to check your redirect syntax, visit
@@ -103,8 +225,49 @@ rule 10: valid
rule 11: valid
```
-## Disable redirects
+## Differences from Netlify's implementation
+
+Most supported `_redirects` rules behave the same in both GitLab and Netlify.
+However, there are some minor differences:
+
+- **All rule URLs must begin with a slash:**
+
+ Netlify does not require URLs to begin with a forward slash:
+
+ ```plaintext
+ # Valid in Netlify, invalid in GitLab
+ */path /new/path 200
+ ```
+
+ GitLab validates that all URLs begin with a forward slash. A valid
+ equivalent of the previous example:
+
+ ```plaintext
+ # Valid in both Netlify and GitLab
+ /old/path /new/path 200
+ ```
+- **All placeholder values are populated:**
+
+ Netlify only populates placeholder values that appear in the `to` path:
+
+ ```plaintext
+ /old /new/:placeholder
+ ```
+
+ Given a request to `/old`:
+
+ - Netlify redirects to `/new/:placeholder` (with a
+ literal `:placeholder`).
+ - GitLab redirects to `/new/`.
+
+## Features behind feature flags
+
+Some Pages features are behind feature flags.
+
+### Feature flag for redirects
+
+FLAG:
Redirects in GitLab Pages is under development, and is deployed behind a feature flag
that is **enabled by default**.
@@ -126,3 +289,28 @@ For [source installations](../../../administration/pages/source.md), define the
export FF_ENABLE_REDIRECTS="false"
/path/to/pages/bin/gitlab-pages -config gitlab-pages.conf
```
+
+### Feature flag for rewrites
+
+FLAG:
+Rewrites in GitLab Pages is under development, and is deployed behind a feature flag
+that is **disabled by default**.
+
+To enable rewrites, for [Omnibus installations](../../../administration/pages/index.md), define the
+`FF_ENABLE_PLACEHOLDERS` environment variable in the
+[global settings](../../../administration/pages/index.md#global-settings).
+Add the following line to `/etc/gitlab/gitlab.rb` and
+[reconfigure the instance](../../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure):
+
+```ruby
+gitlab_pages['env']['FF_ENABLE_PLACEHOLDERS'] = 'true'
+```
+
+For [source installations](../../../administration/pages/source.md), define the
+`FF_ENABLE_PLACEHOLDERS` environment variable, then
+[restart GitLab](../../../administration/restart_gitlab.md#installations-from-source):
+
+```shell
+export FF_ENABLE_PLACEHOLDERS="true"
+/path/to/pages/bin/gitlab-pages -config gitlab-pages.conf
+```
diff --git a/doc/user/project/repository/repository_mirroring.md b/doc/user/project/repository/repository_mirroring.md
index 76eae58b431..6e5fbdd140a 100644
--- a/doc/user/project/repository/repository_mirroring.md
+++ b/doc/user/project/repository/repository_mirroring.md
@@ -223,13 +223,15 @@ If a repository you're interested in is located on a different server, and you w
to browse its content and its activity using the GitLab interface, you can configure
mirror pulling:
-1. If you [configured two-factor authentication (2FA)](https://docs.github.com/en/github/authenticating-to-github/securing-your-account-with-two-factor-authentication-2fa)
- for GitHub, create a [personal access token for GitHub](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token)
- with the `read_repository` scope. If 2FA is enabled, this personal access
+1. If your remote repository is on GitHub and you have
+ [two-factor authentication (2FA) configured](https://docs.github.com/en/github/authenticating-to-github/securing-your-account-with-two-factor-authentication-2fa),
+ create a [personal access token for GitHub](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token).
+ with the `repo` scope. If 2FA is enabled, this personal access
token serves as your GitHub password.
1. In your project, go to **Settings > Repository**, and then expand the
**Mirroring repositories** section.
-1. In the **Git repository URL** field, enter a repository URL.
+1. In the **Git repository URL** field, enter a repository URL. Include the username
+ in the URL if required: `https://MYUSERNAME@github.com/group/PROJECTNAME.git`
1. In the **Mirror direction** dropdown, select **Pull**.
1. In the **Authentication method** dropdown, select your authentication method.
1. Select from the following checkboxes, if needed:
diff --git a/jest.config.js b/jest.config.js
index cfc8e254791..4d9e19abbaf 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -3,15 +3,3 @@ const baseConfig = require('./jest.config.base');
module.exports = {
...baseConfig('spec/frontend'),
};
-
-const karmaTestFile = process.argv.find((arg) => arg.includes('spec/javascripts/'));
-if (karmaTestFile) {
- console.error(`
-Files in spec/javascripts/ and ee/spec/javascripts need to be run with Karma.
-Please use the following command instead:
-
-yarn karma -f ${karmaTestFile}
-
-`);
- process.exit(1);
-}
diff --git a/lib/backup/pages.rb b/lib/backup/pages.rb
index ae293073ba2..393cf4108a1 100644
--- a/lib/backup/pages.rb
+++ b/lib/backup/pages.rb
@@ -2,12 +2,16 @@
module Backup
class Pages < Backup::Files
+ # pages used to deploy tmp files to this path
+ # if some of these files are still there, we don't need them in the backup
+ LEGACY_PAGES_TMP_PATH = '@pages.tmp'
+
attr_reader :progress
def initialize(progress)
@progress = progress
- super('pages', Gitlab.config.pages.path, excludes: [::Projects::UpdatePagesService::TMP_EXTRACT_PATH])
+ super('pages', Gitlab.config.pages.path, excludes: [LEGACY_PAGES_TMP_PATH])
end
end
end
diff --git a/lib/gitlab/background_migration/backfill_projects_with_coverage.rb b/lib/gitlab/background_migration/backfill_projects_with_coverage.rb
new file mode 100644
index 00000000000..ca262c0bd59
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_projects_with_coverage.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Backfill project_ci_feature_usages for a range of projects with coverage
+ class BackfillProjectsWithCoverage
+ class ProjectCiFeatureUsage < ActiveRecord::Base # rubocop:disable Style/Documentation
+ self.table_name = 'project_ci_feature_usages'
+ end
+
+ COVERAGE_ENUM_VALUE = 1
+ INSERT_DELAY_SECONDS = 0.1
+
+ def perform(start_id, end_id, sub_batch_size)
+ report_results = ActiveRecord::Base.connection.execute <<~SQL
+ SELECT DISTINCT project_id, default_branch
+ FROM ci_daily_build_group_report_results
+ WHERE id BETWEEN #{start_id} AND #{end_id}
+ SQL
+
+ report_results.to_a.in_groups_of(sub_batch_size, false) do |batch|
+ ProjectCiFeatureUsage.insert_all(build_values(batch))
+
+ sleep INSERT_DELAY_SECONDS
+ end
+ end
+
+ private
+
+ def build_values(batch)
+ batch.map do |data|
+ {
+ project_id: data['project_id'],
+ feature: COVERAGE_ENUM_VALUE,
+ default_branch: data['default_branch']
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/load_balancing.rb b/lib/gitlab/database/load_balancing.rb
index c967072e422..65c35b5aaf2 100644
--- a/lib/gitlab/database/load_balancing.rb
+++ b/lib/gitlab/database/load_balancing.rb
@@ -108,13 +108,14 @@ module Gitlab
end
# Configures proxying of requests.
- def self.configure_proxy(proxy = ConnectionProxy.new(hosts))
- ActiveRecord::Base.load_balancing_proxy = proxy
+ def self.configure_proxy
+ lb = LoadBalancer.new(hosts, primary_only: !enable?)
+ ActiveRecord::Base.load_balancing_proxy = ConnectionProxy.new(lb)
# Populate service discovery immediately if it is configured
if service_discovery_enabled?
ServiceDiscovery
- .new(proxy.load_balancer, **service_discovery_configuration)
+ .new(lb, **service_discovery_configuration)
.perform_service_discovery
end
end
diff --git a/lib/gitlab/database/load_balancing/connection_proxy.rb b/lib/gitlab/database/load_balancing/connection_proxy.rb
index 938f4951532..1be63da8896 100644
--- a/lib/gitlab/database/load_balancing/connection_proxy.rb
+++ b/lib/gitlab/database/load_balancing/connection_proxy.rb
@@ -34,15 +34,15 @@ module Gitlab
).freeze
# hosts - The hosts to use for load balancing.
- def initialize(hosts = [])
- @load_balancer = LoadBalancer.new(hosts)
+ def initialize(load_balancer)
+ @load_balancer = load_balancer
end
def select_all(arel, name = nil, binds = [], preparable: nil)
if arel.respond_to?(:locked) && arel.locked
# SELECT ... FOR UPDATE queries should be sent to the primary.
- write_using_load_balancer(:select_all, arel, name, binds,
- sticky: true)
+ current_session.write!
+ write_using_load_balancer(:select_all, arel, name, binds)
else
read_using_load_balancer(:select_all, arel, name, binds)
end
@@ -56,7 +56,8 @@ module Gitlab
STICKY_WRITES.each do |name|
define_method(name) do |*args, **kwargs, &block|
- write_using_load_balancer(name, *args, sticky: true, **kwargs, &block)
+ current_session.write!
+ write_using_load_balancer(name, *args, **kwargs, &block)
end
end
@@ -65,13 +66,20 @@ module Gitlab
track_read_only_transaction!
read_using_load_balancer(:transaction, *args, **kwargs, &block)
else
- write_using_load_balancer(:transaction, *args, sticky: true, **kwargs, &block)
+ current_session.write!
+ write_using_load_balancer(:transaction, *args, **kwargs, &block)
end
ensure
untrack_read_only_transaction!
end
+ def respond_to_missing?(name, include_private = false)
+ @load_balancer.read_write do |connection|
+ connection.respond_to?(name, include_private)
+ end
+ end
+
# Delegates all unknown messages to a read-write connection.
def method_missing(...)
if current_session.fallback_to_replicas_for_ambiguous_queries?
@@ -102,18 +110,13 @@ module Gitlab
# name - The name of the method to call on a connection object.
# sticky - If set to true the session will stick to the master after
# the write.
- def write_using_load_balancer(name, *args, sticky: false, **kwargs, &block)
+ def write_using_load_balancer(...)
if read_only_transaction?
raise WriteInsideReadOnlyTransactionError, 'A write query is performed inside a read-only transaction'
end
@load_balancer.read_write do |connection|
- # Sticking has to be enabled before calling the method. Not doing so
- # could lead to methods called in a block still being performed on a
- # secondary instead of on a primary (when necessary).
- current_session.write! if sticky
-
- connection.send(name, *args, **kwargs, &block)
+ connection.send(...)
end
end
diff --git a/lib/gitlab/database/load_balancing/load_balancer.rb b/lib/gitlab/database/load_balancing/load_balancer.rb
index 73d6a4fbb48..cdaeebde4df 100644
--- a/lib/gitlab/database/load_balancing/load_balancer.rb
+++ b/lib/gitlab/database/load_balancing/load_balancer.rb
@@ -15,9 +15,18 @@ module Gitlab
attr_reader :host_list
# hosts - The hostnames/addresses of the additional databases.
- def initialize(hosts = [], model = ActiveRecord::Base)
+ # model - The ActiveRecord base model the load balancer is enabled for.
+ # primary_only - If set, the replicas are ignored and the primary is
+ # always used.
+ def initialize(hosts = [], model = ActiveRecord::Base, primary_only: false)
+ @primary_only = primary_only
@model = model
- @host_list = HostList.new(hosts.map { |addr| Host.new(addr, self) })
+ @host_list =
+ if primary_only
+ HostList.new([PrimaryHost.new(self)])
+ else
+ HostList.new(hosts.map { |addr| Host.new(addr, self) })
+ end
end
def disconnect!(timeout: 120)
@@ -217,8 +226,6 @@ module Gitlab
.establish_connection(replica_db_config)
end
- private
-
# ActiveRecord::ConnectionAdapters::ConnectionHandler handles fetching,
# and caching for connections pools for each "connection", so we
# leverage that.
@@ -230,13 +237,15 @@ module Gitlab
)
end
+ private
+
def ensure_caching!
host.enable_query_cache! unless host.query_cache_enabled
end
def request_cache
base = RequestStore[:gitlab_load_balancer] ||= {}
- base[pool] ||= {}
+ base[self] ||= {}
end
end
end
diff --git a/lib/gitlab/database/load_balancing/primary_host.rb b/lib/gitlab/database/load_balancing/primary_host.rb
new file mode 100644
index 00000000000..795fa7c3909
--- /dev/null
+++ b/lib/gitlab/database/load_balancing/primary_host.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LoadBalancing
+ # A host that wraps the primary database connection.
+ #
+ # This class is used to always enable load balancing as if replicas exist,
+ # without the need for extra database connections. This ensures that code
+ # using the load balancer doesn't have to handle the case where load
+ # balancing is enabled, but no replicas have been configured (= the
+ # default case).
+ class PrimaryHost
+ def initialize(load_balancer)
+ @load_balancer = load_balancer
+ end
+
+ def release_connection
+ @load_balancer.release_primary_connection
+ end
+
+ def enable_query_cache!
+ # This could mess up the primary connection, so we make this a no-op
+ nil
+ end
+
+ def disable_query_cache!
+ # This could mess up the primary connection, so we make this a no-op
+ nil
+ end
+
+ def query_cache_enabled
+ @load_balancer.pool.query_cache_enabled
+ end
+
+ def connection
+ @load_balancer.pool.connection
+ end
+
+ def disconnect!(timeout: 120)
+ nil
+ end
+
+ def offline!
+ nil
+ end
+
+ def online?
+ true
+ end
+
+ def primary_write_location
+ @load_balancer.primary_write_location
+ ensure
+ @load_balancer.release_primary_connection
+ end
+
+ def database_replica_location
+ row = query_and_release(<<-SQL.squish)
+ SELECT pg_last_wal_replay_lsn()::text AS location
+ SQL
+
+ row['location'] if row.any?
+ rescue *Host::CONNECTION_ERRORS
+ nil
+ end
+
+ def caught_up?(_location)
+ true
+ end
+
+ def query_and_release(sql)
+ connection.select_all(sql).first || {}
+ rescue StandardError
+ {}
+ ensure
+ release_connection
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/instrumentation/redis_interceptor.rb b/lib/gitlab/instrumentation/redis_interceptor.rb
index 0f21a16793d..ba25e54ac9f 100644
--- a/lib/gitlab/instrumentation/redis_interceptor.rb
+++ b/lib/gitlab/instrumentation/redis_interceptor.rb
@@ -41,7 +41,10 @@ module Gitlab
instrumentation_class.add_call_details(duration, args)
end
- if duration > DURATION_ERROR_THRESHOLD && Feature.enabled?(:report_on_long_redis_durations, default_enabled: :yaml)
+ if duration > DURATION_ERROR_THRESHOLD &&
+ instrumentation_class == ::Gitlab::Instrumentation::Redis::SharedState &&
+ Feature.enabled?(:report_on_long_redis_durations, default_enabled: :yaml)
+
Gitlab::ErrorTracking.track_exception(MysteryRedisDurationError.new(caller),
command: command_from_args(args),
duration: duration,
diff --git a/lib/tasks/karma.rake b/lib/tasks/karma.rake
deleted file mode 100644
index fa3f8805159..00000000000
--- a/lib/tasks/karma.rake
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-unless Rails.env.production?
- namespace :karma do
- # alias exists for legacy reasons
- desc 'GitLab | Karma | Generate fixtures for JavaScript tests'
- task fixtures: ['frontend:fixtures']
-
- desc 'GitLab | Karma | Run JavaScript tests'
- task tests: ['yarn:check'] do
- sh "yarn run karma" do |ok, res|
- abort('rake karma:tests failed') unless ok
- end
- end
- end
-
- desc 'GitLab | Karma | Shortcut for karma:fixtures and karma:tests'
- task karma: ['karma:fixtures', 'karma:tests']
-end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 4fc2f939c97..ce956af6199 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -8505,6 +8505,9 @@ msgstr ""
msgid "Configure settings for Advanced Search with Elasticsearch."
msgstr ""
+msgid "Configure specific limits for Files API requests that supersede the general user and IP rate limits."
+msgstr ""
+
msgid "Configure specific limits for Git LFS requests that supersede the general user and IP rate limits."
msgstr ""
@@ -14305,6 +14308,9 @@ msgstr ""
msgid "Files"
msgstr ""
+msgid "Files API Rate Limits"
+msgstr ""
+
msgid "Files breadcrumb"
msgstr ""
diff --git a/package.json b/package.json
index a4216fcad01..5fb256b96e4 100644
--- a/package.json
+++ b/package.json
@@ -15,10 +15,6 @@
"jest-debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
"jest:integration": "jest --config jest.config.integration.js",
"jsdoc": "jsdoc -c config/jsdocs.config.js",
- "prekarma": "yarn check-dependencies",
- "karma": "BABEL_ENV=${BABEL_ENV:=karma} karma start --single-run true config/karma.config.js",
- "karma-coverage": "BABEL_ENV=coverage karma start --single-run true config/karma.config.js",
- "karma-start": "BABEL_ENV=karma karma start config/karma.config.js",
"lint:eslint": "yarn run internal:eslint",
"lint:eslint:fix": "yarn run internal:eslint --fix",
"lint:eslint:all": "yarn run internal:eslint .",
@@ -162,7 +158,7 @@
"portal-vue": "^2.1.7",
"prismjs": "^1.21.0",
"prosemirror-inputrules": "^1.1.3",
- "prosemirror-markdown": "^1.5.1",
+ "prosemirror-markdown": "^1.5.2",
"prosemirror-model": "^1.14.3",
"prosemirror-state": "^1.3.4",
"prosemirror-tables": "^1.1.1",
@@ -242,14 +238,6 @@
"jest-util": "^26.5.2",
"jsdoc": "^3.5.5",
"jsdoc-vue": "^1.0.0",
- "karma": "^4.2.0",
- "karma-chrome-launcher": "^3.0.0",
- "karma-coverage-istanbul-reporter": "^2.1.0",
- "karma-jasmine": "^1.1.2",
- "karma-junit-reporter": "^1.2.0",
- "karma-mocha-reporter": "^2.2.5",
- "karma-sourcemap-loader": "^0.3.7",
- "karma-webpack": "^4.0.2",
"markdownlint-cli": "0.26.0",
"md5": "^2.2.1",
"miragejs": "^0.1.40",
diff --git a/rubocop/cop/migration/prevent_index_creation.rb b/rubocop/cop/migration/prevent_index_creation.rb
index 1486607acbe..aeeec36ecf0 100644
--- a/rubocop/cop/migration/prevent_index_creation.rb
+++ b/rubocop/cop/migration/prevent_index_creation.rb
@@ -12,16 +12,29 @@ module RuboCop
MSG = "Adding new index to #{FORBIDDEN_TABLES.join(", ")} is forbidden, see https://gitlab.com/gitlab-org/gitlab/-/issues/332886"
+ def on_new_investigation
+ super
+ @forbidden_tables_used = false
+ end
+
def_node_matcher :add_index?, <<~PATTERN
- (send nil? :add_index (sym #forbidden_tables?) ...)
+ (send nil? :add_index ({sym|str} #forbidden_tables?) ...)
PATTERN
def_node_matcher :add_concurrent_index?, <<~PATTERN
- (send nil? :add_concurrent_index (sym #forbidden_tables?) ...)
+ (send nil? :add_concurrent_index ({sym|str} #forbidden_tables?) ...)
PATTERN
- def forbidden_tables?(node)
- FORBIDDEN_TABLES.include?(node)
+ def_node_matcher :forbidden_constant_defined?, <<~PATTERN
+ (casgn nil? _ ({sym|str} #forbidden_tables?))
+ PATTERN
+
+ def_node_matcher :add_concurrent_index_with_constant?, <<~PATTERN
+ (send nil? :add_concurrent_index (const nil? _) ...)
+ PATTERN
+
+ def on_casgn(node)
+ @forbidden_tables_used = !!forbidden_constant_defined?(node)
end
def on_def(node)
@@ -32,8 +45,18 @@ module RuboCop
end
end
+ private
+
+ def forbidden_tables?(node)
+ FORBIDDEN_TABLES.include?(node.to_sym)
+ end
+
def offense?(node)
- add_index?(node) || add_concurrent_index?(node)
+ add_index?(node) || add_concurrent_index?(node) || any_constant_used_with_forbidden_tables?(node)
+ end
+
+ def any_constant_used_with_forbidden_tables?(node)
+ add_concurrent_index_with_constant?(node) && @forbidden_tables_used
end
end
end
diff --git a/scripts/frontend/check_no_partial_karma_jest.sh b/scripts/frontend/check_no_partial_karma_jest.sh
deleted file mode 100755
index c5fffa5900b..00000000000
--- a/scripts/frontend/check_no_partial_karma_jest.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env bash
-
-karma_directory=spec/javascripts
-
-if [ -d ee ]; then
- karma_directory="$karma_directory ee/$karma_directory"
-fi
-
-karma_files=$(find $karma_directory -type f -name '*_spec.js' -not -path '*/helpers/*')
-violations=""
-
-for karma_file in $karma_files; do
- jest_file=${karma_file/spec\/javascripts/"spec/frontend"}
-
- if [ -f $jest_file ]; then
- violations="$violations $jest_file"
- fi
-done
-
-if [[ -z "$violations" ]]; then
- echo "All good!"
- exit 0
-else
- echo "Danger! The following Jest specs have corresponding files in the Karma spec directory (i.e. spec/javascripts):"
- echo ""
- echo "------------------------------"
- for file in $violations; do
- echo $file
- done
- echo "------------------------------"
- echo ""
- echo "For each of these files, please either:"
- echo ""
- echo "1. Fully migrate the file to Jest and remove the corresponding Karma file."
- echo "2. Remove the Jest file for now, make any relevant changes in the corresponding Karma file, and handle the migration to Jest in a separate MR."
- echo ""
- echo "Why is this a problem?"
- echo ""
- echo "- It's nice to have a single source of truth for the unit tests of a subject."
- echo "- This will cause conflicts if the remaining Karma spec is migrated using our automated tool."
- echo " https://gitlab.com/gitlab-org/frontend/playground/migrate-karma-to-jest"
- echo ""
- exit 1
-fi
diff --git a/scripts/frontend/file_test_coverage.js b/scripts/frontend/file_test_coverage.js
index 04a9035fce2..3ad92a5abbe 100755
--- a/scripts/frontend/file_test_coverage.js
+++ b/scripts/frontend/file_test_coverage.js
@@ -14,7 +14,7 @@ const fs = require('fs');
const path = require('path');
const sourceDirectories = ['app/assets/javascripts'];
-const testDirectories = ['spec/javascripts', 'spec/frontend'];
+const testDirectories = ['spec/frontend'];
if (fs.existsSync('ee')) {
sourceDirectories.forEach((dir) => {
diff --git a/scripts/static-analysis b/scripts/static-analysis
index 0576d8cdca9..6ad7c0b19c3 100755
--- a/scripts/static-analysis
+++ b/scripts/static-analysis
@@ -51,8 +51,7 @@ class StaticAnalysis
Task.new(%w[scripts/lint-conflicts.sh], 1),
Task.new(%w[yarn run block-dependencies], 1),
Task.new(%w[scripts/lint-rugged], 1),
- Task.new(%w[scripts/gemfile_lock_changed.sh], 1),
- Task.new(%w[scripts/frontend/check_no_partial_karma_jest.sh], 1)
+ Task.new(%w[scripts/gemfile_lock_changed.sh], 1)
].compact.freeze
def run_tasks!(options = {})
diff --git a/spec/factories/clusters/agents.rb b/spec/factories/clusters/agents.rb
index 334671f69f0..4dc82f91bab 100644
--- a/spec/factories/clusters/agents.rb
+++ b/spec/factories/clusters/agents.rb
@@ -3,6 +3,7 @@
FactoryBot.define do
factory :cluster_agent, class: 'Clusters::Agent' do
project
+ association :created_by_user, factory: :user
sequence(:name) { |n| "agent-#{n}" }
end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index b3e5c5f1e64..df4e71c06de 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -557,6 +557,20 @@ RSpec.describe 'Admin updates settings' do
expect(page).to have_content "Application settings saved successfully"
expect(current_settings.issues_create_limit).to eq(0)
end
+
+ it 'changes Files API rate limits settings' do
+ visit network_admin_application_settings_path
+
+ page.within('[data-testid="files-limits-settings"]') do
+ check 'Enable unauthenticated API request rate limit'
+ fill_in 'Max unauthenticated API requests per period per IP', with: 10
+ click_button 'Save changes'
+ end
+
+ expect(page).to have_content "Application settings saved successfully"
+ expect(current_settings.throttle_unauthenticated_files_api_enabled).to be true
+ expect(current_settings.throttle_unauthenticated_files_api_requests_per_period).to eq(10)
+ end
end
context 'Preferences page' do
diff --git a/spec/javascripts/.eslintrc.yml b/spec/javascripts/.eslintrc.yml
deleted file mode 100644
index b863156b57c..00000000000
--- a/spec/javascripts/.eslintrc.yml
+++ /dev/null
@@ -1,39 +0,0 @@
----
-env:
- jasmine: true
-extends: plugin:jasmine/recommended
-globals:
- appendLoadFixtures: false
- appendLoadStyleFixtures: false
- appendSetFixtures: false
- appendSetStyleFixtures: false
- getJSONFixture: false
- loadFixtures: false
- loadJSONFixtures: false
- loadStyleFixtures: false
- preloadFixtures: false
- preloadStyleFixtures: false
- readFixtures: false
- sandbox: false
- setFixtures: false
- setStyleFixtures: false
- spyOnDependency: false
- spyOnEvent: false
- ClassSpecHelper: false
-plugins:
- - jasmine
-rules:
- func-names: off
- jasmine/no-suite-dupes:
- - warn
- - branch
- jasmine/no-spec-dupes:
- - warn
- - branch
- prefer-arrow-callback: off
- import/no-unresolved:
- - error
- - ignore:
- - 'fixtures/blob'
- # Temporarily disabled to facilitate an upgrade to eslint-plugin-jasmine
- jasmine/prefer-toHaveBeenCalledWith: off
diff --git a/spec/javascripts/fixtures/.gitignore b/spec/javascripts/fixtures/.gitignore
deleted file mode 100644
index d6b7ef32c84..00000000000
--- a/spec/javascripts/fixtures/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-!.gitignore
diff --git a/spec/javascripts/fly_out_nav_browser_spec.js b/spec/javascripts/fly_out_nav_browser_spec.js
deleted file mode 100644
index 12ea0e262bc..00000000000
--- a/spec/javascripts/fly_out_nav_browser_spec.js
+++ /dev/null
@@ -1,334 +0,0 @@
-// this file can't be migrated to jest because it relies on the browser to perform integration tests:
-// (specifically getClientBoundingRect and mouse movements)
-// see: https://gitlab.com/groups/gitlab-org/-/epics/895#what-if-theres-a-karma-spec-which-is-simply-unmovable-to-jest-ie-it-is-dependent-on-a-running-browser-environment
-
-import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
-import { SIDEBAR_COLLAPSED_CLASS } from '~/contextual_sidebar';
-import {
- calculateTop,
- showSubLevelItems,
- canShowSubItems,
- canShowActiveSubItems,
- mouseEnterTopItems,
- mouseLeaveTopItem,
- getOpenMenu,
- setOpenMenu,
- mousePos,
- getHideSubItemsInterval,
- documentMouseMove,
- getHeaderHeight,
- setSidebar,
- subItemsMouseLeave,
-} from '~/fly_out_nav';
-
-describe('Fly out sidebar navigation', () => {
- let el;
- let breakpointSize = 'lg';
-
- beforeEach(() => {
- el = document.createElement('div');
- el.style.position = 'relative';
- document.body.appendChild(el);
-
- spyOn(GlBreakpointInstance, 'getBreakpointSize').and.callFake(() => breakpointSize);
-
- setOpenMenu(null);
- });
-
- afterEach(() => {
- document.body.innerHTML = '';
- breakpointSize = 'lg';
- mousePos.length = 0;
-
- setSidebar(null);
- });
-
- describe('calculateTop', () => {
- it('returns boundingRect top', () => {
- const boundingRect = {
- top: 100,
- height: 100,
- };
-
- expect(calculateTop(boundingRect, 100)).toBe(100);
- });
-
- it('returns boundingRect - bottomOverflow', () => {
- const boundingRect = {
- top: window.innerHeight - 50,
- height: 100,
- };
-
- expect(calculateTop(boundingRect, 100)).toBe(window.innerHeight - 50);
- });
- });
-
- describe('getHideSubItemsInterval', () => {
- beforeEach(() => {
- el.innerHTML =
- '<div class="sidebar-sub-level-items" style="position: fixed; top: 0; left: 100px; height: 150px;"></div>';
- });
-
- it('returns 0 if currentOpenMenu is nil', () => {
- expect(getHideSubItemsInterval()).toBe(0);
- });
-
- it('returns 0 if mousePos is empty', () => {
- expect(getHideSubItemsInterval()).toBe(0);
- });
-
- it('returns 0 when mouse above sub-items', () => {
- showSubLevelItems(el);
- documentMouseMove({
- clientX: el.getBoundingClientRect().left,
- clientY: el.getBoundingClientRect().top,
- });
- documentMouseMove({
- clientX: el.getBoundingClientRect().left,
- clientY: el.getBoundingClientRect().top - 50,
- });
-
- expect(getHideSubItemsInterval()).toBe(0);
- });
-
- it('returns 0 when mouse is below sub-items', () => {
- const subItems = el.querySelector('.sidebar-sub-level-items');
-
- showSubLevelItems(el);
- documentMouseMove({
- clientX: el.getBoundingClientRect().left,
- clientY: el.getBoundingClientRect().top,
- });
- documentMouseMove({
- clientX: el.getBoundingClientRect().left,
- clientY: el.getBoundingClientRect().top - subItems.getBoundingClientRect().height + 50,
- });
-
- expect(getHideSubItemsInterval()).toBe(0);
- });
-
- it('returns 300 when mouse is moved towards sub-items', () => {
- documentMouseMove({
- clientX: el.getBoundingClientRect().left,
- clientY: el.getBoundingClientRect().top,
- });
- showSubLevelItems(el);
- documentMouseMove({
- clientX: el.getBoundingClientRect().left + 20,
- clientY: el.getBoundingClientRect().top + 10,
- });
-
- expect(getHideSubItemsInterval()).toBe(300);
- });
- });
-
- describe('mouseLeaveTopItem', () => {
- beforeEach(() => {
- spyOn(el.classList, 'remove');
- });
-
- it('removes is-over class if currentOpenMenu is null', () => {
- mouseLeaveTopItem(el);
-
- expect(el.classList.remove).toHaveBeenCalledWith('is-over');
- });
-
- it('removes is-over class if currentOpenMenu is null & there are sub-items', () => {
- el.innerHTML = '<div class="sidebar-sub-level-items" style="position: absolute;"></div>';
-
- mouseLeaveTopItem(el);
-
- expect(el.classList.remove).toHaveBeenCalledWith('is-over');
- });
-
- it('does not remove is-over class if currentOpenMenu is the passed in sub-items', () => {
- el.innerHTML = '<div class="sidebar-sub-level-items" style="position: absolute;"></div>';
-
- setOpenMenu(el.querySelector('.sidebar-sub-level-items'));
- mouseLeaveTopItem(el);
-
- expect(el.classList.remove).not.toHaveBeenCalled();
- });
- });
-
- describe('mouseEnterTopItems', () => {
- beforeEach(() => {
- el.innerHTML =
- '<div class="sidebar-sub-level-items" style="position: absolute; top: 0; left: 100px; height: 200px;"></div>';
- });
-
- it('shows sub-items after 0ms if no menu is open', (done) => {
- mouseEnterTopItems(el);
-
- expect(getHideSubItemsInterval()).toBe(0);
-
- setTimeout(() => {
- expect(el.querySelector('.sidebar-sub-level-items').style.display).toBe('block');
-
- done();
- });
- });
-
- it('shows sub-items after 300ms if a menu is currently open', (done) => {
- documentMouseMove({
- clientX: el.getBoundingClientRect().left,
- clientY: el.getBoundingClientRect().top,
- });
-
- setOpenMenu(el.querySelector('.sidebar-sub-level-items'));
-
- documentMouseMove({
- clientX: el.getBoundingClientRect().left + 20,
- clientY: el.getBoundingClientRect().top + 10,
- });
-
- mouseEnterTopItems(el, 0);
-
- expect(getHideSubItemsInterval()).toBe(300);
-
- setTimeout(() => {
- expect(el.querySelector('.sidebar-sub-level-items').style.display).toBe('block');
-
- done();
- });
- });
- });
-
- describe('showSubLevelItems', () => {
- beforeEach(() => {
- el.innerHTML = '<div class="sidebar-sub-level-items" style="position: absolute;"></div>';
- });
-
- it('adds is-over class to el', () => {
- spyOn(el.classList, 'add');
-
- showSubLevelItems(el);
-
- expect(el.classList.add).toHaveBeenCalledWith('is-over');
- });
-
- it('does not show sub-items on mobile', () => {
- breakpointSize = 'xs';
-
- showSubLevelItems(el);
-
- expect(el.querySelector('.sidebar-sub-level-items').style.display).not.toBe('block');
- });
-
- it('shows sub-items', () => {
- showSubLevelItems(el);
-
- expect(el.querySelector('.sidebar-sub-level-items').style.display).toBe('block');
- });
-
- it('shows collapsed only sub-items if icon only sidebar', () => {
- const subItems = el.querySelector('.sidebar-sub-level-items');
- const sidebar = document.createElement('div');
- sidebar.classList.add(SIDEBAR_COLLAPSED_CLASS);
- subItems.classList.add('is-fly-out-only');
-
- setSidebar(sidebar);
-
- showSubLevelItems(el);
-
- expect(el.querySelector('.sidebar-sub-level-items').style.display).toBe('block');
- });
-
- it('does not show collapsed only sub-items if icon only sidebar', () => {
- const subItems = el.querySelector('.sidebar-sub-level-items');
- subItems.classList.add('is-fly-out-only');
-
- showSubLevelItems(el);
-
- expect(subItems.style.display).not.toBe('block');
- });
-
- it('sets transform of sub-items', () => {
- const sidebar = document.createElement('div');
- const subItems = el.querySelector('.sidebar-sub-level-items');
-
- sidebar.style.width = '200px';
-
- document.body.appendChild(sidebar);
-
- setSidebar(sidebar);
- showSubLevelItems(el);
-
- expect(subItems.style.transform).toBe(
- `translate3d(200px, ${
- Math.floor(el.getBoundingClientRect().top) - getHeaderHeight()
- }px, 0px)`,
- );
- });
-
- it('sets is-above when element is above', () => {
- const subItems = el.querySelector('.sidebar-sub-level-items');
- subItems.style.height = `${window.innerHeight + el.offsetHeight}px`;
- el.style.top = `${window.innerHeight - el.offsetHeight}px`;
-
- spyOn(subItems.classList, 'add');
-
- showSubLevelItems(el);
-
- expect(subItems.classList.add).toHaveBeenCalledWith('is-above');
- });
- });
-
- describe('canShowSubItems', () => {
- it('returns true if on desktop size', () => {
- expect(canShowSubItems()).toBeTruthy();
- });
-
- it('returns false if on mobile size', () => {
- breakpointSize = 'xs';
-
- expect(canShowSubItems()).toBeFalsy();
- });
- });
-
- describe('canShowActiveSubItems', () => {
- it('returns true by default', () => {
- expect(canShowActiveSubItems(el)).toBeTruthy();
- });
-
- it('returns false when active & expanded sidebar', () => {
- const sidebar = document.createElement('div');
- el.classList.add('active');
-
- setSidebar(sidebar);
-
- expect(canShowActiveSubItems(el)).toBeFalsy();
- });
-
- it('returns true when active & collapsed sidebar', () => {
- const sidebar = document.createElement('div');
- sidebar.classList.add(SIDEBAR_COLLAPSED_CLASS);
- el.classList.add('active');
-
- setSidebar(sidebar);
-
- expect(canShowActiveSubItems(el)).toBeTruthy();
- });
- });
-
- describe('subItemsMouseLeave', () => {
- beforeEach(() => {
- el.innerHTML = '<div class="sidebar-sub-level-items" style="position: absolute;"></div>';
-
- setOpenMenu(el.querySelector('.sidebar-sub-level-items'));
- });
-
- it('hides subMenu if element is not hovered', () => {
- subItemsMouseLeave(el);
-
- expect(getOpenMenu()).toBeNull();
- });
-
- it('does not hide subMenu if element is hovered', () => {
- el.classList.add('is-over');
- subItemsMouseLeave(el);
-
- expect(getOpenMenu()).not.toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/lib/utils/mock_data.js b/spec/javascripts/lib/utils/mock_data.js
deleted file mode 100644
index f1358986f2a..00000000000
--- a/spec/javascripts/lib/utils/mock_data.js
+++ /dev/null
@@ -1 +0,0 @@
-export * from '../../../frontend/lib/utils/mock_data';
diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js
deleted file mode 100644
index be14d2ee7e7..00000000000
--- a/spec/javascripts/test_bundle.js
+++ /dev/null
@@ -1,145 +0,0 @@
-/* eslint-disable
- jasmine/no-global-setup, no-underscore-dangle, no-console
-*/
-
-import { config as testUtilsConfig } from '@vue/test-utils';
-import jasmineDiff from 'jasmine-diff';
-import $ from 'jquery';
-import 'core-js/features/set-immediate';
-import 'vendor/jasmine-jquery';
-import '~/commons';
-import Vue from 'vue';
-import { getDefaultAdapter } from '~/lib/utils/axios_utils';
-import Translate from '~/vue_shared/translate';
-
-import { FIXTURES_PATH, TEST_HOST } from './test_constants';
-
-// Tech debt issue TBD
-testUtilsConfig.logModifiedComponents = false;
-
-const isHeadlessChrome = /\bHeadlessChrome\//.test(navigator.userAgent);
-Vue.config.devtools = !isHeadlessChrome;
-Vue.config.productionTip = false;
-
-let hasVueWarnings = false;
-Vue.config.warnHandler = (msg, vm, trace) => {
- // The following workaround is necessary, so we are able to use setProps from Vue test utils
- // see https://github.com/vuejs/vue-test-utils/issues/631#issuecomment-421108344
- const currentStack = new Error().stack;
- const isInVueTestUtils = currentStack
- .split('\n')
- .some((line) => line.startsWith(' at VueWrapper.setProps ('));
- if (isInVueTestUtils) {
- return;
- }
-
- hasVueWarnings = true;
- fail(`${msg}${trace}`);
-};
-
-let hasVueErrors = false;
-Vue.config.errorHandler = function (err) {
- hasVueErrors = true;
- fail(err);
-};
-
-Vue.use(Translate);
-
-// enable test fixtures
-jasmine.getFixtures().fixturesPath = FIXTURES_PATH;
-jasmine.getJSONFixtures().fixturesPath = FIXTURES_PATH;
-
-beforeAll(() => {
- jasmine.addMatchers(
- jasmineDiff(jasmine, {
- colors: window.__karma__.config.color,
- inline: window.__karma__.config.color,
- }),
- );
-});
-
-// globalize common libraries
-window.$ = $;
-window.jQuery = window.$;
-
-// stub expected globals
-window.gl = window.gl || {};
-window.gl.TEST_HOST = TEST_HOST;
-window.gon = window.gon || {};
-window.gon.test_env = true;
-window.gon.ee = process.env.IS_EE;
-gon.relative_url_root = '';
-
-let hasUnhandledPromiseRejections = false;
-
-window.addEventListener('unhandledrejection', (event) => {
- hasUnhandledPromiseRejections = true;
- console.error('Unhandled promise rejection:');
- console.error(event.reason.stack || event.reason);
-});
-
-let longRunningTestTimeoutHandle;
-
-beforeEach((done) => {
- longRunningTestTimeoutHandle = setTimeout(() => {
- done.fail('Test is running too long!');
- }, 4000);
- done();
-});
-
-afterEach(() => {
- clearTimeout(longRunningTestTimeoutHandle);
-});
-
-const axiosDefaultAdapter = getDefaultAdapter();
-
-// render all of our tests
-const testContexts = [require.context('spec', true, /_spec$/)];
-
-if (process.env.IS_EE) {
- testContexts.push(require.context('ee_spec', true, /_spec$/));
-}
-
-testContexts.forEach((context) => {
- context.keys().forEach((path) => {
- try {
- context(path);
- } catch (err) {
- console.log(err);
- console.error('[GL SPEC RUNNER ERROR] Unable to load spec: ', path);
- describe('Test bundle', function () {
- it(`includes '${path}'`, function () {
- expect(err).toBeNull();
- });
- });
- }
- });
-});
-
-describe('test errors', () => {
- beforeAll((done) => {
- if (hasUnhandledPromiseRejections || hasVueWarnings || hasVueErrors) {
- setTimeout(done, 1000);
- } else {
- done();
- }
- });
-
- it('has no unhandled Promise rejections', () => {
- expect(hasUnhandledPromiseRejections).toBe(false);
- });
-
- it('has no Vue warnings', () => {
- expect(hasVueWarnings).toBe(false);
- });
-
- it('has no Vue error', () => {
- expect(hasVueErrors).toBe(false);
- });
-
- it('restores axios adapter after mocking', () => {
- if (getDefaultAdapter() !== axiosDefaultAdapter) {
- fail('axios adapter is not restored! Did you forget a restore() on MockAdapter?');
- }
- });
-});
diff --git a/spec/javascripts/test_constants.js b/spec/javascripts/test_constants.js
deleted file mode 100644
index de7b3a0e80c..00000000000
--- a/spec/javascripts/test_constants.js
+++ /dev/null
@@ -1 +0,0 @@
-export * from '../frontend/__helpers__/test_constants';
diff --git a/spec/lib/gitlab/background_migration/backfill_projects_with_coverage_spec.rb b/spec/lib/gitlab/background_migration/backfill_projects_with_coverage_spec.rb
new file mode 100644
index 00000000000..49056154744
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_projects_with_coverage_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillProjectsWithCoverage, schema: 20210818185845 do
+ let(:projects) { table(:projects) }
+ let(:project_ci_feature_usages) { table(:project_ci_feature_usages) }
+ let(:ci_pipelines) { table(:ci_pipelines) }
+ let(:ci_daily_build_group_report_results) { table(:ci_daily_build_group_report_results) }
+ let(:group) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:project_1) { projects.create!(namespace_id: group.id) }
+ let(:project_2) { projects.create!(namespace_id: group.id) }
+ let(:pipeline_1) { ci_pipelines.create!(project_id: project_1.id, source: 13) }
+ let(:pipeline_2) { ci_pipelines.create!(project_id: project_1.id, source: 13) }
+ let(:pipeline_3) { ci_pipelines.create!(project_id: project_2.id, source: 13) }
+ let(:pipeline_4) { ci_pipelines.create!(project_id: project_2.id, source: 13) }
+
+ subject { described_class.new }
+
+ describe '#perform' do
+ before do
+ ci_daily_build_group_report_results.create!(
+ id: 1,
+ project_id: project_1.id,
+ date: 4.days.ago,
+ last_pipeline_id: pipeline_1.id,
+ ref_path: 'main',
+ group_name: 'rspec',
+ data: { coverage: 95.0 },
+ default_branch: true,
+ group_id: group.id
+ )
+
+ ci_daily_build_group_report_results.create!(
+ id: 2,
+ project_id: project_1.id,
+ date: 3.days.ago,
+ last_pipeline_id: pipeline_2.id,
+ ref_path: 'main',
+ group_name: 'rspec',
+ data: { coverage: 95.0 },
+ default_branch: true,
+ group_id: group.id
+ )
+
+ ci_daily_build_group_report_results.create!(
+ id: 3,
+ project_id: project_2.id,
+ date: 2.days.ago,
+ last_pipeline_id: pipeline_3.id,
+ ref_path: 'main',
+ group_name: 'rspec',
+ data: { coverage: 95.0 },
+ default_branch: true,
+ group_id: group.id
+ )
+
+ ci_daily_build_group_report_results.create!(
+ id: 4,
+ project_id: project_2.id,
+ date: 1.day.ago,
+ last_pipeline_id: pipeline_4.id,
+ ref_path: 'test_branch',
+ group_name: 'rspec',
+ data: { coverage: 95.0 },
+ default_branch: false,
+ group_id: group.id
+ )
+
+ stub_const("#{described_class}::INSERT_DELAY_SECONDS", 0)
+ end
+
+ it 'creates entries per project and default_branch combination in the given range', :aggregate_failures do
+ subject.perform(1, 4, 2)
+
+ entries = project_ci_feature_usages.order('project_id ASC, default_branch DESC')
+
+ expect(entries.count).to eq(3)
+ expect(entries[0]).to have_attributes(project_id: project_1.id, feature: 1, default_branch: true)
+ expect(entries[1]).to have_attributes(project_id: project_2.id, feature: 1, default_branch: true)
+ expect(entries[2]).to have_attributes(project_id: project_2.id, feature: 1, default_branch: false)
+ end
+
+ context 'when an entry for the project and default branch combination already exists' do
+ before do
+ subject.perform(1, 4, 2)
+ end
+
+ it 'does not create a new entry' do
+ expect { subject.perform(1, 4, 2) }.not_to change { project_ci_feature_usages.count }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb b/spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb
index 0ca99ec9acf..52c3d49086c 100644
--- a/spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb
@@ -3,7 +3,9 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
- let(:proxy) { described_class.new }
+ let(:proxy) do
+ described_class.new(Gitlab::Database::LoadBalancing::LoadBalancer.new([]))
+ end
describe '#select' do
it 'performs a read' do
@@ -35,9 +37,15 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
describe 'using a SELECT FOR UPDATE query' do
it 'runs the query on the primary and sticks to it' do
arel = double(:arel, locked: true)
+ session = Gitlab::Database::LoadBalancing::Session.new
+
+ allow(Gitlab::Database::LoadBalancing::Session).to receive(:current)
+ .and_return(session)
+
+ expect(session).to receive(:write!)
expect(proxy).to receive(:write_using_load_balancer)
- .with(:select_all, arel, 'foo', [], sticky: true)
+ .with(:select_all, arel, 'foo', [])
proxy.select_all(arel, 'foo')
end
@@ -58,8 +66,13 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
Gitlab::Database::LoadBalancing::ConnectionProxy::STICKY_WRITES.each do |name|
describe "#{name}" do
it 'runs the query on the primary and sticks to it' do
- expect(proxy).to receive(:write_using_load_balancer)
- .with(name, 'foo', sticky: true)
+ session = Gitlab::Database::LoadBalancing::Session.new
+
+ allow(Gitlab::Database::LoadBalancing::Session).to receive(:current)
+ .and_return(session)
+
+ expect(session).to receive(:write!)
+ expect(proxy).to receive(:write_using_load_balancer).with(name, 'foo')
proxy.send(name, 'foo')
end
@@ -108,7 +121,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
# We have an extra test for #transaction here to make sure that nested queries
# are also sent to a primary.
describe '#transaction' do
- let(:session) { double(:session) }
+ let(:session) { Gitlab::Database::LoadBalancing::Session.new }
before do
allow(Gitlab::Database::LoadBalancing::Session).to receive(:current)
@@ -192,7 +205,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
proxy.foo('foo')
end
- it 'properly forwards trailing hash arguments' do
+ it 'properly forwards keyword arguments' do
allow(proxy.load_balancer).to receive(:read_write)
expect(proxy).to receive(:write_using_load_balancer).and_call_original
@@ -217,7 +230,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
proxy.foo('foo')
end
- it 'properly forwards trailing hash arguments' do
+ it 'properly forwards keyword arguments' do
allow(proxy.load_balancer).to receive(:read)
expect(proxy).to receive(:read_using_load_balancer).and_call_original
@@ -297,20 +310,12 @@ RSpec.describe Gitlab::Database::LoadBalancing::ConnectionProxy do
.and_return(session)
end
- it 'uses but does not stick to the primary when sticking is disabled' do
+ it 'uses but does not stick to the primary' do
expect(proxy.load_balancer).to receive(:read_write).and_yield(connection)
expect(connection).to receive(:foo).with('foo')
expect(session).not_to receive(:write!)
proxy.write_using_load_balancer(:foo, 'foo')
end
-
- it 'sticks to the primary when sticking is enabled' do
- expect(proxy.load_balancer).to receive(:read_write).and_yield(connection)
- expect(connection).to receive(:foo).with('foo')
- expect(session).to receive(:write!)
-
- proxy.write_using_load_balancer(:foo, 'foo', sticky: true)
- end
end
end
diff --git a/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb b/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
index 4de5cb7c3d7..5d8440123e6 100644
--- a/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
@@ -41,6 +41,17 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
top_error
end
+ describe '#initialize' do
+ it 'ignores the hosts when the primary_only option is enabled' do
+ lb = described_class.new([db_host], primary_only: true)
+ hosts = lb.host_list.hosts
+
+ expect(hosts.length).to eq(1)
+ expect(hosts.first)
+ .to be_instance_of(Gitlab::Database::LoadBalancing::PrimaryHost)
+ end
+ end
+
describe '#read' do
it 'yields a connection for a read' do
connection = double(:connection)
@@ -121,6 +132,17 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
expect { |b| lb.read(&b) }
.to yield_with_args(ActiveRecord::Base.retrieve_connection)
end
+
+ it 'uses the primary when the primary_only option is enabled' do
+ lb = described_class.new(primary_only: true)
+
+ # When no hosts are configured, we don't want to produce any warnings, as
+ # they aren't useful/too noisy.
+ expect(Gitlab::Database::LoadBalancing::Logger).not_to receive(:warn)
+
+ expect { |b| lb.read(&b) }
+ .to yield_with_args(ActiveRecord::Base.retrieve_connection)
+ end
end
describe '#read_write' do
diff --git a/spec/lib/gitlab/database/load_balancing/primary_host_spec.rb b/spec/lib/gitlab/database/load_balancing/primary_host_spec.rb
new file mode 100644
index 00000000000..a2f8e52db2f
--- /dev/null
+++ b/spec/lib/gitlab/database/load_balancing/primary_host_spec.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LoadBalancing::PrimaryHost do
+ let(:load_balancer) { Gitlab::Database::LoadBalancing::LoadBalancer.new }
+ let(:host) { Gitlab::Database::LoadBalancing::PrimaryHost.new(load_balancer) }
+
+ describe '#connection' do
+ it 'returns a connection from the pool' do
+ expect(load_balancer.pool).to receive(:connection)
+
+ host.connection
+ end
+ end
+
+ describe '#release_connection' do
+ it 'releases a connection from the pool' do
+ expect(load_balancer).to receive(:release_primary_connection)
+
+ host.release_connection
+ end
+ end
+
+ describe '#enable_query_cache!' do
+ it 'does nothing' do
+ expect(host.enable_query_cache!).to be_nil
+ end
+ end
+
+ describe '#disable_query_cache!' do
+ it 'does nothing' do
+ expect(host.disable_query_cache!).to be_nil
+ end
+ end
+
+ describe '#query_cache_enabled' do
+ it 'delegates to the primary connection pool' do
+ expect(host.query_cache_enabled)
+ .to eq(load_balancer.pool.query_cache_enabled)
+ end
+ end
+
+ describe '#disconnect!' do
+ it 'does nothing' do
+ expect(host.disconnect!).to be_nil
+ end
+ end
+
+ describe '#offline!' do
+ it 'does nothing' do
+ expect(host.offline!).to be_nil
+ end
+ end
+
+ describe '#online?' do
+ it 'returns true' do
+ expect(host.online?).to eq(true)
+ end
+ end
+
+ describe '#primary_write_location' do
+ it 'returns the write location of the primary' do
+ expect(host.primary_write_location).to be_an_instance_of(String)
+ expect(host.primary_write_location).not_to be_empty
+ end
+ end
+
+ describe '#caught_up?' do
+ it 'returns true' do
+ expect(host.caught_up?('foo')).to eq(true)
+ end
+ end
+
+ describe '#database_replica_location' do
+ let(:connection) { double(:connection) }
+
+ it 'returns the write ahead location of the replica', :aggregate_failures do
+ expect(host)
+ .to receive(:query_and_release)
+ .and_return({ 'location' => '0/D525E3A8' })
+
+ expect(host.database_replica_location).to be_an_instance_of(String)
+ end
+
+ it 'returns nil when the database query returned no rows' do
+ expect(host).to receive(:query_and_release).and_return({})
+
+ expect(host.database_replica_location).to be_nil
+ end
+
+ it 'returns nil when the database connection fails' do
+ allow(host).to receive(:connection).and_raise(PG::Error)
+
+ expect(host.database_replica_location).to be_nil
+ end
+ end
+
+ describe '#query_and_release' do
+ it 'executes a SQL query' do
+ results = host.query_and_release('SELECT 10 AS number')
+
+ expect(results).to be_an_instance_of(Hash)
+ expect(results['number'].to_i).to eq(10)
+ end
+
+ it 'releases the connection after running the query' do
+ expect(host)
+ .to receive(:release_connection)
+ .once
+
+ host.query_and_release('SELECT 10 AS number')
+ end
+
+ it 'returns an empty Hash in the event of an error' do
+ expect(host.connection)
+ .to receive(:select_all)
+ .and_raise(RuntimeError, 'kittens')
+
+ expect(host.query_and_release('SELECT 10 AS number')).to eq({})
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing_spec.rb b/spec/lib/gitlab/database/load_balancing_spec.rb
index 08dc449ec60..c1df02cb584 100644
--- a/spec/lib/gitlab/database/load_balancing_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing_spec.rb
@@ -306,10 +306,10 @@ RSpec.describe Gitlab::Database::LoadBalancing do
.and_return(true)
instance = double(:instance)
- lb = instance_spy(Gitlab::Database::LoadBalancing::LoadBalancer)
- proxy = double(:proxy, load_balancer: lb)
+ lb = Gitlab::Database::LoadBalancing::LoadBalancer.new([])
+ proxy = Gitlab::Database::LoadBalancing::ConnectionProxy.new(lb)
- allow(Gitlab::Database::LoadBalancing)
+ allow(described_class)
.to receive(:proxy)
.and_return(proxy)
@@ -345,7 +345,8 @@ RSpec.describe Gitlab::Database::LoadBalancing do
context 'when the load balancing is configured' do
let(:db_host) { ActiveRecord::Base.connection_pool.db_config.host }
- let(:proxy) { described_class::ConnectionProxy.new([db_host]) }
+ let(:load_balancer) { described_class::LoadBalancer.new([db_host]) }
+ let(:proxy) { described_class::ConnectionProxy.new(load_balancer) }
context 'when a proxy connection is used' do
it 'returns :unknown' do
@@ -785,6 +786,16 @@ RSpec.describe Gitlab::Database::LoadBalancing do
it 'redirects queries to the right roles' do
roles = []
+ # If we don't run any queries, the pool may be a NullPool. This can
+ # result in some tests reporting a role as `:unknown`, even though the
+ # tests themselves are correct.
+ #
+ # To prevent this from happening we simply run a simple query to
+ # ensure the proper pool type is put in place. The exact query doesn't
+ # matter, provided it actually runs a query and thus creates a proper
+ # connection pool.
+ model.count
+
subscriber = ActiveSupport::Notifications.subscribe('sql.active_record') do |event|
role = ::Gitlab::Database::LoadBalancing.db_role_for_connection(event.payload[:connection])
roles << role if role.present?
diff --git a/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb b/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb
index cd1828791c3..b2a11353d0c 100644
--- a/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb
+++ b/spec/lib/gitlab/instrumentation/redis_interceptor_spec.rb
@@ -130,15 +130,25 @@ RSpec.describe Gitlab::Instrumentation::RedisInterceptor, :clean_gitlab_redis_sh
end
context 'when report_on_long_redis_durations is enabled' do
- it 'tracks an exception and continues' do
- expect(Gitlab::ErrorTracking)
- .to receive(:track_exception)
- .with(an_instance_of(described_class::MysteryRedisDurationError),
- command: 'mget',
- duration: be > threshold,
- timestamp: a_string_matching(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{5}/))
+ context 'for an instance other than SharedState' do
+ it 'does nothing' do
+ expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
- Gitlab::Redis::SharedState.with { |r| r.mget('foo', 'foo') { sleep threshold + 0.1 } }
+ Gitlab::Redis::Queues.with { |r| r.mget('foo', 'foo') { sleep threshold + 0.1 } }
+ end
+ end
+
+ context 'for the SharedState instance' do
+ it 'tracks an exception and continues' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_exception)
+ .with(an_instance_of(described_class::MysteryRedisDurationError),
+ command: 'mget',
+ duration: be > threshold,
+ timestamp: a_string_matching(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{5}/))
+
+ Gitlab::Redis::SharedState.with { |r| r.mget('foo', 'foo') { sleep threshold + 0.1 } }
+ end
end
end
end
diff --git a/spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb b/spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb
new file mode 100644
index 00000000000..d87f952b5da
--- /dev/null
+++ b/spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!('backfill_projects_with_coverage')
+
+RSpec.describe BackfillProjectsWithCoverage do
+ let(:projects) { table(:projects) }
+ let(:ci_pipelines) { table(:ci_pipelines) }
+ let(:ci_daily_build_group_report_results) { table(:ci_daily_build_group_report_results) }
+ let(:group) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:project_1) { projects.create!(namespace_id: group.id) }
+ let(:project_2) { projects.create!(namespace_id: group.id) }
+ let(:pipeline_1) { ci_pipelines.create!(project_id: project_1.id) }
+ let(:pipeline_2) { ci_pipelines.create!(project_id: project_2.id) }
+ let(:pipeline_3) { ci_pipelines.create!(project_id: project_2.id) }
+
+ describe '#up' do
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 2)
+ stub_const("#{described_class}::SUB_BATCH_SIZE", 1)
+
+ ci_daily_build_group_report_results.create!(
+ id: 1,
+ project_id: project_1.id,
+ date: 3.days.ago,
+ last_pipeline_id: pipeline_1.id,
+ ref_path: 'main',
+ group_name: 'rspec',
+ data: { coverage: 95.0 },
+ default_branch: true,
+ group_id: group.id
+ )
+
+ ci_daily_build_group_report_results.create!(
+ id: 2,
+ project_id: project_2.id,
+ date: 2.days.ago,
+ last_pipeline_id: pipeline_2.id,
+ ref_path: 'main',
+ group_name: 'rspec',
+ data: { coverage: 95.0 },
+ default_branch: true,
+ group_id: group.id
+ )
+
+ ci_daily_build_group_report_results.create!(
+ id: 3,
+ project_id: project_2.id,
+ date: 1.day.ago,
+ last_pipeline_id: pipeline_3.id,
+ ref_path: 'test_branch',
+ group_name: 'rspec',
+ data: { coverage: 95.0 },
+ default_branch: false,
+ group_id: group.id
+ )
+ end
+
+ it 'schedules BackfillProjectsWithCoverage background jobs', :aggregate_failures do
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, 1, 2, 1)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, 3, 3, 1)
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/rubocop/cop/migration/prevent_index_creation_spec.rb b/spec/rubocop/cop/migration/prevent_index_creation_spec.rb
index aa1779a8cd5..b5bb770553a 100644
--- a/spec/rubocop/cop/migration/prevent_index_creation_spec.rb
+++ b/spec/rubocop/cop/migration/prevent_index_creation_spec.rb
@@ -15,22 +15,63 @@ RSpec.describe RuboCop::Cop::Migration::PreventIndexCreation do
end
context 'when adding an index to a forbidden table' do
- it "registers an offense when add_index is used", :aggregate_failures do
- forbidden_tables.each do |table|
- expect_offense(<<~RUBY)
- def change
- add_index :#{table}, :protected
- ^^^^^^^^^ Adding new index to #{forbidden_tables_list} is forbidden, see https://gitlab.com/gitlab-org/gitlab/-/issues/332886
- end
- RUBY
+ context 'when table_name is a symbol' do
+ it "registers an offense when add_index is used", :aggregate_failures do
+ forbidden_tables.each do |table_name|
+ expect_offense(<<~RUBY)
+ def change
+ add_index :#{table_name}, :protected
+ ^^^^^^^^^ Adding new index to #{forbidden_tables_list} is forbidden, see https://gitlab.com/gitlab-org/gitlab/-/issues/332886
+ end
+ RUBY
+ end
+ end
+
+ it "registers an offense when add_concurrent_index is used", :aggregate_failures do
+ forbidden_tables.each do |table_name|
+ expect_offense(<<~RUBY)
+ def change
+ add_concurrent_index :#{table_name}, :protected
+ ^^^^^^^^^^^^^^^^^^^^ Adding new index to #{forbidden_tables_list} is forbidden, see https://gitlab.com/gitlab-org/gitlab/-/issues/332886
+ end
+ RUBY
+ end
end
end
- it "registers an offense when add_concurrent_index is used", :aggregate_failures do
- forbidden_tables.each do |table|
+ context 'when table_name is a string' do
+ it "registers an offense when add_index is used", :aggregate_failures do
+ forbidden_tables.each do |table_name|
+ expect_offense(<<~RUBY)
+ def change
+ add_index "#{table_name}", :protected
+ ^^^^^^^^^ Adding new index to #{forbidden_tables_list} is forbidden, see https://gitlab.com/gitlab-org/gitlab/-/issues/332886
+ end
+ RUBY
+ end
+ end
+
+ it "registers an offense when add_concurrent_index is used", :aggregate_failures do
+ forbidden_tables.each do |table_name|
+ expect_offense(<<~RUBY)
+ def change
+ add_concurrent_index "#{table_name}", :protected
+ ^^^^^^^^^^^^^^^^^^^^ Adding new index to #{forbidden_tables_list} is forbidden, see https://gitlab.com/gitlab-org/gitlab/-/issues/332886
+ end
+ RUBY
+ end
+ end
+ end
+
+ context 'when table_name is a constant' do
+ it "registers an offense when add_concurrent_index is used", :aggregate_failures do
expect_offense(<<~RUBY)
+ INDEX_NAME = "index_name"
+ TABLE_NAME = :ci_builds
+ disable_ddl_transaction!
+
def change
- add_concurrent_index :#{table}, :protected
+ add_concurrent_index TABLE_NAME, :protected
^^^^^^^^^^^^^^^^^^^^ Adding new index to #{forbidden_tables_list} is forbidden, see https://gitlab.com/gitlab-org/gitlab/-/issues/332886
end
RUBY
@@ -46,6 +87,20 @@ RSpec.describe RuboCop::Cop::Migration::PreventIndexCreation do
end
RUBY
end
+
+ context 'when using a constant' do
+ it 'does not register an offense' do
+ expect_no_offenses(<<~RUBY)
+ disable_ddl_transaction!
+
+ TABLE_NAME = "not_forbidden"
+
+ def up
+ add_concurrent_index TABLE_NAME, :protected
+ end
+ RUBY
+ end
+ end
end
end
diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb
index 0f21736eda0..1edcbd01861 100644
--- a/spec/services/projects/update_pages_service_spec.rb
+++ b/spec/services/projects/update_pages_service_spec.rb
@@ -19,16 +19,9 @@ RSpec.describe Projects::UpdatePagesService do
subject { described_class.new(project, build) }
before do
- stub_feature_flags(skip_pages_deploy_to_legacy_storage: false)
project.legacy_remove_pages
end
- context '::TMP_EXTRACT_PATH' do
- subject { described_class::TMP_EXTRACT_PATH }
-
- it { is_expected.not_to match(Gitlab::PathRegex.namespace_format_regex) }
- end
-
context 'for new artifacts' do
context "for a valid job" do
let!(:artifacts_archive) { create(:ci_job_artifact, :correct_checksum, file: file, job: build) }
@@ -52,36 +45,6 @@ RSpec.describe Projects::UpdatePagesService do
expect(project.pages_metadatum).to be_deployed
expect(project.pages_metadatum.artifacts_archive).to eq(artifacts_archive)
expect(project.pages_deployed?).to be_truthy
-
- # Check that all expected files are extracted
- %w[index.html zero .hidden/file].each do |filename|
- expect(File.exist?(File.join(project.pages_path, 'public', filename))).to be_truthy
- end
- end
-
- it 'creates a temporary directory with the project and build ID' do
- expect(Dir).to receive(:mktmpdir).with("project-#{project.id}-build-#{build.id}-", anything).and_call_original
-
- subject.execute
- end
-
- it "doesn't deploy to legacy storage if it's disabled" do
- allow(Settings.pages.local_store).to receive(:enabled).and_return(false)
-
- expect(execute).to eq(:success)
- expect(project.pages_deployed?).to be_truthy
-
- expect(File.exist?(File.join(project.pages_path, 'public', 'index.html'))).to eq(false)
- end
-
- it "doesn't deploy to legacy storage if skip_pages_deploy_to_legacy_storage is enabled" do
- allow(Settings.pages.local_store).to receive(:enabled).and_return(true)
- stub_feature_flags(skip_pages_deploy_to_legacy_storage: true)
-
- expect(execute).to eq(:success)
- expect(project.pages_deployed?).to be_truthy
-
- expect(File.exist?(File.join(project.pages_path, 'public', 'index.html'))).to eq(false)
end
it 'creates pages_deployment and saves it in the metadata' do
@@ -99,16 +62,6 @@ RSpec.describe Projects::UpdatePagesService do
expect(deployment.ci_build_id).to eq(build.id)
end
- it 'fails if another deployment is in progress' do
- subject.try_obtain_lease do
- expect do
- execute
- end.to raise_error("Failed to deploy pages - other deployment is in progress")
-
- expect(GenericCommitStatus.last.description).to eq("Failed to deploy pages - other deployment is in progress")
- end
- end
-
it 'does not fail if pages_metadata is absent' do
project.pages_metadatum.destroy!
project.reload
@@ -156,47 +109,10 @@ RSpec.describe Projects::UpdatePagesService do
expect(GenericCommitStatus.last.description).to eq("pages site contains 3 file entries, while limit is set to 2")
end
- it 'removes pages after destroy' do
- expect(PagesWorker).to receive(:perform_in)
- expect(project.pages_deployed?).to be_falsey
- expect(Dir.exist?(File.join(project.pages_path))).to be_falsey
-
- expect(execute).to eq(:success)
-
- expect(project.pages_metadatum).to be_deployed
- expect(project.pages_deployed?).to be_truthy
- expect(Dir.exist?(File.join(project.pages_path))).to be_truthy
-
- project.destroy!
-
- expect(Dir.exist?(File.join(project.pages_path))).to be_falsey
- expect(ProjectPagesMetadatum.find_by_project_id(project)).to be_nil
- end
-
- context 'when using empty file' do
- let(:file) { empty_file }
-
- it 'fails to extract' do
- expect { execute }
- .to raise_error(Projects::UpdatePagesService::FailedToExtractError)
- end
- end
-
- context 'when using pages with non-writeable public' do
- let(:file) { fixture_file_upload("spec/fixtures/pages_non_writeable.zip") }
-
- context 'when using RubyZip' do
- it 'succeeds to extract' do
- expect(execute).to eq(:success)
- expect(project.pages_metadatum).to be_deployed
- end
- end
- end
-
context 'when timeout happens by DNS error' do
before do
allow_next_instance_of(described_class) do |instance|
- allow(instance).to receive(:extract_zip_archive!).and_raise(SocketError)
+ allow(instance).to receive(:create_pages_deployment).and_raise(SocketError)
end
end
@@ -209,24 +125,6 @@ RSpec.describe Projects::UpdatePagesService do
end
end
- context 'when failed to extract zip artifacts' do
- before do
- expect_next_instance_of(described_class) do |instance|
- expect(instance).to receive(:extract_zip_archive!)
- .and_raise(Projects::UpdatePagesService::FailedToExtractError)
- end
- end
-
- it 'raises an error' do
- expect { execute }
- .to raise_error(Projects::UpdatePagesService::FailedToExtractError)
-
- build.reload
- expect(deploy_status).to be_failed
- expect(project.pages_metadatum).not_to be_deployed
- end
- end
-
context 'when missing artifacts metadata' do
before do
expect(build).to receive(:artifacts_metadata?).and_return(false)
@@ -338,12 +236,6 @@ RSpec.describe Projects::UpdatePagesService do
end
end
- it 'fails to remove project pages when no pages is deployed' do
- expect(PagesWorker).not_to receive(:perform_in)
- expect(project.pages_deployed?).to be_falsey
- project.destroy!
- end
-
it 'fails if no artifacts' do
expect(execute).not_to eq(:success)
end
@@ -384,38 +276,6 @@ RSpec.describe Projects::UpdatePagesService do
end
end
- context 'when file size is spoofed' do
- let(:metadata) { spy('metadata') }
-
- include_context 'pages zip with spoofed size'
-
- before do
- file = fixture_file_upload(fake_zip_path, 'pages.zip')
- metafile = fixture_file_upload('spec/fixtures/pages.zip.meta')
-
- create(:ci_job_artifact, :archive, file: file, job: build)
- create(:ci_job_artifact, :metadata, file: metafile, job: build)
-
- allow(build).to receive(:artifacts_metadata_entry).with('public/', recursive: true)
- .and_return(metadata)
- allow(metadata).to receive(:total_size).and_return(100)
-
- # to pass entries count check
- root_metadata = double('root metadata')
- allow(build).to receive(:artifacts_metadata_entry).with('', recursive: true)
- .and_return(root_metadata)
- allow(root_metadata).to receive_message_chain(:entries, :count).and_return(10)
- end
-
- it 'raises an error' do
- expect do
- subject.execute
- end.to raise_error(Projects::UpdatePagesService::FailedToExtractError,
- 'Entry public/index.html should be 1B but is larger when inflated')
- expect(deploy_status).to be_script_failure
- end
- end
-
context 'when retrying the job' do
let!(:older_deploy_job) do
create(:generic_commit_status, :failed, pipeline: pipeline,
diff --git a/spec/support/database_load_balancing.rb b/spec/support/database_load_balancing.rb
index 03fa7886295..7b0f49cb1b4 100644
--- a/spec/support/database_load_balancing.rb
+++ b/spec/support/database_load_balancing.rb
@@ -4,7 +4,9 @@ RSpec.configure do |config|
config.before(:each, :db_load_balancing) do
allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
- proxy = ::Gitlab::Database::LoadBalancing::ConnectionProxy.new([Gitlab::Database.main.config['host']])
+ lb = ::Gitlab::Database::LoadBalancing::LoadBalancer
+ .new([Gitlab::Database.main.config['host']])
+ proxy = ::Gitlab::Database::LoadBalancing::ConnectionProxy.new(lb)
allow(ActiveRecord::Base).to receive(:load_balancing_proxy).and_return(proxy)
diff --git a/spec/support/shared_contexts/pages_zip_with_spoofed_size_shared_context.rb b/spec/support/shared_contexts/pages_zip_with_spoofed_size_shared_context.rb
deleted file mode 100644
index 4cec5ab3b74..00000000000
--- a/spec/support/shared_contexts/pages_zip_with_spoofed_size_shared_context.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-# the idea of creating zip archive with spoofed size is borrowed from
-# https://github.com/rubyzip/rubyzip/pull/403/files#diff-118213fb4baa6404a40f89e1147661ebR88
-RSpec.shared_context 'pages zip with spoofed size' do
- let(:real_zip_path) { Tempfile.new(['real', '.zip']).path }
- let(:fake_zip_path) { Tempfile.new(['fake', '.zip']).path }
-
- before do
- full_file_name = 'public/index.html'
- true_size = 500_000
- fake_size = 1
-
- ::Zip::File.open(real_zip_path, ::Zip::File::CREATE) do |zf|
- zf.get_output_stream(full_file_name) do |os|
- os.write 'a' * true_size
- end
- end
-
- compressed_size = nil
- ::Zip::File.open(real_zip_path) do |zf|
- a_entry = zf.find_entry(full_file_name)
- compressed_size = a_entry.compressed_size
- end
-
- true_size_bytes = [compressed_size, true_size, full_file_name.size].pack('LLS')
- fake_size_bytes = [compressed_size, fake_size, full_file_name.size].pack('LLS')
-
- data = File.binread(real_zip_path)
- data.gsub! true_size_bytes, fake_size_bytes
-
- File.open(fake_zip_path, 'wb') do |file|
- file.write data
- end
- end
-
- after do
- File.delete(real_zip_path) if File.exist?(real_zip_path)
- File.delete(fake_zip_path) if File.exist?(fake_zip_path)
- end
-end
diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb
index f52c5e02544..c7715eb43fc 100644
--- a/spec/tooling/danger/project_helper_spec.rb
+++ b/spec/tooling/danger/project_helper_spec.rb
@@ -60,7 +60,6 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'app/views/foo' | [:frontend]
'public/foo' | [:frontend]
'scripts/frontend/foo' | [:frontend]
- 'spec/javascripts/foo' | [:frontend]
'spec/frontend/bar' | [:frontend]
'spec/frontend_integration/bar' | [:frontend]
'vendor/assets/foo' | [:frontend]
@@ -73,7 +72,6 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'ee/app/assets/foo' | [:frontend]
'ee/app/views/foo' | [:frontend]
- 'ee/spec/javascripts/foo' | [:frontend]
'ee/spec/frontend/bar' | [:frontend]
'ee/spec/frontend_integration/bar' | [:frontend]
@@ -220,7 +218,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
describe '.local_warning_message' do
it 'returns an informational message with rules that can run' do
- expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changelog, database, documentation, duplicate_yarn_dependencies, eslint, gitaly, karma, pajamas, pipeline, prettier, product_intelligence, utility_css, vue_shared_documentation')
+ expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changelog, database, documentation, duplicate_yarn_dependencies, eslint, gitaly, pajamas, pipeline, prettier, product_intelligence, utility_css, vue_shared_documentation')
end
end
diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb
index 07daf249023..cfc0f9ff774 100644
--- a/tooling/danger/project_helper.rb
+++ b/tooling/danger/project_helper.rb
@@ -10,7 +10,6 @@ module Tooling
duplicate_yarn_dependencies
eslint
gitaly
- karma
pajamas
pipeline
prettier
diff --git a/vendor/assets/javascripts/jasmine-jquery.js b/vendor/assets/javascripts/jasmine-jquery.js
deleted file mode 100644
index a1f1e892c57..00000000000
--- a/vendor/assets/javascripts/jasmine-jquery.js
+++ /dev/null
@@ -1,854 +0,0 @@
-/* eslint-disable */
-/*
- Jasmine JQuery 3.0 patched version from this fork : https://github.com/cmrd-senya/jasmine-jquery/blob/jquery3/lib/jasmine-jquery.js
-*/
-/*!
-Jasmine-jQuery: a set of jQuery helpers for Jasmine tests.
-
-Version 2.1.1
-
-https://github.com/velesin/jasmine-jquery
-
-Copyright (c) 2010-2014 Wojciech Zawistowski, Travis Jeffery
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-(function (root, factory) {
- if (typeof module !== 'undefined' && module.exports) {
- // The line below is patched from jquery => jquery/dist/jquery
- // in order to load a jQuery with ajax, so that this testing library
- // doesn't break
- factory(root, root.jasmine, require('jquery/dist/jquery'));
- } else {
- factory(root, root.jasmine, root.jQuery);
- }
-}((function() {return this; })(), function (window, jasmine, $) { "use strict";
-
- jasmine.spiedEventsKey = function (selector, eventName) {
- for(var i = 0;; i++) {
- var key = [eventName, i].toString()
- if (data.spiedEvents[key] === undefined || data.spiedEvents[key].selector.is($(selector))) {
- return key
- }
- }
- }
-
- jasmine.getFixtures = function () {
- return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures()
- }
-
- jasmine.getStyleFixtures = function () {
- return jasmine.currentStyleFixtures_ = jasmine.currentStyleFixtures_ || new jasmine.StyleFixtures()
- }
-
- jasmine.Fixtures = function () {
- this.containerId = 'jasmine-fixtures'
- this.fixturesCache_ = {}
- this.fixturesPath = 'spec/javascripts/fixtures'
- }
-
- jasmine.Fixtures.prototype.set = function (html) {
- this.cleanUp()
- return this.createContainer_(html)
- }
-
- jasmine.Fixtures.prototype.appendSet= function (html) {
- this.addToContainer_(html)
- }
-
- jasmine.Fixtures.prototype.preload = function () {
- this.read.apply(this, arguments)
- }
-
- jasmine.Fixtures.prototype.load = function () {
- this.cleanUp()
- this.createContainer_(this.read.apply(this, arguments))
- }
-
- jasmine.Fixtures.prototype.appendLoad = function () {
- this.addToContainer_(this.read.apply(this, arguments))
- }
-
- jasmine.Fixtures.prototype.read = function () {
- var htmlChunks = []
- , fixtureUrls = arguments
-
- for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
- htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex]))
- }
-
- return htmlChunks.join('')
- }
-
- jasmine.Fixtures.prototype.clearCache = function () {
- this.fixturesCache_ = {}
- }
-
- jasmine.Fixtures.prototype.cleanUp = function () {
- $('#' + this.containerId).remove()
- }
-
- jasmine.Fixtures.prototype.sandbox = function (attributes) {
- var attributesToSet = attributes || {}
- return $('<div id="sandbox" />').attr(attributesToSet)
- }
-
- jasmine.Fixtures.prototype.createContainer_ = function (html) {
- var container = $('<div>')
- .attr('id', this.containerId)
- .html(html)
-
- $(document.body).append(container)
- return container
- }
-
- jasmine.Fixtures.prototype.addToContainer_ = function (html){
- var container = $(document.body).find('#'+this.containerId).append(html)
-
- if (!container.length) {
- this.createContainer_(html)
- }
- }
-
- jasmine.Fixtures.prototype.getFixtureHtml_ = function (url) {
- if (typeof this.fixturesCache_[url] === 'undefined') {
- this.loadFixtureIntoCache_(url)
- }
- return this.fixturesCache_[url]
- }
-
- jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) {
- var self = this
- , url = this.makeFixtureUrl_(relativeUrl)
- , htmlText = ''
- , request = $.ajax({
- async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
- cache: false,
- url: url,
- dataType: 'html',
- success: function (data, status, $xhr) {
- htmlText = $xhr.responseText
- }
- }).fail(function ($xhr, status, err) {
- throw new Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')')
- })
-
- var scripts = $($.parseHTML(htmlText, true)).find('script[src]') || [];
-
- scripts.each(function(){
- $.ajax({
- async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
- cache: false,
- dataType: 'script',
- url: $(this).attr('src'),
- success: function (data, status, $xhr) {
- htmlText += '<script>' + $xhr.responseText + '</script>'
- },
- error: function ($xhr, status, err) {
- throw new Error('Script could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')')
- }
- });
- })
-
- self.fixturesCache_[relativeUrl] = htmlText;
- }
-
- jasmine.Fixtures.prototype.makeFixtureUrl_ = function (relativeUrl){
- return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl
- }
-
- jasmine.Fixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) {
- return this[methodName].apply(this, passedArguments)
- }
-
-
- jasmine.StyleFixtures = function () {
- this.fixturesCache_ = {}
- this.fixturesNodes_ = []
- this.fixturesPath = 'spec/javascripts/fixtures'
- }
-
- jasmine.StyleFixtures.prototype.set = function (css) {
- this.cleanUp()
- this.createStyle_(css)
- }
-
- jasmine.StyleFixtures.prototype.appendSet = function (css) {
- this.createStyle_(css)
- }
-
- jasmine.StyleFixtures.prototype.preload = function () {
- this.read_.apply(this, arguments)
- }
-
- jasmine.StyleFixtures.prototype.load = function () {
- this.cleanUp()
- this.createStyle_(this.read_.apply(this, arguments))
- }
-
- jasmine.StyleFixtures.prototype.appendLoad = function () {
- this.createStyle_(this.read_.apply(this, arguments))
- }
-
- jasmine.StyleFixtures.prototype.cleanUp = function () {
- while(this.fixturesNodes_.length) {
- this.fixturesNodes_.pop().remove()
- }
- }
-
- jasmine.StyleFixtures.prototype.createStyle_ = function (html) {
- var styleText = $('<div></div>').html(html).text()
- , style = $('<style>' + styleText + '</style>')
-
- this.fixturesNodes_.push(style)
- $('head').append(style)
- }
-
- jasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache
- jasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read
- jasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_
- jasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_
- jasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_
- jasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_
-
- jasmine.getJSONFixtures = function () {
- return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures()
- }
-
- jasmine.JSONFixtures = function () {
- this.fixturesCache_ = {}
- this.fixturesPath = 'spec/javascripts/fixtures/json'
- }
-
- jasmine.JSONFixtures.prototype.load = function () {
- this.read.apply(this, arguments)
- return this.fixturesCache_
- }
-
- jasmine.JSONFixtures.prototype.read = function () {
- var fixtureUrls = arguments
-
- for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
- this.getFixtureData_(fixtureUrls[urlIndex])
- }
-
- return this.fixturesCache_
- }
-
- jasmine.JSONFixtures.prototype.clearCache = function () {
- this.fixturesCache_ = {}
- }
-
- jasmine.JSONFixtures.prototype.getFixtureData_ = function (url) {
- if (!this.fixturesCache_[url]) this.loadFixtureIntoCache_(url)
- return this.fixturesCache_[url]
- }
-
- jasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) {
- var self = this
- , url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl
-
- $.ajax({
- async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
- cache: false,
- dataType: 'json',
- url: url,
- success: function (data) {
- self.fixturesCache_[relativeUrl] = data
- },
- error: function ($xhr, status, err) {
- throw new Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')')
- }
- })
- }
-
- jasmine.JSONFixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) {
- return this[methodName].apply(this, passedArguments)
- }
-
- jasmine.jQuery = function () {}
-
- jasmine.jQuery.browserTagCaseIndependentHtml = function (html) {
- return $('<div/>').append(html).html()
- }
-
- jasmine.jQuery.elementToString = function (element) {
- return $(element).map(function () { return this.outerHTML; }).toArray().join(', ')
- }
-
- var data = {
- spiedEvents: {}
- , handlers: []
- }
-
- jasmine.jQuery.events = {
- spyOn: function (selector, eventName) {
- var handler = function (e) {
- var calls = (typeof data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] !== 'undefined') ? data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0
- data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = {
- selector: $(selector),
- args: jasmine.util.argsToArray(arguments),
- calls: ++calls
- }
- }
-
- $(selector).on(eventName, handler)
- data.handlers.push(handler)
-
- return {
- selector: selector,
- eventName: eventName,
- handler: handler,
- reset: function (){
- delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
- },
- calls: {
- count: function () {
- return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ?
- data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0;
- },
- any: function () {
- return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ?
- !!data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : false;
- }
- }
- }
- },
-
- args: function (selector, eventName) {
- var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].args
-
- if (!actualArgs) {
- throw "There is no spy for " + eventName + " on " + selector.toString() + ". Make sure to create a spy using spyOnEvent."
- }
-
- return actualArgs
- },
-
- wasTriggered: function (selector, eventName) {
- return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)])
- },
-
- wasTriggeredWith: function (selector, eventName, expectedArgs, util, customEqualityTesters) {
- var actualArgs = jasmine.jQuery.events.args(selector, eventName).slice(1)
-
- if (Object.prototype.toString.call(expectedArgs) !== '[object Array]')
- actualArgs = actualArgs[0]
-
- return util.equals(actualArgs, expectedArgs, customEqualityTesters)
- },
-
- wasPrevented: function (selector, eventName) {
- var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
- , args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args
- , e = args ? args[0] : undefined
-
- return e && e.isDefaultPrevented()
- },
-
- wasStopped: function (selector, eventName) {
- var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
- , args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args
- , e = args ? args[0] : undefined
-
- return e && e.isPropagationStopped()
- },
-
- cleanUp: function () {
- data.spiedEvents = {}
- data.handlers = []
- }
- }
-
- var hasProperty = function (actualValue, expectedValue) {
- if (expectedValue === undefined)
- return actualValue !== undefined
-
- return actualValue === expectedValue
- }
-
- beforeEach(function () {
- jasmine.addMatchers({
- toHaveClass: function () {
- return {
- compare: function (actual, className) {
- return { pass: $(actual).hasClass(className) }
- }
- }
- },
-
- toHaveCss: function () {
- return {
- compare: function (actual, css) {
- var stripCharsRegex = /[\s;\"\']/g
- for (var prop in css) {
- var value = css[prop]
- // see issue #147 on gh
- ;if ((value === 'auto') && ($(actual).get(0).style[prop] === 'auto')) continue
- var actualStripped = $(actual).css(prop).replace(stripCharsRegex, '')
- var valueStripped = value.replace(stripCharsRegex, '')
- if (actualStripped !== valueStripped) return { pass: false }
- }
- return { pass: true }
- }
- }
- },
-
- toBeVisible: function () {
- return {
- compare: function (actual) {
- return { pass: $(actual).is(':visible') }
- }
- }
- },
-
- toBeHidden: function () {
- return {
- compare: function (actual) {
- return { pass: $(actual).is(':hidden') }
- }
- }
- },
-
- toBeSelected: function () {
- return {
- compare: function (actual) {
- return { pass: $(actual).is(':selected') }
- }
- }
- },
-
- toBeChecked: function () {
- return {
- compare: function (actual) {
- return { pass: $(actual).is(':checked') }
- }
- }
- },
-
- toBeEmpty: function () {
- return {
- compare: function (actual) {
- return { pass: $(actual).is(':empty') }
- }
- }
- },
-
- toBeInDOM: function () {
- return {
- compare: function (actual) {
- return { pass: $.contains(document.documentElement, $(actual)[0]) }
- }
- }
- },
-
- toExist: function () {
- return {
- compare: function (actual) {
- return { pass: $(actual).length }
- }
- }
- },
-
- toHaveLength: function () {
- return {
- compare: function (actual, length) {
- return { pass: $(actual).length === length }
- }
- }
- },
-
- toHaveAttr: function () {
- return {
- compare: function (actual, attributeName, expectedAttributeValue) {
- return { pass: hasProperty($(actual).attr(attributeName), expectedAttributeValue) }
- }
- }
- },
-
- toHaveProp: function () {
- return {
- compare: function (actual, propertyName, expectedPropertyValue) {
- return { pass: hasProperty($(actual).prop(propertyName), expectedPropertyValue) }
- }
- }
- },
-
- toHaveId: function () {
- return {
- compare: function (actual, id) {
- return { pass: $(actual).attr('id') == id }
- }
- }
- },
-
- toHaveHtml: function () {
- return {
- compare: function (actual, html) {
- return { pass: $(actual).html() == jasmine.jQuery.browserTagCaseIndependentHtml(html) }
- }
- }
- },
-
- toContainHtml: function () {
- return {
- compare: function (actual, html) {
- var actualHtml = $(actual).html()
- , expectedHtml = jasmine.jQuery.browserTagCaseIndependentHtml(html)
-
- return { pass: (actualHtml.indexOf(expectedHtml) >= 0) }
- }
- }
- },
-
- toHaveText: function () {
- return {
- compare: function (actual, text) {
- var actualText = $(actual).text()
- var trimmedText = $.trim(actualText)
-
- if (text && $.isFunction(text.test)) {
- return { pass: text.test(actualText) || text.test(trimmedText) }
- } else {
- return { pass: (actualText == text || trimmedText == text) }
- }
- }
- }
- },
-
- toContainText: function () {
- return {
- compare: function (actual, text) {
- var trimmedText = $.trim($(actual).text())
-
- if (text && $.isFunction(text.test)) {
- return { pass: text.test(trimmedText) }
- } else {
- return { pass: trimmedText.indexOf(text) != -1 }
- }
- }
- }
- },
-
- toHaveValue: function () {
- return {
- compare: function (actual, value) {
- return { pass: $(actual).val() === value }
- }
- }
- },
-
- toHaveData: function () {
- return {
- compare: function (actual, key, expectedValue) {
- return { pass: hasProperty($(actual).data(key), expectedValue) }
- }
- }
- },
-
- toContainElement: function () {
- return {
- compare: function (actual, selector) {
- return { pass: $(actual).find(selector).length }
- }
- }
- },
-
- toBeMatchedBy: function () {
- return {
- compare: function (actual, selector) {
- return { pass: $(actual).filter(selector).length }
- }
- }
- },
-
- toBeDisabled: function () {
- return {
- compare: function (actual, selector) {
- return { pass: $(actual).is(':disabled') }
- }
- }
- },
-
- toBeFocused: function (selector) {
- return {
- compare: function (actual, selector) {
- return { pass: $(actual)[0] === $(actual)[0].ownerDocument.activeElement }
- }
- }
- },
-
- toHandle: function () {
- return {
- compare: function (actual, event) {
- if ( !actual || actual.length === 0 ) return { pass: false };
- var events = $._data($(actual).get(0), "events")
-
- if (!events || !event || typeof event !== "string") {
- return { pass: false }
- }
-
- var namespaces = event.split(".")
- , eventType = namespaces.shift()
- , sortedNamespaces = namespaces.slice(0).sort()
- , namespaceRegExp = new RegExp("(^|\\.)" + sortedNamespaces.join("\\.(?:.*\\.)?") + "(\\.|$)")
-
- if (events[eventType] && namespaces.length) {
- for (var i = 0; i < events[eventType].length; i++) {
- var namespace = events[eventType][i].namespace
-
- if (namespaceRegExp.test(namespace))
- return { pass: true }
- }
- } else {
- return { pass: (events[eventType] && events[eventType].length > 0) }
- }
-
- return { pass: false }
- }
- }
- },
-
- toHandleWith: function () {
- return {
- compare: function (actual, eventName, eventHandler) {
- if ( !actual || actual.length === 0 ) return { pass: false };
- var normalizedEventName = eventName.split('.')[0]
- , stack = $._data($(actual).get(0), "events")[normalizedEventName]
-
- for (var i = 0; i < stack.length; i++) {
- if (stack[i].handler == eventHandler) return { pass: true }
- }
-
- return { pass: false }
- }
- }
- },
-
- toHaveBeenTriggeredOn: function () {
- return {
- compare: function (actual, selector) {
- var result = { pass: jasmine.jQuery.events.wasTriggered(selector, actual) }
-
- result.message = result.pass ?
- "Expected event " + $(actual) + " not to have been triggered on " + selector :
- "Expected event " + $(actual) + " to have been triggered on " + selector
-
- return result;
- }
- }
- },
-
- toHaveBeenTriggered: function (){
- return {
- compare: function (actual) {
- var eventName = actual.eventName
- , selector = actual.selector
- , result = { pass: jasmine.jQuery.events.wasTriggered(selector, eventName) }
-
- result.message = result.pass ?
- "Expected event " + eventName + " not to have been triggered on " + selector :
- "Expected event " + eventName + " to have been triggered on " + selector
-
- return result
- }
- }
- },
-
- toHaveBeenTriggeredOnAndWith: function (j$, customEqualityTesters) {
- return {
- compare: function (actual, selector, expectedArgs) {
- var wasTriggered = jasmine.jQuery.events.wasTriggered(selector, actual)
- , result = { pass: wasTriggered && jasmine.jQuery.events.wasTriggeredWith(selector, actual, expectedArgs, j$, customEqualityTesters) }
-
- if (wasTriggered) {
- var actualArgs = jasmine.jQuery.events.args(selector, actual, expectedArgs)[1]
- result.message = result.pass ?
- "Expected event " + actual + " not to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) :
- "Expected event " + actual + " to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs)
-
- } else {
- // todo check on this
- result.message = result.pass ?
- "Expected event " + actual + " not to have been triggered on " + selector :
- "Expected event " + actual + " to have been triggered on " + selector
- }
-
- return result
- }
- }
- },
-
- toHaveBeenPreventedOn: function () {
- return {
- compare: function (actual, selector) {
- var result = { pass: jasmine.jQuery.events.wasPrevented(selector, actual) }
-
- result.message = result.pass ?
- "Expected event " + actual + " not to have been prevented on " + selector :
- "Expected event " + actual + " to have been prevented on " + selector
-
- return result
- }
- }
- },
-
- toHaveBeenPrevented: function () {
- return {
- compare: function (actual) {
- var eventName = actual.eventName
- , selector = actual.selector
- , result = { pass: jasmine.jQuery.events.wasPrevented(selector, eventName) }
-
- result.message = result.pass ?
- "Expected event " + eventName + " not to have been prevented on " + selector :
- "Expected event " + eventName + " to have been prevented on " + selector
-
- return result
- }
- }
- },
-
- toHaveBeenStoppedOn: function () {
- return {
- compare: function (actual, selector) {
- var result = { pass: jasmine.jQuery.events.wasStopped(selector, actual) }
-
- result.message = result.pass ?
- "Expected event " + actual + " not to have been stopped on " + selector :
- "Expected event " + actual + " to have been stopped on " + selector
-
- return result;
- }
- }
- },
-
- toHaveBeenStopped: function () {
- return {
- compare: function (actual) {
- var eventName = actual.eventName
- , selector = actual.selector
- , result = { pass: jasmine.jQuery.events.wasStopped(selector, eventName) }
-
- result.message = result.pass ?
- "Expected event " + eventName + " not to have been stopped on " + selector :
- "Expected event " + eventName + " to have been stopped on " + selector
-
- return result
- }
- }
- }
- })
-
- jasmine.getEnv().addCustomEqualityTester(function(a, b) {
- if (a && b) {
- if (a instanceof $ || jasmine.isDomNode(a)) {
- var $a = $(a)
-
- if (b instanceof $)
- return $a.length == b.length && a.is(b)
-
- return $a.is(b);
- }
-
- if (b instanceof $ || jasmine.isDomNode(b)) {
- var $b = $(b)
-
- if (a instanceof $)
- return a.length == $b.length && $b.is(a)
-
- return $(b).is(a);
- }
- }
- })
-
- jasmine.getEnv().addCustomEqualityTester(function (a, b) {
- if (a instanceof $ && b instanceof $ && a.size() == b.size())
- return a.is(b)
- })
- })
-
- afterEach(function () {
- jasmine.getFixtures().cleanUp()
- jasmine.getStyleFixtures().cleanUp()
- jasmine.jQuery.events.cleanUp()
- })
-
- window.readFixtures = function () {
- return jasmine.getFixtures().proxyCallTo_('read', arguments)
- }
-
- window.preloadFixtures = function () {
- jasmine.getFixtures().proxyCallTo_('preload', arguments)
- }
-
- window.loadFixtures = function () {
- jasmine.getFixtures().proxyCallTo_('load', arguments)
- }
-
- window.appendLoadFixtures = function () {
- jasmine.getFixtures().proxyCallTo_('appendLoad', arguments)
- }
-
- window.setFixtures = function (html) {
- return jasmine.getFixtures().proxyCallTo_('set', arguments)
- }
-
- window.appendSetFixtures = function () {
- jasmine.getFixtures().proxyCallTo_('appendSet', arguments)
- }
-
- window.sandbox = function (attributes) {
- return jasmine.getFixtures().sandbox(attributes)
- }
-
- window.spyOnEvent = function (selector, eventName) {
- return jasmine.jQuery.events.spyOn(selector, eventName)
- }
-
- window.preloadStyleFixtures = function () {
- jasmine.getStyleFixtures().proxyCallTo_('preload', arguments)
- }
-
- window.loadStyleFixtures = function () {
- jasmine.getStyleFixtures().proxyCallTo_('load', arguments)
- }
-
- window.appendLoadStyleFixtures = function () {
- jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments)
- }
-
- window.setStyleFixtures = function (html) {
- jasmine.getStyleFixtures().proxyCallTo_('set', arguments)
- }
-
- window.appendSetStyleFixtures = function (html) {
- jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments)
- }
-
- window.loadJSONFixtures = function () {
- return jasmine.getJSONFixtures().proxyCallTo_('load', arguments)
- }
-
- window.getJSONFixture = function (url) {
- return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url]
- }
-}));
diff --git a/vendor/aws/cloudformation/eks_cluster.yaml b/vendor/aws/cloudformation/eks_cluster.yaml
index 798eaeae799..8d93734fd46 100644
--- a/vendor/aws/cloudformation/eks_cluster.yaml
+++ b/vendor/aws/cloudformation/eks_cluster.yaml
@@ -21,7 +21,7 @@ Parameters:
NodeImageIdSSMParam:
Type: "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>"
- Default: /aws/service/eks/optimized-ami/1.15/amazon-linux-2/recommended/image_id
+ Default: /aws/service/eks/optimized-ami/1.17/amazon-linux-2/recommended/image_id
Description: AWS Systems Manager Parameter Store parameter of the AMI ID for the worker node instances.
NodeInstanceType:
diff --git a/yarn.lock b/yarn.lock
index 40fadbc1ccd..e03f167e73a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -42,7 +42,7 @@
semver "^6.3.0"
source-map "^0.5.0"
-"@babel/generator@^7.15.0", "@babel/generator@^7.4.0":
+"@babel/generator@^7.15.0":
version "7.15.0"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.0.tgz#a7d0c172e0d814974bad5aa77ace543b97917f15"
integrity sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==
@@ -264,7 +264,7 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
-"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.14.5", "@babel/parser@^7.15.0", "@babel/parser@^7.4.3":
+"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.6", "@babel/parser@^7.14.5", "@babel/parser@^7.15.0":
version "7.15.3"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.3.tgz#3416d9bea748052cfcb63dbcc27368105b1ed862"
integrity sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==
@@ -863,7 +863,7 @@
resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.10.2.tgz#49dbbadcbc4b199df064d7d8b3e21c915b84abdb"
integrity sha512-PNQuj9oQH6BL/3l9iiL8hJLQwX14woA2/FHcPtNIZAc7IgFZYJdtMBMXiy4xcefADHTSvoBnmc2AybrHRW1IKQ==
-"@babel/template@^7.10.1", "@babel/template@^7.14.5", "@babel/template@^7.3.3", "@babel/template@^7.4.0":
+"@babel/template@^7.10.1", "@babel/template@^7.14.5", "@babel/template@^7.3.3":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4"
integrity sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==
@@ -872,7 +872,7 @@
"@babel/parser" "^7.14.5"
"@babel/types" "^7.14.5"
-"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.10.1", "@babel/traverse@^7.15.0", "@babel/traverse@^7.4.3":
+"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.10.1", "@babel/traverse@^7.15.0":
version "7.15.0"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.0.tgz#4cca838fd1b2a03283c1f38e141f639d60b3fc98"
integrity sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==
@@ -887,7 +887,7 @@
debug "^4.1.0"
globals "^11.1.0"
-"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.10.1", "@babel/types@^7.10.2", "@babel/types@^7.14.5", "@babel/types@^7.14.8", "@babel/types@^7.15.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.0", "@babel/types@^7.4.4":
+"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.10.1", "@babel/types@^7.10.2", "@babel/types@^7.14.5", "@babel/types@^7.14.8", "@babel/types@^7.15.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
version "7.15.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.0.tgz#61af11f2286c4e9c69ca8deb5f4375a73c72dcbd"
integrity sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==
@@ -2271,11 +2271,6 @@ acorn@^8.0.4:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.0.tgz#52311fd7037ae119cbb134309e901aa46295b3fe"
integrity sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA==
-after@0.8.2:
- version "0.8.2"
- resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
- integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
-
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
@@ -2500,13 +2495,6 @@ apollo-utilities@1.3.4, apollo-utilities@^1.3.0, apollo-utilities@^1.3.4:
ts-invariant "^0.4.0"
tslib "^1.10.0"
-append-transform@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab"
- integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==
- dependencies:
- default-require-extensions "^2.0.0"
-
aproba@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -2604,11 +2592,6 @@ array.prototype.flat@^1.2.3:
define-properties "^1.1.3"
es-abstract "^1.18.0-next.1"
-arraybuffer.slice@~0.0.7:
- version "0.0.7"
- resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
- integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==
-
arrify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
@@ -2848,11 +2831,6 @@ babylon@7.0.0-beta.19:
resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.19.tgz#e928c7e807e970e0536b078ab3e0c48f9e052503"
integrity sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==
-backo2@1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
- integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
-
bail@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776"
@@ -2863,21 +2841,11 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
-base64-arraybuffer@0.1.5:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
- integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg=
-
base64-js@^1.0.2, base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
-base64id@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6"
- integrity sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=
-
base@^0.11.1:
version "0.11.2"
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
@@ -2903,13 +2871,6 @@ bcrypt-pbkdf@^1.0.0:
dependencies:
tweetnacl "^0.14.3"
-better-assert@~1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522"
- integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=
- dependencies:
- callsite "1.0.0"
-
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@@ -2934,12 +2895,7 @@ bl@^4.1.0:
inherits "^2.0.4"
readable-stream "^3.4.0"
-blob@0.0.4:
- version "0.0.4"
- resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921"
- integrity sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=
-
-bluebird@^3.1.1, bluebird@^3.3.0, bluebird@^3.5.5, bluebird@~3.5.0:
+bluebird@^3.1.1, bluebird@^3.5.5, bluebird@~3.5.0:
version "3.5.5"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==
@@ -2949,7 +2905,7 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.9:
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
-body-parser@1.19.0, body-parser@^1.16.1:
+body-parser@1.19.0:
version "1.19.0"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
@@ -3036,7 +2992,7 @@ braces@^2.3.1:
split-string "^3.0.2"
to-regex "^3.0.1"
-braces@^3.0.1, braces@^3.0.2, braces@~3.0.2:
+braces@^3.0.1, braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
@@ -3278,11 +3234,6 @@ call-me-maybe@^1.0.1:
resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
integrity sha1-JtII6onje1y95gJQoV8DHBak1ms=
-callsite@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
- integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA=
-
callsites@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3"
@@ -3331,7 +3282,7 @@ catharsis@~0.8.9:
dependencies:
underscore-contrib "~0.3.0"
-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
+chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -3410,7 +3361,7 @@ cheerio@^1.0.0-rc.9:
parse5-htmlparser2-tree-adapter "^6.0.1"
tslib "^2.2.0"
-"chokidar@>=3.0.0 <4.0.0", chokidar@^2.1.8, chokidar@^3.0.0, chokidar@^3.2.2, chokidar@^3.4.0, chokidar@^3.4.1:
+"chokidar@>=3.0.0 <4.0.0", chokidar@^2.1.8, chokidar@^3.2.2, chokidar@^3.4.0, chokidar@^3.4.1:
version "3.4.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8"
integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==
@@ -3639,7 +3590,7 @@ colorette@^1.2.1, colorette@^1.2.2:
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
-colors@^1.1.0, colors@^1.1.2:
+colors@^1.1.2:
version "1.4.0"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
@@ -3651,7 +3602,7 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
-commander@2, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, commander@~2.20.0:
+commander@2, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
@@ -3666,26 +3617,11 @@ commondir@^1.0.1:
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
-compare-versions@^3.4.0:
- version "3.5.1"
- resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.5.1.tgz#26e1f5cf0d48a77eced5046b9f67b6b61075a393"
- integrity sha512-9fGPIB7C6AyM18CJJBHt5EnCZDG3oiTJYy0NjfIAGjKpzv0tkxWko7TNQHF5ymqm7IH03tqmeuBxtvD+Izh6mg==
-
-component-bind@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
- integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=
-
-component-emitter@1.2.1, component-emitter@^1.2.1:
+component-emitter@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=
-component-inherit@0.0.3:
- version "0.0.3"
- resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
- integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=
-
compressible@~2.0.16:
version "2.0.17"
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1"
@@ -3771,16 +3707,6 @@ connect-history-api-fallback@^1.6.0:
resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"
integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==
-connect@^3.6.0:
- version "3.6.6"
- resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.6.tgz#09eff6c55af7236e137135a72574858b6786f524"
- integrity sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=
- dependencies:
- debug "2.6.9"
- finalhandler "1.1.0"
- parseurl "~1.3.2"
- utils-merge "1.0.1"
-
consola@^2.15.0:
version "2.15.3"
resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550"
@@ -3834,11 +3760,6 @@ cookie-signature@1.0.6:
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
-cookie@0.3.1:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
- integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
-
cookie@0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
@@ -3898,7 +3819,7 @@ core-js-pure@^3.0.0:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
-core-js@^3.1.3, core-js@^3.17.2:
+core-js@^3.17.2:
version "3.17.2"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.17.2.tgz#f960eae710dc62c29cca93d5332e3660e289db10"
integrity sha512-XkbXqhcXeMHPRk2ItS+zQYliAMilea2euoMsnpRRdDad6b2VY6CQQcwz1K8AnWesfw4p165RzY0bTnr3UrbYiA==
@@ -4107,11 +4028,6 @@ cssstyle@^2.2.0:
dependencies:
cssom "~0.3.6"
-custom-event@~1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425"
- integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=
-
custom-jquery-matchers@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/custom-jquery-matchers/-/custom-jquery-matchers-2.1.0.tgz#e5988fa9715c416b0986b372563f872d9e91e024"
@@ -4412,11 +4328,6 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
-date-format@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/date-format/-/date-format-2.1.0.tgz#31d5b5ea211cf5fd764cd38baf9d033df7e125cf"
- integrity sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==
-
date-now@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
@@ -4439,7 +4350,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
dependencies:
ms "2.0.0"
-debug@3.1.0, debug@~3.1.0:
+debug@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
@@ -4523,13 +4434,6 @@ default-gateway@^4.2.0:
execa "^1.0.0"
ip-regex "^2.1.0"
-default-require-extensions@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7"
- integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=
- dependencies:
- strip-bom "^3.0.0"
-
defaults@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
@@ -4632,11 +4536,6 @@ detect-node@^2.0.4:
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
-di@^0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
- integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=
-
diff-sequences@^26.5.0:
version "26.5.0"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.5.0.tgz#ef766cf09d43ed40406611f11c6d8d9dd8b2fefd"
@@ -4713,16 +4612,6 @@ dom-event-types@^1.0.0:
resolved "https://registry.yarnpkg.com/dom-event-types/-/dom-event-types-1.0.0.tgz#5830a0a29e1bf837fe50a70cd80a597232813cae"
integrity sha512-2G2Vwi2zXTHBGqXHsJ4+ak/iP0N8Ar+G8a7LiD2oup5o4sQWytwqqrZu/O6hIMV0KMID2PL69OhpshLO0n7UJQ==
-dom-serialize@^2.2.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b"
- integrity sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=
- dependencies:
- custom-event "~1.0.0"
- ent "~2.2.0"
- extend "^3.0.0"
- void-elements "^2.0.0"
-
dom-serializer@0:
version "0.2.2"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
@@ -4918,7 +4807,7 @@ emojis-list@^3.0.0:
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
-encodeurl@~1.0.1, encodeurl@~1.0.2:
+encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
@@ -4935,46 +4824,6 @@ ends-with@^0.2.0:
resolved "https://registry.yarnpkg.com/ends-with/-/ends-with-0.2.0.tgz#2f9da98d57a50cfda4571ce4339000500f4e6b8a"
integrity sha1-L52pjVelDP2kVxzkM5AAUA9Oa4o=
-engine.io-client@~3.2.0:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36"
- integrity sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==
- dependencies:
- component-emitter "1.2.1"
- component-inherit "0.0.3"
- debug "~3.1.0"
- engine.io-parser "~2.1.1"
- has-cors "1.1.0"
- indexof "0.0.1"
- parseqs "0.0.5"
- parseuri "0.0.5"
- ws "~3.3.1"
- xmlhttprequest-ssl "~1.5.4"
- yeast "0.1.2"
-
-engine.io-parser@~2.1.0, engine.io-parser@~2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.2.tgz#4c0f4cff79aaeecbbdcfdea66a823c6085409196"
- integrity sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==
- dependencies:
- after "0.8.2"
- arraybuffer.slice "~0.0.7"
- base64-arraybuffer "0.1.5"
- blob "0.0.4"
- has-binary2 "~1.0.2"
-
-engine.io@~3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.0.tgz#54332506f42f2edc71690d2f2a42349359f3bf7d"
- integrity sha512-mRbgmAtQ4GAlKwuPnnAvXXwdPhEx+jkc0OBCLrXuD/CRvwNK3AxRSnqK4FSqmAMRRHryVJP8TopOvmEaA64fKw==
- dependencies:
- accepts "~1.3.4"
- base64id "1.0.0"
- cookie "0.3.1"
- debug "~3.1.0"
- engine.io-parser "~2.1.0"
- ws "~3.3.1"
-
enhanced-resolve@^0.9.1:
version "0.9.1"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e"
@@ -5000,11 +4849,6 @@ enquirer@^2.3.5:
dependencies:
ansi-colors "^4.1.1"
-ent@~2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
- integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0=
-
entities@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
@@ -5688,14 +5532,6 @@ file-loader@^6.2.0:
loader-utils "^2.0.0"
schema-utils "^3.0.0"
-fileset@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0"
- integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=
- dependencies:
- glob "^7.0.3"
- minimatch "^3.0.3"
-
fill-range@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
@@ -5713,19 +5549,6 @@ fill-range@^7.0.1:
dependencies:
to-regex-range "^5.0.1"
-finalhandler@1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5"
- integrity sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=
- dependencies:
- debug "2.6.9"
- encodeurl "~1.0.1"
- escape-html "~1.0.3"
- on-finished "~2.3.0"
- parseurl "~1.3.2"
- statuses "~1.3.1"
- unpipe "~1.0.0"
-
finalhandler@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
@@ -5802,11 +5625,6 @@ flat-cache@^3.0.4:
flatted "^3.1.0"
rimraf "^3.0.2"
-flatted@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916"
- integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==
-
flatted@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469"
@@ -5879,15 +5697,6 @@ from2@^2.1.0:
inherits "^2.0.1"
readable-stream "^2.0.0"
-fs-extra@^7.0.1:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
- integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
- dependencies:
- graceful-fs "^4.1.2"
- jsonfile "^4.0.0"
- universalify "^0.1.0"
-
fs-extra@^8.1:
version "8.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
@@ -6204,17 +6013,6 @@ handle-thing@^2.0.0:
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754"
integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==
-handlebars@^4.1.2:
- version "4.7.2"
- resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.2.tgz#01127b3840156a0927058779482031afe0e730d7"
- integrity sha512-4PwqDL2laXtTWZghzzCtunQUTLbo31pcCJrd/B/9JP8XbhVzpS5ZXuKqlOzsd1rtcaLo4KqAn8nl8mkknS4MHw==
- dependencies:
- neo-async "^2.6.0"
- optimist "^0.6.1"
- source-map "^0.6.1"
- optionalDependencies:
- uglify-js "^3.1.4"
-
har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
@@ -6233,18 +6031,6 @@ hard-rejection@^2.1.0:
resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==
-has-binary2@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.2.tgz#e83dba49f0b9be4d026d27365350d9f03f54be98"
- integrity sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=
- dependencies:
- isarray "2.0.1"
-
-has-cors@1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
- integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=
-
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@@ -6477,7 +6263,7 @@ http-proxy-middleware@0.19.1:
lodash "^4.17.11"
micromatch "^3.1.10"
-http-proxy@^1.13.0, http-proxy@^1.17.0:
+http-proxy@^1.17.0:
version "1.18.1"
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==
@@ -6616,11 +6402,6 @@ indexes-of@^1.0.1:
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc=
-indexof@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
- integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=
-
infer-owner@^1.0.3, infer-owner@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
@@ -7056,16 +6837,6 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
-isarray@2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"
- integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=
-
-isbinaryfile@^3.0.0:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621"
- integrity sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=
-
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@@ -7088,55 +6859,11 @@ isstream@~0.1.2:
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
-istanbul-api@^2.1.6:
- version "2.1.6"
- resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.1.6.tgz#d61702a9d1c66ad89d92e66d401e16b0bda4a35f"
- integrity sha512-x0Eicp6KsShG1k1rMgBAi/1GgY7kFGEBwQpw3PXGEmu+rBcBNhqU8g2DgY9mlepAsLPzrzrbqSgCGANnki4POA==
- dependencies:
- async "^2.6.2"
- compare-versions "^3.4.0"
- fileset "^2.0.3"
- istanbul-lib-coverage "^2.0.5"
- istanbul-lib-hook "^2.0.7"
- istanbul-lib-instrument "^3.3.0"
- istanbul-lib-report "^2.0.8"
- istanbul-lib-source-maps "^3.0.6"
- istanbul-reports "^2.2.4"
- js-yaml "^3.13.1"
- make-dir "^2.1.0"
- minimatch "^3.0.4"
- once "^1.4.0"
-
-istanbul-lib-coverage@^2.0.5:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49"
- integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==
-
istanbul-lib-coverage@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec"
integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==
-istanbul-lib-hook@^2.0.7:
- version "2.0.7"
- resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133"
- integrity sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==
- dependencies:
- append-transform "^1.0.0"
-
-istanbul-lib-instrument@^3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630"
- integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==
- dependencies:
- "@babel/generator" "^7.4.0"
- "@babel/parser" "^7.4.3"
- "@babel/template" "^7.4.0"
- "@babel/traverse" "^7.4.3"
- "@babel/types" "^7.4.0"
- istanbul-lib-coverage "^2.0.5"
- semver "^6.0.0"
-
istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d"
@@ -7147,15 +6874,6 @@ istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3:
istanbul-lib-coverage "^3.0.0"
semver "^6.3.0"
-istanbul-lib-report@^2.0.8:
- version "2.0.8"
- resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33"
- integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==
- dependencies:
- istanbul-lib-coverage "^2.0.5"
- make-dir "^2.1.0"
- supports-color "^6.1.0"
-
istanbul-lib-report@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6"
@@ -7165,17 +6883,6 @@ istanbul-lib-report@^3.0.0:
make-dir "^3.0.0"
supports-color "^7.1.0"
-istanbul-lib-source-maps@^3.0.6:
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8"
- integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==
- dependencies:
- debug "^4.1.1"
- istanbul-lib-coverage "^2.0.5"
- make-dir "^2.1.0"
- rimraf "^2.6.3"
- source-map "^0.6.1"
-
istanbul-lib-source-maps@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9"
@@ -7185,13 +6892,6 @@ istanbul-lib-source-maps@^4.0.0:
istanbul-lib-coverage "^3.0.0"
source-map "^0.6.1"
-istanbul-reports@^2.2.4:
- version "2.2.6"
- resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af"
- integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==
- dependencies:
- handlebars "^4.1.2"
-
istanbul-reports@^3.0.0, istanbul-reports@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b"
@@ -7878,95 +7578,6 @@ jszip@^3.1.3:
pako "~1.0.2"
readable-stream "~2.0.6"
-karma-chrome-launcher@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.0.0.tgz#5c3a7f877a304e90781c28fcd9a49e334a890f42"
- integrity sha512-u/PnVgDOP97AUe/gJeABlC6Wa6aQ83MZsm0JgsJQ5bGQ9XcXON/7b2aRhl59A62Zom+q3PFveBkczc7E1RT7TA==
- dependencies:
- which "^1.2.1"
-
-karma-coverage-istanbul-reporter@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.1.0.tgz#5f1bcc13c5e14ee1d91821ee8946861674f54c75"
- integrity sha512-UH0mXPJFJyK5uiK7EkwGtQ8f30lCBAfqRResnZ4pzLJ04SOp4SPlYkmwbbZ6iVJ6sQFVzlDUXlntBEsLRdgZpg==
- dependencies:
- istanbul-api "^2.1.6"
- minimatch "^3.0.4"
-
-karma-jasmine@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-1.1.2.tgz#394f2b25ffb4a644b9ada6f22d443e2fd08886c3"
- integrity sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=
-
-karma-junit-reporter@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/karma-junit-reporter/-/karma-junit-reporter-1.2.0.tgz#4f9c40cedfb1a395f8aef876abf96189917c6396"
- integrity sha1-T5xAzt+xo5X4rvh2q/lhiZF8Y5Y=
- dependencies:
- path-is-absolute "^1.0.0"
- xmlbuilder "8.2.2"
-
-karma-mocha-reporter@^2.2.5:
- version "2.2.5"
- resolved "https://registry.yarnpkg.com/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz#15120095e8ed819186e47a0b012f3cd741895560"
- integrity sha1-FRIAlejtgZGG5HoLAS8810GJVWA=
- dependencies:
- chalk "^2.1.0"
- log-symbols "^2.1.0"
- strip-ansi "^4.0.0"
-
-karma-sourcemap-loader@^0.3.7:
- version "0.3.7"
- resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz#91322c77f8f13d46fed062b042e1009d4c4505d8"
- integrity sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=
- dependencies:
- graceful-fs "^4.1.2"
-
-karma-webpack@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-4.0.2.tgz#23219bd95bdda853e3073d3874d34447c77bced0"
- integrity sha512-970/okAsdUOmiMOCY8sb17A2I8neS25Ad9uhyK3GHgmRSIFJbDcNEFE8dqqUhNe9OHiCC9k3DMrSmtd/0ymP1A==
- dependencies:
- clone-deep "^4.0.1"
- loader-utils "^1.1.0"
- neo-async "^2.6.1"
- schema-utils "^1.0.0"
- source-map "^0.7.3"
- webpack-dev-middleware "^3.7.0"
-
-karma@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/karma/-/karma-4.2.0.tgz#27e88b310cde090d016980ff5444e3a239196fca"
- integrity sha512-fmCuxN1rwJxTdZfOXK5LjlmS4Ana/OvzNMpkyLL/TLE8hmgSkpVpMYQ7RTVa8TNKRVQDZNl5W1oF5cfKfgIMlA==
- dependencies:
- bluebird "^3.3.0"
- body-parser "^1.16.1"
- braces "^3.0.2"
- chokidar "^3.0.0"
- colors "^1.1.0"
- connect "^3.6.0"
- core-js "^3.1.3"
- di "^0.0.1"
- dom-serialize "^2.2.0"
- flatted "^2.0.0"
- glob "^7.1.1"
- graceful-fs "^4.1.2"
- http-proxy "^1.13.0"
- isbinaryfile "^3.0.0"
- lodash "^4.17.11"
- log4js "^4.0.0"
- mime "^2.3.1"
- minimatch "^3.0.2"
- optimist "^0.6.1"
- qjobs "^1.1.4"
- range-parser "^1.2.0"
- rimraf "^2.6.0"
- safe-buffer "^5.0.1"
- socket.io "2.1.1"
- source-map "^0.6.1"
- tmp "0.0.33"
- useragent "2.3.0"
-
katex@^0.13.2:
version "0.13.2"
resolved "https://registry.yarnpkg.com/katex/-/katex-0.13.2.tgz#4075b9144e6af992ec9a4b772fa3754763be5f26"
@@ -8319,13 +7930,6 @@ lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
-log-symbols@^2.1.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
- integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
- dependencies:
- chalk "^2.0.1"
-
log-symbols@^4.0.0, log-symbols@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
@@ -8334,17 +7938,6 @@ log-symbols@^4.0.0, log-symbols@^4.1.0:
chalk "^4.1.0"
is-unicode-supported "^0.1.0"
-log4js@^4.0.0:
- version "4.5.1"
- resolved "https://registry.yarnpkg.com/log4js/-/log4js-4.5.1.tgz#e543625e97d9e6f3e6e7c9fc196dd6ab2cae30b5"
- integrity sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==
- dependencies:
- date-format "^2.0.0"
- debug "^4.1.1"
- flatted "^2.0.0"
- rfdc "^1.1.4"
- streamroller "^1.0.6"
-
loglevel@^1.6.8:
version "1.7.1"
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197"
@@ -8380,7 +7973,7 @@ lowlight@^1.17.0, lowlight@^1.20.0:
fault "^1.0.0"
highlight.js "~10.7.0"
-lru-cache@4.1.x, lru-cache@^4.1.2, lru-cache@^4.1.5:
+lru-cache@^4.1.2, lru-cache@^4.1.5:
version "4.1.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
@@ -8754,7 +8347,7 @@ minimalistic-crypto-utils@^1.0.1:
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
-minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.4:
+minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@@ -8775,11 +8368,6 @@ minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.5:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
-minimist@~0.0.1:
- version "0.0.8"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
- integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
-
minipass-collect@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617"
@@ -8995,7 +8583,7 @@ negotiator@0.6.2:
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
-neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1:
+neo-async@^2.5.0, neo-async@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c"
integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==
@@ -9202,11 +8790,6 @@ object-assign@^4.0.1:
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
-object-component@0.0.3:
- version "0.0.3"
- resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291"
- integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=
-
object-copy@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
@@ -9320,14 +8903,6 @@ optimism@^0.10.0:
dependencies:
"@wry/context" "^0.4.0"
-optimist@^0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
- integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY=
- dependencies:
- minimist "~0.0.1"
- wordwrap "~0.0.2"
-
optionator@^0.8.1:
version "0.8.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
@@ -9593,20 +9168,6 @@ parse5@5.1.1:
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==
-parseqs@0.0.5:
- version "0.0.5"
- resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
- integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=
- dependencies:
- better-assert "~1.0.0"
-
-parseuri@0.0.5:
- version "0.0.5"
- resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a"
- integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=
- dependencies:
- better-assert "~1.0.0"
-
parseurl@~1.3.2, parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
@@ -10070,10 +9631,10 @@ prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.1.2, prosemirror-keymap@^1.1.3,
prosemirror-state "^1.0.0"
w3c-keyname "^2.2.0"
-prosemirror-markdown@^1.5.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/prosemirror-markdown/-/prosemirror-markdown-1.5.1.tgz#877c7faea2225d3c52e988599bbe4457bcb3190f"
- integrity sha512-QvucPHx+gKOQW1SETKUysrful9VBjKqpCFmPotgLfVZ3BdQEGy/NEIFhaXXo3TcuW316MMnKfA90K7GE5I7z8A==
+prosemirror-markdown@^1.5.2:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/prosemirror-markdown/-/prosemirror-markdown-1.5.2.tgz#f188ad14caa8c2f499b4d3eb6082e19f1d9d366e"
+ integrity sha512-e9rVnRULVACEjCvIBOj5P2dGTE/nz8kKspA/GWZXVgtQgqeJEvQ+tUNeZkeRZJ2/I3XPzuWjeoWnwJmkMnIKrg==
dependencies:
markdown-it "^10.0.0"
prosemirror-model "^1.0.0"
@@ -10244,11 +9805,6 @@ purgecss@^4.0.3:
postcss "^8.2.1"
postcss-selector-parser "^6.0.2"
-qjobs@^1.1.4:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071"
- integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==
-
qs@6.7.0:
version "6.7.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
@@ -10294,7 +9850,7 @@ randomfill@^1.0.3:
randombytes "^2.0.5"
safe-buffer "^5.1.0"
-range-parser@^1.2.0, range-parser@^1.2.1, range-parser@~1.2.1:
+range-parser@^1.2.1, range-parser@~1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
@@ -10719,12 +10275,7 @@ reusify@^1.0.4:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
-rfdc@^1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2"
- integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==
-
-rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.3, rimraf@~2.6.2:
+rimraf@^2.5.4, rimraf@^2.6.3, rimraf@~2.6.2:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
@@ -11158,52 +10709,6 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0"
use "^3.1.0"
-socket.io-adapter@~1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz#2a805e8a14d6372124dd9159ad4502f8cb07f06b"
- integrity sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=
-
-socket.io-client@2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.1.1.tgz#dcb38103436ab4578ddb026638ae2f21b623671f"
- integrity sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==
- dependencies:
- backo2 "1.0.2"
- base64-arraybuffer "0.1.5"
- component-bind "1.0.0"
- component-emitter "1.2.1"
- debug "~3.1.0"
- engine.io-client "~3.2.0"
- has-binary2 "~1.0.2"
- has-cors "1.1.0"
- indexof "0.0.1"
- object-component "0.0.3"
- parseqs "0.0.5"
- parseuri "0.0.5"
- socket.io-parser "~3.2.0"
- to-array "0.1.4"
-
-socket.io-parser@~3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077"
- integrity sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==
- dependencies:
- component-emitter "1.2.1"
- debug "~3.1.0"
- isarray "2.0.1"
-
-socket.io@2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.1.tgz#a069c5feabee3e6b214a75b40ce0652e1cfb9980"
- integrity sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==
- dependencies:
- debug "~3.1.0"
- engine.io "~3.2.0"
- has-binary2 "~1.0.2"
- socket.io-adapter "~1.1.0"
- socket.io-client "2.1.1"
- socket.io-parser "~3.2.0"
-
sockjs-client@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.0.tgz#2f8ff5d4b659e0d092f7aba0b7c386bd2aa20add"
@@ -11394,11 +10899,6 @@ static-extend@^0.1.1:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
-statuses@~1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
- integrity sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=
-
stealthy-require@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
@@ -11436,17 +10936,6 @@ stream-shift@^1.0.0:
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=
-streamroller@^1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-1.0.6.tgz#8167d8496ed9f19f05ee4b158d9611321b8cacd9"
- integrity sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==
- dependencies:
- async "^2.6.2"
- date-format "^2.0.0"
- debug "^3.2.6"
- fs-extra "^7.0.1"
- lodash "^4.17.14"
-
string-hash@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
@@ -11955,7 +11444,7 @@ tiptap@^1.32.2:
tiptap-commands "^1.17.1"
tiptap-utils "^1.13.1"
-tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33:
+tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
@@ -11967,11 +11456,6 @@ tmpl@1.0.x:
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
-to-array@0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
- integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA=
-
to-arraybuffer@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
@@ -12200,19 +11684,6 @@ uc.micro@^1.0.1, uc.micro@^1.0.5:
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
-uglify-js@^3.1.4:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5"
- integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==
- dependencies:
- commander "~2.20.0"
- source-map "~0.6.1"
-
-ultron@~1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
- integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==
-
undefsafe@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.2.tgz#225f6b9e0337663e0d8e7cfd686fc2836ccace76"
@@ -12426,14 +11897,6 @@ use@^3.1.0:
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
-useragent@2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972"
- integrity sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==
- dependencies:
- lru-cache "4.1.x"
- tmp "0.0.x"
-
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
@@ -12542,11 +12005,6 @@ vm-browserify@^1.0.1:
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019"
integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==
-void-elements@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
- integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
-
vscode-json-languageservice@^3.6.0:
version "3.9.1"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.9.1.tgz#f72b581f8cd2bd9b47445ccf8b0ddcde6aba7483"
@@ -12842,7 +12300,7 @@ webpack-cli@^3.3.12:
v8-compile-cache "^2.1.1"
yargs "^13.3.2"
-webpack-dev-middleware@^3.7.0, webpack-dev-middleware@^3.7.2:
+webpack-dev-middleware@^3.7.2:
version "3.7.2"
resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3"
integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==
@@ -12982,7 +12440,7 @@ which-module@^2.0.0:
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
-which@^1.2.1, which@^1.2.14, which@^1.2.9, which@^1.3.1:
+which@^1.2.14, which@^1.2.9, which@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
@@ -13008,11 +12466,6 @@ word-wrap@^1.2.3, word-wrap@~1.2.3:
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
-wordwrap@~0.0.2:
- version "0.0.3"
- resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
- integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc=
-
worker-farm@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8"
@@ -13100,15 +12553,6 @@ ws@^7.2.3, ws@^7.3.1:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59"
integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==
-ws@~3.3.1:
- version "3.3.3"
- resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
- integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==
- dependencies:
- async-limiter "~1.0.0"
- safe-buffer "~5.1.0"
- ultron "~1.1.0"
-
xdg-basedir@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
@@ -13140,11 +12584,6 @@ xml@^1.0.1:
resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"
integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=
-xmlbuilder@8.2.2:
- version "8.2.2"
- resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-8.2.2.tgz#69248673410b4ba42e1a6136551d2922335aa773"
- integrity sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=
-
xmlbuilder@~9.0.1:
version "9.0.7"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
@@ -13160,11 +12599,6 @@ xmlcreate@^1.0.1:
resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-1.0.2.tgz#fa6bf762a60a413fb3dd8f4b03c5b269238d308f"
integrity sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=
-xmlhttprequest-ssl@~1.5.4:
- version "1.5.5"
- resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
- integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=
-
xtend@^4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
@@ -13292,11 +12726,6 @@ yarn-deduplicate@^3.1.0:
commander "^6.1.0"
semver "^7.3.2"
-yeast@0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
- integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=
-
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"