diff options
43 files changed, 404 insertions, 404 deletions
diff --git a/.rubocop.yml b/.rubocop.yml index db607ec36ec..43b4e46171b 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -569,6 +569,8 @@ RSpec/ImplicitSubject: RSpec/ReceiveNever: Enabled: false +# Already covered by `RSpec::Configuration#on_potential_false_positives = :raise`. +# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86429 RSpec/UnspecifiedException: Enabled: false diff --git a/.rubocop_todo/rspec/verified_doubles.yml b/.rubocop_todo/rspec/verified_doubles.yml index 819685b38ba..ee24ed73a27 100644 --- a/.rubocop_todo/rspec/verified_doubles.yml +++ b/.rubocop_todo/rspec/verified_doubles.yml @@ -90,7 +90,6 @@ RSpec/VerifiedDoubles: - ee/spec/lib/sidebars/groups/menus/analytics_menu_spec.rb - ee/spec/lib/system_check/geo/geo_database_configured_check_spec.rb - ee/spec/models/app_sec/fuzzing/api/ci_configuration_spec.rb - - ee/spec/models/ee/approvable_spec.rb - ee/spec/models/concerns/geo/verification_state_spec.rb - ee/spec/models/ee/ci/job_artifact_spec.rb - ee/spec/models/ee/user_spec.rb diff --git a/app/assets/javascripts/blob/3d_viewer/index.js b/app/assets/javascripts/blob/3d_viewer/index.js index d4efe409fef..2831c37838b 100644 --- a/app/assets/javascripts/blob/3d_viewer/index.js +++ b/app/assets/javascripts/blob/3d_viewer/index.js @@ -1,11 +1,8 @@ -import OrbitControlsClass from 'three-orbit-controls'; -import STLLoaderClass from 'three-stl-loader'; +import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; +import { STLLoader } from 'three/examples/jsm/loaders/STLLoader'; import * as THREE from 'three/build/three.module'; import MeshObject from './mesh_object'; -const STLLoader = STLLoaderClass(THREE); -const OrbitControls = OrbitControlsClass(THREE); - export default class Renderer { constructor(container) { this.renderWrapper = this.render.bind(this); diff --git a/app/assets/javascripts/blob/3d_viewer/mesh_object.js b/app/assets/javascripts/blob/3d_viewer/mesh_object.js index c55a9ca8926..5322dc00e86 100644 --- a/app/assets/javascripts/blob/3d_viewer/mesh_object.js +++ b/app/assets/javascripts/blob/3d_viewer/mesh_object.js @@ -22,7 +22,7 @@ export default class MeshObject extends Mesh { if (this.geometry.boundingSphere.radius > 4) { const scale = 4 / this.geometry.boundingSphere.radius; - this.geometry.applyMatrix(new Matrix4().makeScale(scale, scale, scale)); + this.geometry.applyMatrix4(new Matrix4().makeScale(scale, scale, scale)); this.geometry.computeBoundingSphere(); this.position.x = -this.geometry.boundingSphere.center.x; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue index 4e580c88ef3..5581863591c 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue @@ -130,11 +130,16 @@ export default { }, async fetchExpandedContent() { this.isLoadingExpandedContent = true; + this.error = null; try { await this.fetch(this.fetchExpandedData, FETCH_TYPE_EXPANDED); } catch { this.error = this.errorText; + + // Reset these values so that we allow refetching + this.isExpandedForTheFirstTime = true; + this.isCollapsed = true; } this.isLoadingExpandedContent = false; diff --git a/app/controllers/projects/pipelines/tests_controller.rb b/app/controllers/projects/pipelines/tests_controller.rb index 8ac370b1bd4..d77cf095a4f 100644 --- a/app/controllers/projects/pipelines/tests_controller.rb +++ b/app/controllers/projects/pipelines/tests_controller.rb @@ -51,7 +51,8 @@ module Projects def test_suite suite = builds.sum do |build| - build.collect_test_reports!(Gitlab::Ci::Reports::TestReport.new) + test_report = build.collect_test_reports!(Gitlab::Ci::Reports::TestReport.new) + test_report.get_suite(build.test_suite_name) end Gitlab::Ci::Reports::TestFailureHistory.new(suite.failed.values, project).load! diff --git a/app/graphql/resolvers/ci/test_suite_resolver.rb b/app/graphql/resolvers/ci/test_suite_resolver.rb index f758e217b47..a2d3af9c664 100644 --- a/app/graphql/resolvers/ci/test_suite_resolver.rb +++ b/app/graphql/resolvers/ci/test_suite_resolver.rb @@ -28,7 +28,8 @@ module Resolvers def load_test_suite_data(builds) suite = builds.sum do |build| - build.collect_test_reports!(Gitlab::Ci::Reports::TestReport.new) + test_report = build.collect_test_reports!(Gitlab::Ci::Reports::TestReport.new) + test_report.get_suite(build.test_suite_name) end Gitlab::Ci::Reports::TestFailureHistory.new(suite.failed.values, pipeline.project).load! diff --git a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb index 15ab4435204..8295bd58388 100644 --- a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb +++ b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb @@ -84,6 +84,8 @@ module IssueResolverArguments end def ready?(**args) + args[:not] = args[:not].to_h if args[:not].present? + params_not_mutually_exclusive(args, mutually_exclusive_assignee_username_args) params_not_mutually_exclusive(args, mutually_exclusive_milestone_args) params_not_mutually_exclusive(args.fetch(:not, {}), mutually_exclusive_milestone_args) @@ -114,7 +116,6 @@ module IssueResolverArguments def prepare_finder_params(args) params = super(args) - params[:not] = params[:not].to_h if params[:not].present? params[:iids] ||= [params.delete(:iid)].compact if params[:iid] params[:attempt_project_search_optimizations] = true if params[:search].present? diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb index 1c43432594a..6f64e5b5053 100644 --- a/app/graphql/types/base_field.rb +++ b/app/graphql/types/base_field.rb @@ -17,8 +17,6 @@ module Types @requires_argument = !!kwargs.delete(:requires_argument) @authorize = Array.wrap(kwargs.delete(:authorize)) kwargs[:complexity] = field_complexity(kwargs[:resolver_class], kwargs[:complexity]) - @feature_flag = kwargs[:_deprecated_feature_flag] - kwargs = check_feature_flag(kwargs) @deprecation = gitlab_deprecation(kwargs) after_connection_extensions = kwargs.delete(:late_extensions) || [] @@ -91,16 +89,8 @@ module Types @constant_complexity end - def visible?(context) - return false if feature_flag.present? && !Feature.enabled?(feature_flag) - - super - end - private - attr_reader :feature_flag - def field_authorized?(object, ctx) object = object.node if object.is_a?(GraphQL::Pagination::Connection::Edge) @@ -123,27 +113,6 @@ module Types @authorization ||= ::Gitlab::Graphql::Authorize::ObjectAuthorization.new(@authorize) end - def feature_documentation_message(key, description) - message_parts = ["#{description} Available only when feature flag `#{key}` is enabled."] - - message_parts << if Feature::Definition.has_definition?(key) && Feature::Definition.default_enabled?(key) - "This flag is enabled by default." - else - "This flag is disabled by default, because the feature is experimental and is subject to change without notice." - end - - message_parts.join(' ') - end - - def check_feature_flag(args) - ff = args.delete(:_deprecated_feature_flag) - return args unless ff.present? - - args[:description] = feature_documentation_message(ff, args[:description]) - - args - end - def field_complexity(resolver_class, current) return current if current.present? && current > 0 diff --git a/app/graphql/types/ci/config_variable_type.rb b/app/graphql/types/ci/config_variable_type.rb new file mode 100644 index 00000000000..87ae026c2c1 --- /dev/null +++ b/app/graphql/types/ci/config_variable_type.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Types + module Ci + class ConfigVariableType < BaseObject # rubocop:disable Graphql/AuthorizeTypes + graphql_name 'CiConfigVariable' + description 'CI/CD config variables.' + + field :key, GraphQL::Types::String, + null: true, + description: 'Name of the variable.' + + field :description, GraphQL::Types::String, + null: true, + description: 'Description for the CI/CD config variable.' + + field :value, GraphQL::Types::String, + null: true, + description: 'Value of the variable.' + end + end +end diff --git a/app/graphql/types/ci/group_variable_type.rb b/app/graphql/types/ci/group_variable_type.rb index 3322f741342..8821fdd8eb4 100644 --- a/app/graphql/types/ci/group_variable_type.rb +++ b/app/graphql/types/ci/group_variable_type.rb @@ -10,16 +10,16 @@ module Types implements(VariableInterface) field :environment_scope, GraphQL::Types::String, - null: true, - description: 'Scope defining the environments that can use the variable.' - - field :protected, GraphQL::Types::Boolean, - null: true, - description: 'Indicates whether the variable is protected.' + null: true, + description: 'Scope defining the environments that can use the variable.' field :masked, GraphQL::Types::Boolean, - null: true, - description: 'Indicates whether the variable is masked.' + null: true, + description: 'Indicates whether the variable is masked.' + + field :protected, GraphQL::Types::Boolean, + null: true, + description: 'Indicates whether the variable is protected.' end end end diff --git a/app/graphql/types/ci/instance_variable_type.rb b/app/graphql/types/ci/instance_variable_type.rb index f564a2f59a0..7ffc52deb73 100644 --- a/app/graphql/types/ci/instance_variable_type.rb +++ b/app/graphql/types/ci/instance_variable_type.rb @@ -9,21 +9,29 @@ module Types implements(VariableInterface) + field :id, GraphQL::Types::ID, + null: false, + description: 'ID of the variable.' + field :environment_scope, GraphQL::Types::String, - null: true, - deprecated: { - reason: 'No longer used, only available for GroupVariableType and ProjectVariableType', - milestone: '15.3' - }, - description: 'Scope defining the environments that can use the variable.' + null: true, + deprecated: { + reason: 'No longer used, only available for GroupVariableType and ProjectVariableType', + milestone: '15.3' + }, + description: 'Scope defining the environments that can use the variable.' field :protected, GraphQL::Types::Boolean, - null: true, - description: 'Indicates whether the variable is protected.' + null: true, + description: 'Indicates whether the variable is protected.' field :masked, GraphQL::Types::Boolean, - null: true, - description: 'Indicates whether the variable is masked.' + null: true, + description: 'Indicates whether the variable is masked.' + + field :raw, GraphQL::Types::Boolean, + null: true, + description: 'Indicates whether the variable is raw.' def environment_scope nil diff --git a/app/graphql/types/ci/manual_variable_type.rb b/app/graphql/types/ci/manual_variable_type.rb index d6f59c1d249..ed92a6645b4 100644 --- a/app/graphql/types/ci/manual_variable_type.rb +++ b/app/graphql/types/ci/manual_variable_type.rb @@ -10,12 +10,12 @@ module Types implements(VariableInterface) field :environment_scope, GraphQL::Types::String, - null: true, - deprecated: { - reason: 'No longer used, only available for GroupVariableType and ProjectVariableType', - milestone: '15.3' - }, - description: 'Scope defining the environments that can use the variable.' + null: true, + deprecated: { + reason: 'No longer used, only available for GroupVariableType and ProjectVariableType', + milestone: '15.3' + }, + description: 'Scope defining the environments that can use the variable.' def environment_scope nil diff --git a/app/graphql/types/ci/project_variable_type.rb b/app/graphql/types/ci/project_variable_type.rb index 625bb7fd4b1..02e3cdc1a11 100644 --- a/app/graphql/types/ci/project_variable_type.rb +++ b/app/graphql/types/ci/project_variable_type.rb @@ -10,16 +10,16 @@ module Types implements(VariableInterface) field :environment_scope, GraphQL::Types::String, - null: true, - description: 'Scope defining the environments that can use the variable.' + null: true, + description: 'Scope defining the environments that can use the variable.' field :protected, GraphQL::Types::Boolean, - null: true, - description: 'Indicates whether the variable is protected.' + null: true, + description: 'Indicates whether the variable is protected.' field :masked, GraphQL::Types::Boolean, - null: true, - description: 'Indicates whether the variable is masked.' + null: true, + description: 'Indicates whether the variable is masked.' end end end diff --git a/app/graphql/types/ci/variable_interface.rb b/app/graphql/types/ci/variable_interface.rb index 82c9ba7121c..ec68d3c987c 100644 --- a/app/graphql/types/ci/variable_interface.rb +++ b/app/graphql/types/ci/variable_interface.rb @@ -8,24 +8,24 @@ module Types graphql_name 'CiVariable' field :id, GraphQL::Types::ID, - null: false, - description: 'ID of the variable.' + null: false, + description: 'ID of the variable.' field :key, GraphQL::Types::String, - null: true, - description: 'Name of the variable.' + null: true, + description: 'Name of the variable.' + + field :raw, GraphQL::Types::Boolean, + null: true, + description: 'Indicates whether the variable is raw.' field :value, GraphQL::Types::String, - null: true, - description: 'Value of the variable.' + null: true, + description: 'Value of the variable.' field :variable_type, ::Types::Ci::VariableTypeEnum, - null: true, - description: 'Type of the variable.' - - field :raw, GraphQL::Types::Boolean, - null: true, - description: 'Indicates whether the variable is raw.' + null: true, + description: 'Type of the variable.' end end end diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb index 2ad4e8848d1..53336a2affa 100644 --- a/app/graphql/types/project_type.rb +++ b/app/graphql/types/project_type.rb @@ -18,6 +18,17 @@ module Types null: false, description: 'Path of the CI configuration file.' + field :ci_config_variables, [Types::Ci::ConfigVariableType], + null: true, + calls_gitaly: true, + authorize: :create_pipeline, + alpha: { milestone: '15.3' }, + description: 'CI/CD config variable.' do + argument :sha, GraphQL::Types::String, + required: true, + description: 'Sha.' + end + field :full_path, GraphQL::Types::ID, null: false, description: 'Full path of the project.' @@ -549,6 +560,16 @@ module Types project.container_repositories.size end + def ci_config_variables(sha) + result = ::Ci::ListConfigVariablesService.new(object, context[:current_user]).execute(sha) + + return if result.nil? + + result.map do |var_key, var_config| + { key: var_key, **var_config } + end + end + def sast_ci_configuration return unless Ability.allowed?(current_user, :download_code, object) diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index d9e8873ffc1..1228dfd87d6 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -996,15 +996,11 @@ module Ci end def collect_test_reports!(test_reports) - test_reports.get_suite(test_suite_name).tap do |test_suite| - each_report(Ci::JobArtifact.file_types_for_report(:test)) do |file_type, blob| - Gitlab::Ci::Parsers.fabricate!(file_type).parse!( - blob, - test_suite, - job: self - ) - end + each_report(Ci::JobArtifact.file_types_for_report(:test)) do |file_type, blob| + Gitlab::Ci::Parsers.fabricate!(file_type).parse!(blob, test_reports, job: self) end + + test_reports end def collect_accessibility_reports!(accessibility_report) @@ -1181,6 +1177,14 @@ module Ci job_artifacts.map(&:file_type) end + def test_suite_name + if matrix_build? + name + else + group_name + end + end + protected def run_status_commit_hooks! @@ -1191,14 +1195,6 @@ module Ci private - def test_suite_name - if matrix_build? - name - else - group_name - end - end - def matrix_build? options.dig(:parallel, :matrix).present? end diff --git a/app/services/ci/build_report_result_service.rb b/app/services/ci/build_report_result_service.rb index f9146b3677a..20a31322919 100644 --- a/app/services/ci/build_report_result_service.rb +++ b/app/services/ci/build_report_result_service.rb @@ -22,7 +22,8 @@ module Ci private def generate_test_suite_report(build) - build.collect_test_reports!(Gitlab::Ci::Reports::TestReport.new) + test_report = build.collect_test_reports!(Gitlab::Ci::Reports::TestReport.new) + test_report.get_suite(build.test_suite_name) end def tests_params(test_suite) diff --git a/app/services/ci/test_failure_history_service.rb b/app/services/ci/test_failure_history_service.rb index 2214a6a2729..5a8072b2a0d 100644 --- a/app/services/ci/test_failure_history_service.rb +++ b/app/services/ci/test_failure_history_service.rb @@ -80,8 +80,8 @@ module Ci end def generate_test_suite!(build) - # Returns an instance of Gitlab::Ci::Reports::TestSuite - build.collect_test_reports!(Gitlab::Ci::Reports::TestReport.new) + test_report = build.collect_test_reports!(Gitlab::Ci::Reports::TestReport.new) + test_report.get_suite(build.test_suite_name) end def ci_unit_test_attrs(batch) diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 5a33b2ebc44..68afb17f485 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -10098,6 +10098,18 @@ Represents the total number of issues and their weights for a particular day. | <a id="ciconfigstagegroups"></a>`groups` | [`CiConfigGroupConnection`](#ciconfiggroupconnection) | Groups of jobs for the stage. (see [Connections](#connections)) | | <a id="ciconfigstagename"></a>`name` | [`String`](#string) | Name of the stage. | +### `CiConfigVariable` + +CI/CD config variables. + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="ciconfigvariabledescription"></a>`description` | [`String`](#string) | Description for the CI/CD config variable. | +| <a id="ciconfigvariablekey"></a>`key` | [`String`](#string) | Name of the variable. | +| <a id="ciconfigvariablevalue"></a>`value` | [`String`](#string) | Value of the variable. | + ### `CiGroup` #### Fields @@ -15801,6 +15813,22 @@ four standard [pagination arguments](#connection-pagination-arguments): | ---- | ---- | ----------- | | <a id="projectboardsid"></a>`id` | [`BoardID`](#boardid) | Find a board by its ID. | +##### `Project.ciConfigVariables` + +CI/CD config variable. + +WARNING: +**Introduced** in 15.3. +This feature is in Alpha. It can be changed or removed at any time. + +Returns [`[CiConfigVariable!]`](#ciconfigvariable). + +###### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="projectciconfigvariablessha"></a>`sha` | [`String!`](#string) | Sha. | + ##### `Project.ciTemplate` Find a single CI/CD template by name. diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md index 190e853a376..78ff8fbba36 100644 --- a/doc/development/api_graphql_styleguide.md +++ b/doc/development/api_graphql_styleguide.md @@ -546,12 +546,6 @@ def resolve(id: ) end ``` -### `feature_flag` property (deprecated) - -NOTE: -This property is deprecated and should no longer be used. The property -has been temporarily renamed to `_deprecated_feature_flag` and support for it will be removed in [#369202](https://gitlab.com/gitlab-org/gitlab/-/issues/369202). - ## Deprecating schema items The GitLab GraphQL API is versionless, which means we maintain backwards diff --git a/lib/gitlab/ci/parsers/test/junit.rb b/lib/gitlab/ci/parsers/test/junit.rb index 999ffff85d2..d95ecff85cd 100644 --- a/lib/gitlab/ci/parsers/test/junit.rb +++ b/lib/gitlab/ci/parsers/test/junit.rb @@ -8,7 +8,9 @@ module Gitlab JunitParserError = Class.new(Gitlab::Ci::Parsers::ParserError) ATTACHMENT_TAG_REGEX = /\[\[ATTACHMENT\|(?<path>.+?)\]\]/.freeze - def parse!(xml_data, test_suite, job:) + def parse!(xml_data, test_report, job:) + test_suite = test_report.get_suite(job.test_suite_name) + root = Hash.from_xml(xml_data) total_parsed = 0 max_test_cases = job.max_test_cases_per_report diff --git a/lib/gitlab/import_export/group/import_export.yml b/lib/gitlab/import_export/group/import_export.yml index 7e81112796f..a58469cea57 100644 --- a/lib/gitlab/import_export/group/import_export.yml +++ b/lib/gitlab/import_export/group/import_export.yml @@ -32,14 +32,11 @@ included_attributes: - :created_at - :updated_at - :start_date - - :last_run_date - - :duration_in_weeks - - :iterations_in_advance - :active - - :automatic - :roll_over - :title - :description + - :sequence iterations_cadences: *iterations_cadence_definition iteration: &iteration_definition - :iid @@ -69,6 +66,10 @@ excluded_attributes: - :state_id iterations_cadence: &iterations_cadence_definition - :id + - :last_run_date + - :duration_in_weeks + - :iterations_in_advance + - :automatic iterations_cadences: *iterations_cadence_definition iteration: &iteration_excluded_definition - :id diff --git a/lib/gitlab/import_export/group/relation_factory.rb b/lib/gitlab/import_export/group/relation_factory.rb index 08db9471e27..1b8436c4ed9 100644 --- a/lib/gitlab/import_export/group/relation_factory.rb +++ b/lib/gitlab/import_export/group/relation_factory.rb @@ -26,7 +26,10 @@ module Gitlab private def setup_models - setup_note if @relation_name == :notes + case @relation_name + when :notes then setup_note + when :'Iterations::Cadence' then setup_iterations_cadence + end update_group_references end @@ -45,6 +48,10 @@ module Gitlab def use_attributes_permitter? false end + + def setup_iterations_cadence + @relation_hash['automatic'] = false + end end end end diff --git a/package.json b/package.json index 710b9595927..1bc6317f00b 100644 --- a/package.json +++ b/package.json @@ -168,9 +168,7 @@ "string-hash": "1.1.3", "style-loader": "^2.0.0", "swagger-ui-dist": "4.12.0", - "three": "^0.84.0", - "three-orbit-controls": "^82.1.0", - "three-stl-loader": "^1.0.4", + "three": "^0.143.0", "timeago.js": "^4.0.2", "unified": "^10.1.2", "unist-util-visit-parents": "^5.1.0", diff --git a/rubocop/code_reuse_helpers.rb b/rubocop/code_reuse_helpers.rb index 2769da2389c..87b907f8778 100644 --- a/rubocop/code_reuse_helpers.rb +++ b/rubocop/code_reuse_helpers.rb @@ -81,12 +81,6 @@ module RuboCop in_app_directory?(node, 'graphql') end - # Returns true if the given node resides in app/graphql/types, - # ee/app/graphql/types, or ee/app/graphql/ee/types. - def in_graphql_types?(node) - in_graphql_directory?(node, 'types') - end - # Returns true if the given node resides in lib/api or ee/lib/api. def in_api?(node) in_lib_directory?(node, 'api') diff --git a/rubocop/cop/gitlab/mark_used_feature_flags.rb b/rubocop/cop/gitlab/mark_used_feature_flags.rb index 63bccec31c0..4844dab0a30 100644 --- a/rubocop/cop/gitlab/mark_used_feature_flags.rb +++ b/rubocop/cop/gitlab/mark_used_feature_flags.rb @@ -26,9 +26,6 @@ module RuboCop data_consistency deduplicate ].freeze - GRAPHQL_METHODS = %i[ - field - ].freeze SELF_METHODS = %i[ push_frontend_feature_flag push_force_frontend_feature_flag @@ -36,7 +33,7 @@ module RuboCop limit_feature_flag_for_override= ].freeze + EXPERIMENT_METHODS + RUGGED_METHODS + WORKER_METHODS - RESTRICT_ON_SEND = FEATURE_METHODS + EXPERIMENTATION_METHODS + GRAPHQL_METHODS + SELF_METHODS + RESTRICT_ON_SEND = FEATURE_METHODS + EXPERIMENTATION_METHODS + SELF_METHODS USAGE_DATA_COUNTERS_EVENTS_YAML_GLOBS = [ File.expand_path("../../../config/metrics/aggregates/*.yml", __dir__), @@ -138,15 +135,6 @@ module RuboCop node.children[3].each_pair.find do |pair| pair.key.value == :feature_flag end&.value - elsif graphql_method?(node) - return unless node.children.size > 3 - - opts_index = node.children[3].hash_type? ? 3 : 4 - return unless node.children[opts_index] - - node.children[opts_index].each_pair.find do |pair| - pair.key.value == :_deprecated_feature_flag - end&.value else arg_index = rugged_method?(node) ? 3 : 2 @@ -209,16 +197,12 @@ module RuboCop WORKER_METHODS.include?(method_name(node)) end - def graphql_method?(node) - GRAPHQL_METHODS.include?(method_name(node)) && in_graphql_types?(node) - end - def self_method?(node) SELF_METHODS.include?(method_name(node)) && class_caller(node).empty? end def trackable_flag?(node) - feature_method?(node) || experimentation_method?(node) || graphql_method?(node) || self_method?(node) + feature_method?(node) || experimentation_method?(node) || self_method?(node) end # Marking all event's feature flags as used as Gitlab::UsageDataCounters::HLLRedisCounter.track_event{,context} diff --git a/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js b/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js index 049e5bcce92..b1ed61faf66 100644 --- a/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js @@ -236,16 +236,17 @@ describe('MR Widget', () => { data: { vulnerabilities: [{ vuln: 2 }] }, }; + const fetchExpandedData = jest.fn().mockResolvedValue(mockDataExpanded); + createComponent({ propsData: { isCollapsible: true, fetchCollapsedData: () => Promise.resolve(mockDataCollapsed), - fetchExpandedData: () => Promise.resolve(mockDataExpanded), + fetchExpandedData, }, }); findToggleButton().vm.$emit('click'); - await waitForPromises(); // First fetches the collapsed data @@ -259,6 +260,62 @@ describe('MR Widget', () => { collapsed: null, expanded: mockDataExpanded.data, }); + + // Triggering a click does not call the expanded data again + findToggleButton().vm.$emit('click'); + await waitForPromises(); + expect(fetchExpandedData).toHaveBeenCalledTimes(1); + }); + + it('allows refetching when fetch expanded data returns an error', async () => { + const fetchExpandedData = jest.fn().mockRejectedValue({ error: true }); + + createComponent({ + propsData: { + isCollapsible: true, + fetchCollapsedData: () => Promise.resolve([]), + fetchExpandedData, + }, + }); + + findToggleButton().vm.$emit('click'); + await waitForPromises(); + + // First fetches the collapsed data + expect(wrapper.emitted('input')[0][0]).toEqual({ + collapsed: undefined, + expanded: null, + }); + + expect(fetchExpandedData).toHaveBeenCalledTimes(1); + expect(wrapper.emitted('input')).toHaveLength(1); // Should not an emit an input call because request failed + + findToggleButton().vm.$emit('click'); + await waitForPromises(); + expect(fetchExpandedData).toHaveBeenCalledTimes(2); + }); + + it('resets the error message when another request is fetched', async () => { + const fetchExpandedData = jest.fn().mockRejectedValue({ error: true }); + + createComponent({ + propsData: { + isCollapsible: true, + fetchCollapsedData: () => Promise.resolve([]), + fetchExpandedData, + }, + }); + + findToggleButton().vm.$emit('click'); + await waitForPromises(); + + expect(wrapper.findByText('Failed to load').exists()).toBe(true); + fetchExpandedData.mockImplementation(() => new Promise(() => {})); + + findToggleButton().vm.$emit('click'); + await nextTick(); + + expect(wrapper.findByText('Failed to load').exists()).toBe(false); }); }); }); diff --git a/spec/graphql/features/feature_flag_spec.rb b/spec/graphql/features/feature_flag_spec.rb deleted file mode 100644 index b06718eb16a..00000000000 --- a/spec/graphql/features/feature_flag_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Graphql Field feature flags' do - include GraphqlHelpers - include Graphql::ResolverFactories - - let_it_be(:user) { create(:user) } - - let(:feature_flag) { 'test_feature' } - let(:test_object) { double(name: 'My name') } - let(:query_string) { '{ item { name } }' } - let(:result) { execute_query(query_type)['data'] } - - before do - skip_feature_flags_yaml_validation - end - - subject { result } - - describe 'Feature flagged field' do - let(:type) { type_factory } - - let(:query_type) do - query_factory do |query| - query.field :item, type, null: true, _deprecated_feature_flag: feature_flag, resolver: new_resolver(test_object) - end - end - - it 'checks YAML definition for default_enabled' do - # Exception is indicative of a check for YAML definition - expect { subject }.to raise_error(Feature::InvalidFeatureFlagError, /The feature flag YAML definition for '#{feature_flag}' does not exist/) - end - - context 'skipping YAML check' do - before do - skip_default_enabled_yaml_check - end - - it 'returns the value when feature is enabled' do - expect(subject['item']).to eq('name' => test_object.name) - end - - it 'returns nil when the feature is disabled' do - stub_feature_flags(feature_flag => false) - - expect(subject).to be_nil - end - end - end -end diff --git a/spec/graphql/types/base_field_spec.rb b/spec/graphql/types/base_field_spec.rb index b85716e4d21..9f8a8717efb 100644 --- a/spec/graphql/types/base_field_spec.rb +++ b/spec/graphql/types/base_field_spec.rb @@ -205,39 +205,6 @@ RSpec.describe Types::BaseField do end end end - - describe '#visible?' do - context 'and has a feature_flag' do - let(:flag) { :test_feature } - let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String, _deprecated_feature_flag: flag, null: false) } - let(:context) { {} } - - before do - skip_feature_flags_yaml_validation - end - - it 'checks YAML definition for default_enabled' do - # Exception is indicative of a check for YAML definition - expect { field.visible?(context) }.to raise_error(Feature::InvalidFeatureFlagError, /The feature flag YAML definition for '#{flag}' does not exist/) - end - - context 'skipping YAML check' do - before do - skip_default_enabled_yaml_check - end - - it 'returns false if the feature is not enabled' do - stub_feature_flags(flag => false) - - expect(field.visible?(context)).to eq(false) - end - - it 'returns true if the feature is enabled' do - expect(field.visible?(context)).to eq(true) - end - end - end - end end describe '#resolve' do @@ -251,77 +218,11 @@ RSpec.describe Types::BaseField do end end - describe '#description' do - context 'feature flag given' do - let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String, _deprecated_feature_flag: flag, null: false, description: 'Test description.') } - let(:flag) { :test_flag } - - it 'prepends the description' do - expect(field.description).to start_with 'Test description. Available only when feature flag `test_flag` is enabled.' - end - - context 'falsey feature_flag values' do - using RSpec::Parameterized::TableSyntax - - where(:flag, :feature_value, :default_enabled) do - '' | false | false - '' | true | false - nil | false | true - nil | true | false - end - - with_them do - it 'returns the correct description' do - expect(field.description).to eq('Test description.') - end - end - end - - context 'with different default_enabled values' do - using RSpec::Parameterized::TableSyntax - - where(:feature_value, :default_enabled, :expected_description) do - disabled_ff_description = "Test description. Available only when feature flag `test_flag` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice." - enabled_ff_description = "Test description. Available only when feature flag `test_flag` is enabled. This flag is enabled by default." - - false | false | disabled_ff_description - true | false | disabled_ff_description - false | true | enabled_ff_description - true | true | enabled_ff_description - end - - with_them do - before do - stub_feature_flags("#{flag}": feature_value) - - allow(Feature::Definition).to receive(:has_definition?).with(flag).and_return(true) - allow(Feature::Definition).to receive(:default_enabled?).and_return(default_enabled) - end - - it 'returns the correct availability in the description' do - expect(field.description).to eq expected_description - end - end - end - end - end - include_examples 'Gitlab-style deprecations' do def subject(args = {}) base_args = { name: 'test', type: GraphQL::Types::String, null: true } described_class.new(**base_args.merge(args)) end - - it 'interacts well with the `_deprecated_feature_flag` property' do - field = subject( - deprecated: { milestone: '1.10', reason: 'Deprecation reason' }, - description: 'Field description.', - _deprecated_feature_flag: 'foo_flag' - ) - - expect(field.description).to start_with('Field description. Available only when feature flag `foo_flag` is enabled.') - expect(field.description).to end_with('Deprecated in 1.10: Deprecation reason.') - end end end diff --git a/spec/graphql/types/ci/config_variable_type_spec.rb b/spec/graphql/types/ci/config_variable_type_spec.rb new file mode 100644 index 00000000000..2b0937a7858 --- /dev/null +++ b/spec/graphql/types/ci/config_variable_type_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['CiConfigVariable'] do + specify { expect(described_class).to have_graphql_fields(:key, :description, :value).at_least } +end diff --git a/spec/graphql/types/ci/instance_variable_type_spec.rb b/spec/graphql/types/ci/instance_variable_type_spec.rb index cf4aaed31f1..c77a4ac1dc4 100644 --- a/spec/graphql/types/ci/instance_variable_type_spec.rb +++ b/spec/graphql/types/ci/instance_variable_type_spec.rb @@ -5,5 +5,5 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['CiInstanceVariable'] do specify { expect(described_class.interfaces).to contain_exactly(Types::Ci::VariableInterface) } - specify { expect(described_class).to have_graphql_fields(:masked, :protected).at_least } + specify { expect(described_class).to have_graphql_fields(:environment_scope, :masked, :protected).at_least } end diff --git a/spec/graphql/types/ci/manual_variable_type_spec.rb b/spec/graphql/types/ci/manual_variable_type_spec.rb index 2884c818a52..21d36b7dfc0 100644 --- a/spec/graphql/types/ci/manual_variable_type_spec.rb +++ b/spec/graphql/types/ci/manual_variable_type_spec.rb @@ -4,4 +4,6 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['CiManualVariable'] do specify { expect(described_class.interfaces).to contain_exactly(Types::Ci::VariableInterface) } + + specify { expect(described_class).to have_graphql_fields(:environment_scope).at_least } end diff --git a/spec/graphql/types/ci/variable_interface_spec.rb b/spec/graphql/types/ci/variable_interface_spec.rb index 8cef0ac2a14..328c5305a44 100644 --- a/spec/graphql/types/ci/variable_interface_spec.rb +++ b/spec/graphql/types/ci/variable_interface_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['CiVariable'] do specify do expect(described_class).to have_graphql_fields( - :id, :key, :value, :variable_type, :raw + :id, :key, :raw, :value, :variable_type ).at_least end end diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb index 538ccfb2d01..c340275bd9c 100644 --- a/spec/graphql/types/project_type_spec.rb +++ b/spec/graphql/types/project_type_spec.rb @@ -37,6 +37,7 @@ RSpec.describe GitlabSchema.types['Project'] do ci_template timelogs merge_commit_template squash_commit_template work_item_types recent_issue_boards ci_config_path_or_default packages_cleanup_policy ci_variables timelog_categories fork_targets + ci_config_variables ] expect(described_class).to include_graphql_fields(*expected_fields) diff --git a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb index 82fa11d5f98..821a5057d2e 100644 --- a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb +++ b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb @@ -4,11 +4,13 @@ require 'fast_spec_helper' RSpec.describe Gitlab::Ci::Parsers::Test::Junit do describe '#parse!' do - subject { described_class.new.parse!(junit, test_suite, job: job) } + subject { described_class.new.parse!(junit, test_report, job: job) } - let(:test_suite) { Gitlab::Ci::Reports::TestSuite.new('rspec') } + let(:job) { double(test_suite_name: 'rspec', max_test_cases_per_report: max_test_cases) } + + let(:test_report) { Gitlab::Ci::Reports::TestReport.new } + let(:test_suite) { test_report.get_suite(job.test_suite_name) } let(:test_cases) { flattened_test_cases(test_suite) } - let(:job) { double(max_test_cases_per_report: max_test_cases) } let(:max_test_cases) { 0 } context 'when data is JUnit style XML' do diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 960bde3ec93..64cb547a048 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -4366,9 +4366,7 @@ RSpec.describe Ci::Build do end describe '#collect_test_reports!' do - subject { build.collect_test_reports!(test_reports) } - - let(:test_reports) { Gitlab::Ci::Reports::TestReport.new } + subject(:test_reports) { build.collect_test_reports!(Gitlab::Ci::Reports::TestReport.new) } it { expect(test_reports.get_suite(build.name).total_count).to eq(0) } @@ -4416,56 +4414,6 @@ RSpec.describe Ci::Build do end end end - - context 'when build is part of parallel build' do - let(:build_1) { create(:ci_build, name: 'build 1/2') } - let(:test_report) { Gitlab::Ci::Reports::TestReport.new } - - before do - build_1.collect_test_reports!(test_report) - end - - it 'uses the group name for test suite name' do - expect(test_report.test_suites.keys).to contain_exactly('build') - end - - context 'when there are more than one parallel builds' do - let(:build_2) { create(:ci_build, name: 'build 2/2') } - - before do - build_2.collect_test_reports!(test_report) - end - - it 'merges the test suite from parallel builds' do - expect(test_report.test_suites.keys).to contain_exactly('build') - end - end - end - - context 'when build is part of matrix build' do - let(:test_report) { Gitlab::Ci::Reports::TestReport.new } - let(:matrix_build_1) { create(:ci_build, :matrix) } - - before do - matrix_build_1.collect_test_reports!(test_report) - end - - it 'uses the job name for the test suite' do - expect(test_report.test_suites.keys).to contain_exactly(matrix_build_1.name) - end - - context 'when there are more than one matrix builds' do - let(:matrix_build_2) { create(:ci_build, :matrix) } - - before do - matrix_build_2.collect_test_reports!(test_report) - end - - it 'keeps separate test suites' do - expect(test_report.test_suites.keys).to match_array([matrix_build_1.name, matrix_build_2.name]) - end - end - end end describe '#collect_accessibility_reports!' do @@ -5662,4 +5610,28 @@ RSpec.describe Ci::Build do end end end + + describe '#test_suite_name' do + let(:build) { create(:ci_build, name: 'test') } + + it 'uses the group name for test suite name' do + expect(build.test_suite_name).to eq('test') + end + + context 'when build is part of parallel build' do + let(:build) { create(:ci_build, name: 'build 1/2') } + + it 'uses the group name for test suite name' do + expect(build.test_suite_name).to eq('build') + end + end + + context 'when build is part of matrix build' do + let!(:matrix_build) { create(:ci_build, :matrix) } + + it 'uses the job name for the test suite' do + expect(matrix_build.test_suite_name).to eq(matrix_build.name) + end + end + end end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index e713d0dc068..e4c0e81cc1b 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -4370,6 +4370,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do create(:ci_job_artifact, :junit_with_ant, job: build_java) end + it 'has a test suite for each job' do + expect(subject.test_suites.keys).to contain_exactly('rspec', 'java') + end + it 'returns test reports with collected data' do expect(subject.total_count).to be(7) expect(subject.success_count).to be(5) @@ -4388,6 +4392,34 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end end + context 'when the pipeline has parallel builds with test reports' do + let!(:parallel_build_1) { create(:ci_build, name: 'build 1/2', pipeline: pipeline) } + let!(:parallel_build_2) { create(:ci_build, name: 'build 2/2', pipeline: pipeline) } + + before do + create(:ci_job_artifact, :junit, job: parallel_build_1) + create(:ci_job_artifact, :junit, job: parallel_build_2) + end + + it 'merges the test suite from parallel builds' do + expect(subject.test_suites.keys).to contain_exactly('build') + end + end + + context 'the pipeline has matrix builds with test reports' do + let!(:matrix_build_1) { create(:ci_build, :matrix, pipeline: pipeline) } + let!(:matrix_build_2) { create(:ci_build, :matrix, pipeline: pipeline) } + + before do + create(:ci_job_artifact, :junit, job: matrix_build_1) + create(:ci_job_artifact, :junit, job: matrix_build_2) + end + + it 'keeps separate test suites for each matrix build' do + expect(subject.test_suites.keys).to contain_exactly(matrix_build_1.name, matrix_build_2.name) + end + end + context 'when pipeline does not have any builds with test reports' do it 'returns empty test reports' do expect(subject.total_count).to be(0) diff --git a/spec/requests/api/graphql/ci/config_variables_spec.rb b/spec/requests/api/graphql/ci/config_variables_spec.rb new file mode 100644 index 00000000000..c010ea3b9d4 --- /dev/null +++ b/spec/requests/api/graphql/ci/config_variables_spec.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Query.project(fullPath).ciConfigVariables(sha)' do + include GraphqlHelpers + include ReactiveCachingHelpers + + let_it_be(:project) { create(:project, :repository, :public) } + let_it_be(:user) { create(:user) } + let_it_be(:content) do + File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) + end + + let(:sha) { project.commit.sha } + + let(:service) { Ci::ListConfigVariablesService.new(project, user) } + + let(:query) do + %( + query { + project(fullPath: "#{project.full_path}") { + ciConfigVariables(sha: "#{sha}") { + key + value + description + } + } + } + ) + end + + context 'when the user has the correct permissions' do + before do + project.add_maintainer(user) + stub_ci_pipeline_yaml_file(content) + allow(Ci::ListConfigVariablesService) + .to receive(:new) + .and_return(service) + end + + context 'when the cache is not empty' do + before do + synchronous_reactive_cache(service) + end + + it 'returns the CI variables for the config' do + post_graphql(query, current_user: user) + + expect(graphql_data.dig('project', 'ciConfigVariables')).to contain_exactly( + { + 'key' => 'DB_NAME', + 'value' => 'postgres', + 'description' => nil + }, + { + 'key' => 'ENVIRONMENT_VAR', + 'value' => 'env var value', + 'description' => 'env var description' + } + ) + end + end + + context 'when the cache is empty' do + let(:sha) { 'main' } + + it 'returns nothing' do + post_graphql(query, current_user: user) + + expect(graphql_data.dig('project', 'ciConfigVariables')).to be_nil + end + end + end + + context 'when the user is not authorized' do + before do + project.add_guest(user) + stub_ci_pipeline_yaml_file(content) + allow(Ci::ListConfigVariablesService) + .to receive(:new) + .and_return(service) + synchronous_reactive_cache(service) + end + + it 'returns nothing' do + post_graphql(query, current_user: user) + + expect(graphql_data.dig('project', 'ciConfigVariables')).to be_nil + end + end +end diff --git a/spec/rubocop/code_reuse_helpers_spec.rb b/spec/rubocop/code_reuse_helpers_spec.rb index 5cc396a4e3e..a8f935426e6 100644 --- a/spec/rubocop/code_reuse_helpers_spec.rb +++ b/spec/rubocop/code_reuse_helpers_spec.rb @@ -172,31 +172,6 @@ RSpec.describe RuboCop::CodeReuseHelpers do end end - describe '#in_graphql_types?' do - %w[ - app/graphql/types - ee/app/graphql/ee/types - ee/app/graphql/types - ].each do |path| - it "returns true for a node in #{path}" do - node = build_and_parse_source('10', rails_root_join(path, 'foo.rb')) - - expect(cop.in_graphql_types?(node)).to eq(true) - end - end - - %w[ - app/graphql/resolvers - app/foo - ].each do |path| - it "returns false for a node in #{path}" do - node = build_and_parse_source('10', rails_root_join(path, 'foo.rb')) - - expect(cop.in_graphql_types?(node)).to eq(false) - end - end - end - describe '#in_api?' do it 'returns true for a node in the API directory' do node = build_and_parse_source('10', rails_root_join('lib', 'api', 'foo.rb')) diff --git a/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb b/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb index 5f72996a06a..c61376d7760 100644 --- a/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb +++ b/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb @@ -212,19 +212,6 @@ RSpec.describe RuboCop::Cop::Gitlab::MarkUsedFeatureFlags do include_examples 'does not set any flags as used', 'deduplicate :delayed' end - describe 'GraphQL `field` method' do - before do - allow(cop).to receive(:in_graphql_types?).and_return(true) - end - - include_examples 'sets flag as used', 'field :runners, Types::Ci::RunnerType.connection_type, null: true, _deprecated_feature_flag: :foo', 'foo' - include_examples 'sets flag as used', 'field :runners, null: true, _deprecated_feature_flag: :foo', 'foo' - include_examples 'does not set any flags as used', 'field :solution' - include_examples 'does not set any flags as used', 'field :runners, Types::Ci::RunnerType.connection_type' - include_examples 'does not set any flags as used', 'field :runners, Types::Ci::RunnerType.connection_type, null: true, description: "hello world"' - include_examples 'does not set any flags as used', 'field :solution, type: GraphQL::Types::String, null: true, description: "URL to the vulnerabilitys details page."' - end - describe "tracking of usage data metrics known events happens at the beginning of inspection" do let(:usage_data_counters_known_event_feature_flags) { ['an_event_feature_flag'] } diff --git a/spec/support/gitlab_stubs/gitlab_ci.yml b/spec/support/gitlab_stubs/gitlab_ci.yml index b1533879e32..b6a66cfa2c6 100644 --- a/spec/support/gitlab_stubs/gitlab_ci.yml +++ b/spec/support/gitlab_stubs/gitlab_ci.yml @@ -8,6 +8,9 @@ before_script: variables: DB_NAME: postgres + ENVIRONMENT_VAR: + value: 'env var value' + description: 'env var description' stages: - test diff --git a/yarn.lock b/yarn.lock index c294459f91e..0af3b375914 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11286,20 +11286,10 @@ textextensions@2: resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.2.0.tgz#38ac676151285b658654581987a0ce1a4490d286" integrity sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA== -three-orbit-controls@^82.1.0: - version "82.1.0" - resolved "https://registry.yarnpkg.com/three-orbit-controls/-/three-orbit-controls-82.1.0.tgz#11a7f33d0a20ecec98f098b37780f6537374fab4" - integrity sha1-EafzPQog7OyY8Jizd4D2U3N0+rQ= - -three-stl-loader@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/three-stl-loader/-/three-stl-loader-1.0.4.tgz#6b3319a31e3b910aab1883d19b00c81a663c3e03" - integrity sha1-azMZox47kQqrGIPRmwDIGmY8PgM= - -three@^0.84.0: - version "0.84.0" - resolved "https://registry.yarnpkg.com/three/-/three-0.84.0.tgz#95be85a55a0fa002aa625ed559130957dcffd918" - integrity sha1-lb6FpVoPoAKqYl7VWRMJV9z/2Rg= +three@^0.143.0: + version "0.143.0" + resolved "https://registry.yarnpkg.com/three/-/three-0.143.0.tgz#1455bca132cc2b20beb7f41d313e10c29e5ed9df" + integrity sha512-oKcAGYHhJ46TGEuHjodo2n6TY2R6lbvrkp+feKZxqsUL/WkH7GKKaeu6RHeyb2Xjfk2dPLRKLsOP0KM2VgT8Zg== throat@^6.0.1: version "6.0.1" |