Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
263baf70a1
commit
53ab147992
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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?
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.'
|
||||
|
||||
field :value, GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'Value of the variable.'
|
||||
|
||||
field :variable_type, ::Types::Ci::VariableTypeEnum,
|
||||
null: true,
|
||||
description: 'Type of the variable.'
|
||||
null: true,
|
||||
description: 'Name of the variable.'
|
||||
|
||||
field :raw, GraphQL::Types::Boolean,
|
||||
null: true,
|
||||
description: 'Indicates whether the variable is raw.'
|
||||
null: true,
|
||||
description: 'Indicates whether the variable is raw.'
|
||||
|
||||
field :value, GraphQL::Types::String,
|
||||
null: true,
|
||||
description: 'Value of the variable.'
|
||||
|
||||
field :variable_type, ::Types::Ci::VariableTypeEnum,
|
||||
null: true,
|
||||
description: 'Type of the variable.'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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'))
|
||||
|
|
|
@ -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'] }
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@ before_script:
|
|||
|
||||
variables:
|
||||
DB_NAME: postgres
|
||||
ENVIRONMENT_VAR:
|
||||
value: 'env var value'
|
||||
description: 'env var description'
|
||||
|
||||
stages:
|
||||
- test
|
||||
|
|
18
yarn.lock
18
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"
|
||||
|
|
Loading…
Reference in New Issue