diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-18 09:10:05 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-18 09:10:05 +0000 |
commit | 89eff770d213e684b5fa4df121cb51a059e8d263 (patch) | |
tree | f2783e2aaf50ebba6051f11335a45029b8549d34 | |
parent | 681ca59b6f81a3a0057e3d528c27bcf96c2edd1b (diff) | |
download | gitlab-ce-89eff770d213e684b5fa4df121cb51a059e8d263.tar.gz |
Add latest changes from gitlab-org/gitlab@master
34 files changed, 325 insertions, 345 deletions
diff --git a/app/assets/javascripts/monitoring/components/charts/time_series.vue b/app/assets/javascripts/monitoring/components/charts/time_series.vue index e7cd612409f..054111c203e 100644 --- a/app/assets/javascripts/monitoring/components/charts/time_series.vue +++ b/app/assets/javascripts/monitoring/components/charts/time_series.vue @@ -1,6 +1,6 @@ <script> import { isEmpty, omit, throttle } from 'lodash'; -import { GlLink, GlDeprecatedButton, GlTooltip, GlResizeObserverDirective } from '@gitlab/ui'; +import { GlLink, GlTooltip, GlResizeObserverDirective } from '@gitlab/ui'; import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts'; import { s__ } from '~/locale'; import { getSvgIconPathContent } from '~/lib/utils/icon_utils'; @@ -25,7 +25,6 @@ export default { GlAreaChart, GlLineChart, GlTooltip, - GlDeprecatedButton, GlChartSeriesLabel, GlLink, Icon, diff --git a/app/graphql/resolvers/ci_configuration/sast_resolver.rb b/app/graphql/resolvers/ci_configuration/sast_resolver.rb deleted file mode 100644 index e8c42076ea2..00000000000 --- a/app/graphql/resolvers/ci_configuration/sast_resolver.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -require "json" - -module Resolvers - module CiConfiguration - class SastResolver < BaseResolver - SAST_UI_SCHEMA_PATH = 'app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json' - - type ::Types::CiConfiguration::Sast::Type, null: true - - def resolve(**args) - Gitlab::Json.parse(File.read(Rails.root.join(SAST_UI_SCHEMA_PATH))) - end - end - end -end diff --git a/app/graphql/resolvers/project_pipeline_resolver.rb b/app/graphql/resolvers/project_pipeline_resolver.rb index 5bafe3dd140..181c1e77109 100644 --- a/app/graphql/resolvers/project_pipeline_resolver.rb +++ b/app/graphql/resolvers/project_pipeline_resolver.rb @@ -10,7 +10,7 @@ module Resolvers def resolve(iid:) BatchLoader::GraphQL.for(iid).batch(key: project) do |iids, loader, args| - args[:key].ci_pipelines.for_iid(iids).each { |pl| loader.call(pl.iid.to_s, pl) } + args[:key].all_pipelines.for_iid(iids).each { |pl| loader.call(pl.iid.to_s, pl) } end end end diff --git a/app/graphql/types/ci/pipeline_config_source_enum.rb b/app/graphql/types/ci/pipeline_config_source_enum.rb new file mode 100644 index 00000000000..48f88c133b4 --- /dev/null +++ b/app/graphql/types/ci/pipeline_config_source_enum.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Types + module Ci + class PipelineConfigSourceEnum < BaseEnum + ::Ci::PipelineEnums.config_sources.keys.each do |state_symbol| + value state_symbol.to_s.upcase, value: state_symbol.to_s + end + end + end +end diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb index caa7079e2c6..c9cbae2d828 100644 --- a/app/graphql/types/ci/pipeline_type.rb +++ b/app/graphql/types/ci/pipeline_type.rb @@ -25,6 +25,8 @@ module Types field :detailed_status, Types::Ci::DetailedStatusType, null: false, description: 'Detailed status of the pipeline', resolve: -> (obj, _args, ctx) { obj.detailed_status(ctx[:current_user]) } + field :config_source, PipelineConfigSourceEnum, null: true, + description: "Config source of the pipeline (#{::Ci::PipelineEnums.config_sources.keys.join(', ').upcase})" field :duration, GraphQL::INT_TYPE, null: true, description: 'Duration of the pipeline in seconds' field :coverage, GraphQL::FLOAT_TYPE, null: true, diff --git a/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb b/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb deleted file mode 100644 index ccd1c7dd0eb..00000000000 --- a/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -module Types - module CiConfiguration - module Sast - # rubocop: disable Graphql/AuthorizeTypes - class AnalyzersEntityType < BaseObject - graphql_name 'SastCiConfigurationAnalyzersEntity' - description 'Represents an analyzer entity in SAST CI configuration' - - field :name, GraphQL::STRING_TYPE, null: true, - description: 'Name of the analyzer.' - - field :label, GraphQL::STRING_TYPE, null: true, - description: 'Analyzer label used in the config UI.' - - field :enabled, GraphQL::BOOLEAN_TYPE, null: true, - description: 'Indicates whether an analyzer is enabled.' - - field :description, GraphQL::STRING_TYPE, null: true, - description: 'Analyzer description that is displayed on the form.' - end - end - end -end diff --git a/app/graphql/types/ci_configuration/sast/entity_type.rb b/app/graphql/types/ci_configuration/sast/entity_type.rb deleted file mode 100644 index b61b582ad20..00000000000 --- a/app/graphql/types/ci_configuration/sast/entity_type.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true - -module Types - module CiConfiguration - module Sast - # rubocop: disable Graphql/AuthorizeTypes - class EntityType < BaseObject - graphql_name 'SastCiConfigurationEntity' - description 'Represents an entity in SAST CI configuration' - - field :field, GraphQL::STRING_TYPE, null: true, - description: 'CI keyword of entity.' - - field :label, GraphQL::STRING_TYPE, null: true, - description: 'Label for entity used in the form.' - - field :type, GraphQL::STRING_TYPE, null: true, - description: 'Type of the field value.' - - field :options, ::Types::CiConfiguration::Sast::OptionsEntityType.connection_type, null: true, - description: 'Different possible values of the field.' - - field :default_value, GraphQL::STRING_TYPE, null: true, - description: 'Default value that is used if value is empty.' - - field :description, GraphQL::STRING_TYPE, null: true, - description: 'Entity description that is displayed on the form.' - - field :value, GraphQL::STRING_TYPE, null: true, - description: 'Current value of the entity.' - end - end - end -end diff --git a/app/graphql/types/ci_configuration/sast/options_entity_type.rb b/app/graphql/types/ci_configuration/sast/options_entity_type.rb deleted file mode 100644 index 86d104a7fda..00000000000 --- a/app/graphql/types/ci_configuration/sast/options_entity_type.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -module Types - module CiConfiguration - module Sast - # rubocop: disable Graphql/AuthorizeTypes - class OptionsEntityType < BaseObject - graphql_name 'SastCiConfigurationOptionsEntity' - description 'Represents an entity for options in SAST CI configuration' - - field :label, GraphQL::STRING_TYPE, null: true, - description: 'Label of option entity.' - - field :value, GraphQL::STRING_TYPE, null: true, - description: 'Value of option entity.' - end - end - end -end diff --git a/app/graphql/types/ci_configuration/sast/type.rb b/app/graphql/types/ci_configuration/sast/type.rb deleted file mode 100644 index 35d11584ac7..00000000000 --- a/app/graphql/types/ci_configuration/sast/type.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -module Types - module CiConfiguration - module Sast - # rubocop: disable Graphql/AuthorizeTypes - class Type < BaseObject - graphql_name 'SastCiConfiguration' - description 'Represents a CI configuration of SAST' - - field :global, ::Types::CiConfiguration::Sast::EntityType.connection_type, null: true, - description: 'List of global entities related to SAST configuration.' - - field :pipeline, ::Types::CiConfiguration::Sast::EntityType.connection_type, null: true, - description: 'List of pipeline entities related to SAST configuration.' - - field :analyzers, ::Types::CiConfiguration::Sast::AnalyzersEntityType.connection_type, null: true, - description: 'List of analyzers entities attached to SAST configuration.' - end - end - end -end diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb index 523e019b955..5562db69de6 100644 --- a/app/graphql/types/project_type.rb +++ b/app/graphql/types/project_type.rb @@ -175,10 +175,6 @@ module Types description: 'A single environment of the project', resolver: Resolvers::EnvironmentsResolver.single - field :sast_ci_configuration, ::Types::CiConfiguration::Sast::Type, null: true, - description: 'SAST CI configuration for the project', - resolver: ::Resolvers::CiConfiguration::SastResolver - field :issue, Types::IssueType, null: true, diff --git a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json index cce2b28529f..aa4dd60a9fb 100644 --- a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json +++ b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json @@ -4,83 +4,43 @@ "field" : "SECURE_ANALYZERS_PREFIX", "label" : "Image prefix", "type": "string", - "default_value": "registry.gitlab.com/gitlab-org/security-products/analyzers", - "value": "" + "default_value": "", + "value": "", + "description": "Analyzer image's registry prefix (or Name of the registry providing the analyzers' image)" }, { "field" : "SAST_EXCLUDED_PATHS", "label" : "Excluded Paths", "type": "string", - "default_value": "spec, test, tests, tmp", - "value": "" + "default_value": "", + "value": "", + "description": "Comma-separated list of paths to be excluded from analyzer output. Patterns can be globs, file paths, or folder paths." }, { "field" : "SAST_ANALYZER_IMAGE_TAG", "label" : "Image tag", "type": "string", - "options": [], - "default_value": "2", - "value": "" - }, - { - "field" : "SAST_DISABLED", - "label" : "Disable SAST", - "type": "options", - "options": [ - { - "value" :"true", - "label" : "true (disables SAST)" - }, - { - "value":"false", - "label":"false (enables SAST)" - } - ], - "default_value": "false", - "value": "" + "default_value": "", + "value": "", + "description": "Analyzer image's tag" } ], "pipeline": [ { "field" : "stage", "label" : "Stage", - "type": "dropdown", - "options": [ - { - "value" :"test", - "label" : "test" - }, - { - "value":"build", - "label":"build" - } - ], - "default_value": "test", - "value": "" - }, - { - "field" : "allow_failure", - "label" : "Allow Failure", - "type": "options", - "options": [ - { - "value" :"true", - "label" : "Allows pipeline failure" - }, - { - "value": "false", - "label": "Does not allow pipeline failure" - } - ], - "default_value": "true", - "value": "" + "type": "string", + "default_value": "", + "value": "", + "description": "Pipeline stage in which the scan jobs run" }, { - "field" : "rules", - "label" : "Rules", - "type": "multiline", + "field" : "SEARCH_MAX_DEPTH", + "label" : "Search maximum depth", + "type": "string", "default_value": "", - "value": "" + "value": "", + "description": "Maximum depth of language and framework detection" } ], "analyzers": [ diff --git a/changelogs/unreleased/229914-remove-constraint-on-audit-event-type.yml b/changelogs/unreleased/229914-remove-constraint-on-audit-event-type.yml new file mode 100644 index 00000000000..d218fa007cd --- /dev/null +++ b/changelogs/unreleased/229914-remove-constraint-on-audit-event-type.yml @@ -0,0 +1,5 @@ +--- +title: Remove not-null constraint on type column in audit_events +merge_request: 39192 +author: +type: other diff --git a/changelogs/unreleased/null-pipeline-in-graphql-response-224687.yml b/changelogs/unreleased/null-pipeline-in-graphql-response-224687.yml new file mode 100644 index 00000000000..f3490df8178 --- /dev/null +++ b/changelogs/unreleased/null-pipeline-in-graphql-response-224687.yml @@ -0,0 +1,5 @@ +--- +title: Allow GraphQL pipeline to resolve non-CI pipelines and expose configSource field +merge_request: 39275 +author: +type: added diff --git a/db/migrate/20200811055018_remove_not_null_constraint_on_type_from_audit_events.rb b/db/migrate/20200811055018_remove_not_null_constraint_on_type_from_audit_events.rb new file mode 100644 index 00000000000..629f357cd19 --- /dev/null +++ b/db/migrate/20200811055018_remove_not_null_constraint_on_type_from_audit_events.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +class RemoveNotNullConstraintOnTypeFromAuditEvents < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + # rubocop:disable Migration/WithLockRetriesDisallowedMethod + # To avoid deadlock on audit_event and audit_event_part... since there is a trigger to insert record from audit_events + # to audit_events_part..., we need to ensure each ALTER TABLE command run in its own transaction. + def up + with_lock_retries do + change_column_null :audit_events_part_5fc467ac26, :type, true + end + + with_lock_retries do + change_column_null :audit_events, :type, true + end + end + # rubocop:enable Migration/WithLockRetriesDisallowedMethod + + def down + # no-op -- null values might be added after this constraint is removed. + end +end diff --git a/db/schema_migrations/20200811055018 b/db/schema_migrations/20200811055018 new file mode 100644 index 00000000000..abf090f8281 --- /dev/null +++ b/db/schema_migrations/20200811055018 @@ -0,0 +1 @@ +b7477fbcba166d848e3b1bd7f4a184f50f3b2fafe80bfcf44fd6f4f9979ffcb7
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 62cb3964bb9..8b14be0905b 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -68,7 +68,7 @@ COMMENT ON FUNCTION public.table_sync_function_2be879775d() IS 'Partitioning mig CREATE TABLE public.audit_events_part_5fc467ac26 ( id bigint NOT NULL, author_id integer NOT NULL, - type character varying NOT NULL, + type character varying, entity_id integer NOT NULL, entity_type character varying NOT NULL, details text, @@ -9466,7 +9466,7 @@ CREATE TABLE public.ar_internal_metadata ( CREATE TABLE public.audit_events ( id integer NOT NULL, author_id integer NOT NULL, - type character varying NOT NULL, + type character varying, entity_id integer NOT NULL, entity_type character varying NOT NULL, details text, diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql index 9263dce0898..387867309b8 100644 --- a/doc/api/graphql/reference/gitlab_schema.graphql +++ b/doc/api/graphql/reference/gitlab_schema.graphql @@ -10262,6 +10262,13 @@ type Pipeline { committedAt: Time """ + Config source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, + AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, + BRIDGE_SOURCE, PARAMETER_SOURCE) + """ + configSource: PipelineConfigSourceEnum + + """ Coverage percentage """ coverage: Float @@ -10353,6 +10360,17 @@ type Pipeline { userPermissions: PipelinePermissions! } +enum PipelineConfigSourceEnum { + AUTO_DEVOPS_SOURCE + BRIDGE_SOURCE + EXTERNAL_PROJECT_SOURCE + PARAMETER_SOURCE + REMOTE_SOURCE + REPOSITORY_SOURCE + UNKNOWN_SOURCE + WEBIDE_SOURCE +} + """ The connection type for Pipeline. """ diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json index 1d791644909..b2d2bd61d5b 100644 --- a/doc/api/graphql/reference/gitlab_schema.json +++ b/doc/api/graphql/reference/gitlab_schema.json @@ -30653,6 +30653,20 @@ "deprecationReason": null }, { + "name": "configSource", + "description": "Config source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, BRIDGE_SOURCE, PARAMETER_SOURCE)", + "args": [ + + ], + "type": { + "kind": "ENUM", + "name": "PipelineConfigSourceEnum", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "coverage", "description": "Coverage percentage", "args": [ @@ -30928,6 +30942,65 @@ "possibleTypes": null }, { + "kind": "ENUM", + "name": "PipelineConfigSourceEnum", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "UNKNOWN_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "REPOSITORY_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "AUTO_DEVOPS_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEBIDE_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "REMOTE_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EXTERNAL_PROJECT_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "BRIDGE_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PARAMETER_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { "kind": "OBJECT", "name": "PipelineConnection", "description": "The connection type for Pipeline.", diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index fac5357dc78..dd2fa5e191b 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -1571,6 +1571,7 @@ Information about pagination in a connection. | --- | ---- | ---------- | | `beforeSha` | String | Base SHA of the source branch | | `committedAt` | Time | Timestamp of the pipeline's commit | +| `configSource` | PipelineConfigSourceEnum | Config source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, BRIDGE_SOURCE, PARAMETER_SOURCE) | | `coverage` | Float | Coverage percentage | | `createdAt` | Time! | Timestamp of the pipeline's creation | | `detailedStatus` | DetailedStatus! | Detailed status of the pipeline | diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index db2aff9b25a..f2a7da73120 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -306,6 +306,7 @@ module Gitlab Gitlab::UsageData::Topology.new.topology_usage_data end + # rubocop: disable UsageData/DistinctCountByLargeForeignKey def ingress_modsecurity_usage ## # This method measures usage of the Modsecurity Web Application Firewall across the entire @@ -326,6 +327,7 @@ module Gitlab ingress_modsecurity_not_installed: distinct_count(successful_deployments_with_cluster(::Clusters::Applications::Ingress.modsecurity_not_installed), column) } end + # rubocop: enable UsageData/DistinctCountByLargeForeignKey # rubocop: disable CodeReuse/ActiveRecord def container_expiration_policies_usage @@ -729,9 +731,11 @@ module Gitlab end # rubocop: disable CodeReuse/ActiveRecord + # rubocop: disable UsageData/DistinctCountByLargeForeignKey def cluster_applications_user_distinct_count(applications, time_period) distinct_count(applications.where(time_period).available.joins(:cluster), 'clusters.user_id') end + # rubocop: enable UsageData/DistinctCountByLargeForeignKey def clusters_user_distinct_count(clusters, time_period) distinct_count(clusters.where(time_period), :user_id) diff --git a/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb b/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb new file mode 100644 index 00000000000..098410e5ad2 --- /dev/null +++ b/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module UsageData + # Allows counts only for selected tables' foreign keys for `distinct_count` method. + # + # Because distinct_counts over large tables' foreign keys will take a long time + # + # @example + # + # # bad because pipeline_id points to a large table + # distinct_count(Ci::Build, :commit_id) + # + class DistinctCountByLargeForeignKey < RuboCop::Cop::Cop + MSG = 'Avoid doing `%s` for large foreign keys.'.freeze + + def_node_matcher :distinct_count?, <<-PATTERN + (send _ $:distinct_count $...) + PATTERN + + def on_send(node) + distinct_count?(node) do |method_name, method_arguments| + next unless method_arguments && method_arguments.length >= 2 + next if allowed_foreign_key?(method_arguments[1]) + + add_offense(node, location: :selector, message: format(MSG, method_name)) + end + end + + private + + def allowed_foreign_key?(key) + key.type == :sym && allowed_foreign_keys.include?(key.value) + end + + def allowed_foreign_keys + cop_config['AllowedForeignKeys'] || [] + end + end + end + end +end diff --git a/rubocop/rubocop-usage-data.yml b/rubocop/rubocop-usage-data.yml index 887d7aa9427..bd0dd58dcdf 100644 --- a/rubocop/rubocop-usage-data.yml +++ b/rubocop/rubocop-usage-data.yml @@ -30,3 +30,16 @@ UsageData/LargeTable: - :arel_table - :minimum - :maximum +UsageData/DistinctCountByLargeForeignKey: + Enabled: true + Include: + - 'lib/gitlab/usage_data.rb' + - 'ee/lib/ee/gitlab/usage_data.rb' + AllowedForeignKeys: + - :user_id + - :author_id + - :creator_id + - :owner_id + - :project_id + - :issue_id + - :merge_request_id diff --git a/spec/graphql/resolvers/ci_configuration/sast_resolver_spec.rb b/spec/graphql/resolvers/ci_configuration/sast_resolver_spec.rb deleted file mode 100644 index de69ad5d450..00000000000 --- a/spec/graphql/resolvers/ci_configuration/sast_resolver_spec.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Resolvers::CiConfiguration::SastResolver do - include GraphqlHelpers - - let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project) } - - describe '#resolve' do - subject(:sast_config) { resolve(described_class, ctx: { current_user: user }, obj: project) } - - it 'returns global variable informations related to SAST' do - expect(sast_config['global'].first['field']).to eql("SECURE_ANALYZERS_PREFIX") - expect(sast_config['global'].first['label']).to eql("Image prefix") - expect(sast_config['global'].first['type']).to eql("string") - - expect(sast_config['pipeline'].first['field']).to eql("stage") - expect(sast_config['pipeline'].first['label']).to eql("Stage") - expect(sast_config['pipeline'].first['type']).to eql("dropdown") - - expect(sast_config['analyzers'].first['name']).to eql("brakeman") - expect(sast_config['analyzers'].first['label']).to eql("Brakeman") - expect(sast_config['analyzers'].first['enabled']).to be true - end - end -end diff --git a/spec/graphql/resolvers/project_pipeline_resolver_spec.rb b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb index a659b3bdb6e..fada2f9193c 100644 --- a/spec/graphql/resolvers/project_pipeline_resolver_spec.rb +++ b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb @@ -33,4 +33,21 @@ RSpec.describe Resolvers::ProjectPipelineResolver do it 'errors when no iid is passed' do expect { resolve_pipeline(project, {}) }.to raise_error(ArgumentError) end + + context 'when the pipeline is not a ci_config_source' do + let(:pipeline) do + config_source_value = Ci::PipelineEnums.non_ci_config_source_values.first + config_source = Ci::PipelineEnums.config_sources.key(config_source_value) + + create(:ci_pipeline, config_source: config_source, project: project) + end + + it 'resolves pipeline for the passed iid' do + result = batch_sync do + resolve_pipeline(project, { iid: pipeline.iid.to_s }) + end + + expect(result).to eq(pipeline) + end + end end diff --git a/spec/graphql/types/ci_configuration/sast/analyzers_entity_type_spec.rb b/spec/graphql/types/ci_configuration/sast/analyzers_entity_type_spec.rb deleted file mode 100644 index 34a22feeaf5..00000000000 --- a/spec/graphql/types/ci_configuration/sast/analyzers_entity_type_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe GitlabSchema.types['SastCiConfigurationAnalyzersEntity'] do - let(:fields) { %i[name label enabled description] } - - it { expect(described_class.graphql_name).to eq('SastCiConfigurationAnalyzersEntity') } - - it { expect(described_class).to have_graphql_fields(fields) } -end diff --git a/spec/graphql/types/ci_configuration/sast/entity_type_spec.rb b/spec/graphql/types/ci_configuration/sast/entity_type_spec.rb deleted file mode 100644 index 7c6ad013d4a..00000000000 --- a/spec/graphql/types/ci_configuration/sast/entity_type_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe GitlabSchema.types['SastCiConfigurationEntity'] do - let(:fields) { %i[field label description type options default_value value] } - - it { expect(described_class.graphql_name).to eq('SastCiConfigurationEntity') } - - it { expect(described_class).to have_graphql_fields(fields) } -end diff --git a/spec/graphql/types/ci_configuration/sast/options_entity_spec.rb b/spec/graphql/types/ci_configuration/sast/options_entity_spec.rb deleted file mode 100644 index c60c8b9c84a..00000000000 --- a/spec/graphql/types/ci_configuration/sast/options_entity_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe GitlabSchema.types['SastCiConfigurationOptionsEntity'] do - let(:fields) { %i[label value] } - - it { expect(described_class.graphql_name).to eq('SastCiConfigurationOptionsEntity') } - - it { expect(described_class).to have_graphql_fields(fields) } -end diff --git a/spec/graphql/types/ci_configuration/sast/type_spec.rb b/spec/graphql/types/ci_configuration/sast/type_spec.rb deleted file mode 100644 index e7a8cd436e4..00000000000 --- a/spec/graphql/types/ci_configuration/sast/type_spec.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe GitlabSchema.types['SastCiConfiguration'] do - let(:fields) { %i[global pipeline analyzers] } - - it { expect(described_class.graphql_name).to eq('SastCiConfiguration') } - - it { expect(described_class).to have_graphql_fields(fields) } -end diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb index a0b6858fc99..8a5d0cdf12d 100644 --- a/spec/graphql/types/project_type_spec.rb +++ b/spec/graphql/types/project_type_spec.rb @@ -26,7 +26,7 @@ RSpec.describe GitlabSchema.types['Project'] do grafanaIntegration autocloseReferencedIssues suggestion_commit_message environments environment boards jira_import_status jira_imports services releases release alert_management_alerts alert_management_alert alert_management_alert_status_counts - container_expiration_policy sast_ci_configuration service_desk_enabled service_desk_address + container_expiration_policy service_desk_enabled service_desk_address issue_status_counts ] @@ -150,93 +150,5 @@ RSpec.describe GitlabSchema.types['Project'] do it { is_expected.to have_graphql_type(Types::ContainerExpirationPolicyType) } end - describe 'sast_ci_configuration' do - let_it_be(:project) { create(:project) } - let_it_be(:user) { create(:user) } - let_it_be(:query) do - %( - query { - project(fullPath: "#{project.full_path}") { - sastCiConfiguration { - global { - nodes { - type - options { - nodes { - label - value - } - } - field - label - defaultValue - value - } - } - pipeline { - nodes { - type - options { - nodes { - label - value - } - } - field - label - defaultValue - value - } - } - analyzers { - nodes { - name - label - enabled - } - } - } - } - } - ) - end - - subject { GitlabSchema.execute(query, context: { current_user: user }).as_json } - - before do - project.add_developer(user) - end - - it "returns the project's sast configuration for global variables" do - query_result = subject.dig('data', 'project', 'sastCiConfiguration', 'global', 'nodes') - first_config = query_result.first - fourth_config = query_result[3] - expect(first_config['type']).to eq('string') - expect(first_config['field']).to eq('SECURE_ANALYZERS_PREFIX') - expect(first_config['label']).to eq('Image prefix') - expect(first_config['defaultValue']).to eq('registry.gitlab.com/gitlab-org/security-products/analyzers') - expect(first_config['value']).to eq('') - expect(first_config['options']).to be_nil - expect(fourth_config['options']['nodes']).to match([{ "value" => "true", "label" => "true (disables SAST)" }, - { "value" => "false", "label" => "false (enables SAST)" }]) - end - - it "returns the project's sast configuration for pipeline variables" do - configuration = subject.dig('data', 'project', 'sastCiConfiguration', 'pipeline', 'nodes').first - expect(configuration['type']).to eq('dropdown') - expect(configuration['field']).to eq('stage') - expect(configuration['label']).to eq('Stage') - expect(configuration['defaultValue']).to eq('test') - expect(configuration['value']).to eq('') - end - - it "returns the project's sast configuration for analyzer variables" do - configuration = subject.dig('data', 'project', 'sastCiConfiguration', 'analyzers', 'nodes').first - expect(configuration['name']).to eq('brakeman') - expect(configuration['label']).to eq('Brakeman') - expect(configuration['enabled']).to eq(true) - end - end - it_behaves_like 'a GraphQL type with labels' end diff --git a/spec/models/audit_event_partitioned_spec.rb b/spec/models/audit_event_partitioned_spec.rb index 381e755091a..fe69f0083b7 100644 --- a/spec/models/audit_event_partitioned_spec.rb +++ b/spec/models/audit_event_partitioned_spec.rb @@ -10,6 +10,13 @@ RSpec.describe AuditEventPartitioned do expect(partitioned_table.column_names).to match_array(source_table.column_names) end + it 'has the same null constraints as the source table' do + constraints_from_source_table = null_constraints(source_table) + constraints_from_partitioned_table = null_constraints(partitioned_table) + + expect(constraints_from_partitioned_table.to_a).to match_array(constraints_from_source_table.to_a) + end + it 'inserts the same record as the one in the source table', :aggregate_failures do expect { create(:audit_event) }.to change { partitioned_table.count }.by(1) @@ -22,4 +29,13 @@ RSpec.describe AuditEventPartitioned do expect(event_from_partitioned_table).to eq(event_from_source_table) end + + def null_constraints(table) + table.connection.select_all(<<~SQL) + SELECT c.column_name, c.is_nullable + FROM information_schema.columns c + WHERE c.table_name = '#{table.table_name}' + AND c.column_name != 'created_at' + SQL + end end diff --git a/spec/requests/api/graphql/project/pipeline_spec.rb b/spec/requests/api/graphql/project/pipeline_spec.rb index 57b9de25c3d..fef0e7e160c 100644 --- a/spec/requests/api/graphql/project/pipeline_spec.rb +++ b/spec/requests/api/graphql/project/pipeline_spec.rb @@ -29,4 +29,10 @@ RSpec.describe 'getting pipeline information nested in a project' do expect(pipeline_graphql_data).not_to be_nil end + + it 'contains configSource' do + post_graphql(query, current_user: current_user) + + expect(pipeline_graphql_data.dig('configSource')).to eq('UNKNOWN_SOURCE') + end end diff --git a/spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb b/spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb new file mode 100644 index 00000000000..db931c50bdf --- /dev/null +++ b/spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' + +require 'rubocop' +require 'rubocop/rspec/support' + +require_relative '../../../../rubocop/cop/usage_data/distinct_count_by_large_foreign_key' + +RSpec.describe RuboCop::Cop::UsageData::DistinctCountByLargeForeignKey, type: :rubocop do + include CopHelper + + let(:allowed_foreign_keys) { %i[author_id user_id] } + + let(:config) do + RuboCop::Config.new('UsageData/DistinctCountByLargeForeignKey' => { + 'AllowedForeignKeys' => allowed_foreign_keys + }) + end + + subject(:cop) { described_class.new(config) } + + context 'when counting by disallowed key' do + it 'register an offence' do + inspect_source('distinct_count(Issue, :creator_id)') + + expect(cop.offenses.size).to eq(1) + end + end + + context 'when calling by allowed key' do + it 'does not register an offence' do + inspect_source('distinct_count(Issue, :author_id)') + + expect(cop.offenses).to be_empty + end + end +end diff --git a/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml b/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml new file mode 100644 index 00000000000..4134660e4b9 --- /dev/null +++ b/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml @@ -0,0 +1,13 @@ +include: + - template: SAST.gitlab-ci.yml + +variables: + SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers2" + SAST_EXCLUDED_PATHS: "spec, executables" + +stages: + - our_custom_security_stage +sast: + stage: our_custom_security_stage + variables: + SEARCH_MAX_DEPTH: 8 diff --git a/spec/support/shared_contexts/read_ci_configuration_shared_context.rb b/spec/support/shared_contexts/read_ci_configuration_shared_context.rb new file mode 100644 index 00000000000..f8f33e2a745 --- /dev/null +++ b/spec/support/shared_contexts/read_ci_configuration_shared_context.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +RSpec.shared_context 'read ci configuration for sast enabled project' do + let_it_be(:gitlab_ci_yml_content) do + File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_for_sast.yml')) + end + + let_it_be(:project) { create(:project, :repository) } +end |