Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-07-06 03:09:07 +00:00
parent 03ae05df34
commit fbf952e174
29 changed files with 1716 additions and 2 deletions

View file

@ -1 +1 @@
2.3.0
2.4.0

View file

@ -0,0 +1,3 @@
import monitoringApp from '~/monitoring/monitoring_app';
document.addEventListener('DOMContentLoaded', monitoringApp);

View file

@ -1,6 +1,10 @@
# frozen_string_literal: true
class Projects::EnvironmentsController < Projects::ApplicationController
# Metrics dashboard code is getting decoupled from environments and is being moved
# into app/controllers/projects/metrics_dashboard_controller.rb
# See https://gitlab.com/gitlab-org/gitlab/-/issues/226002 for more details.
include MetricsDashboard
layout 'project'

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
module Projects
class MetricsDashboardController < Projects::ApplicationController
# Metrics dashboard code is in the process of being decoupled from environments
# and is getting moved to this controller. Some code may be duplicated from
# app/controllers/projects/environments_controller.rb
# See https://gitlab.com/gitlab-org/gitlab/-/issues/226002 for more details.
before_action :authorize_metrics_dashboard!
before_action do
push_frontend_feature_flag(:prometheus_computed_alerts)
end
def show
if environment
render 'projects/environments/metrics'
else
render_404
end
end
private
def environment
@environment ||=
if params[:environment]
project.environments.find(params[:environment])
else
project.default_environment
end
end
end
end

View file

@ -0,0 +1,17 @@
# 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

View file

@ -0,0 +1,25 @@
# 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

View file

@ -0,0 +1,34 @@
# 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

View file

@ -0,0 +1,19 @@
# 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

View file

@ -0,0 +1,22 @@
# 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

View file

@ -153,6 +153,10 @@ module Types
description: 'Environments of the project',
resolver: Resolvers::EnvironmentsResolver
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,

View file

@ -0,0 +1,158 @@
{
"global": [
{
"field" : "SECURE_ANALYZERS_PREFIX",
"label" : "Image prefix",
"type": "string",
"default_value": "registry.gitlab.com/gitlab-org/security-products/analyzers",
"value": ""
},
{
"field" : "SAST_EXCLUDED_PATHS",
"label" : "Excluded Paths",
"type": "string",
"default_value": "spec, test, tests, tmp",
"value": ""
},
{
"field" : "SECURE_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": ""
}
],
"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": ""
},
{
"field" : "rules",
"label" : "Rules",
"type": "multiline",
"default_value": "",
"value": ""
}
],
"analyzers": [
{
"name": "brakeman",
"label": "Brakeman",
"enabled" : true
},
{
"name": "bandit",
"label": "Bandit",
"enabled" : true
},
{
"name": "eslint",
"label": "ESLint",
"enabled" : true
},
{
"name": "flawfinder",
"label": "Flawfinder",
"enabled" : true
},
{
"name": "kubesec",
"label": "kubesec",
"enabled" : true
},
{
"name": "nodejsscan",
"label": "Node.js Scan",
"enabled" : true
},
{
"name": "gosec",
"label": "Golang Security Checker",
"enabled" : true
},
{
"name": "phpcs-security-audit",
"label": "PHP Security Audit",
"enabled" : true
},
{
"name": "pmd-apex",
"label": "PMD APEX",
"enabled" : true
},
{
"name": "security-code-scan",
"label": "Security Code Scan",
"enabled" : true
},
{
"name": "sobelow",
"label": "Sobelow",
"enabled" : true
},
{
"name": "spotbugs",
"label": "Spotbugs",
"enabled" : true
},
{
"name": "tslint",
"label": "TSLint",
"enabled" : true
},
{
"name": "secrets",
"label": "Secrets",
"enabled" : true
}
]
}

View file

@ -0,0 +1,5 @@
---
title: Database migration to add project_settings.has_confluence
merge_request: 35485
author:
type: other

View file

@ -0,0 +1,5 @@
---
title: Update GitLab Elasticsearch Indexer
merge_request: 35966
author:
type: other

View file

@ -0,0 +1,5 @@
---
title: Add new path to access project metrics dashboard
merge_request: 33905
author:
type: added

View file

@ -0,0 +1,5 @@
---
title: Implement GraphQL query to generate JSON for SAST config UI
merge_request: 35397
author:
type: added

View file

@ -25,6 +25,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
# Use this scope for all new project routes.
scope '-' do
get 'archive/*id', constraints: { format: Gitlab::PathRegex.archive_formats_regex, id: /.+?/ }, to: 'repositories#archive', as: 'archive'
get 'metrics(/:dashboard_path)', constraints: { dashboard_path: /.+\.yml/ },
to: 'metrics_dashboard#show', as: :metrics_dashboard, format: false
resources :artifacts, only: [:index, :destroy]

View file

@ -0,0 +1,19 @@
# frozen_string_literal: true
class AddHasConfluenceToProjectSettings < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
with_lock_retries do
add_column :project_settings, :has_confluence, :boolean, default: false, null: false
end
end
def down
with_lock_retries do
remove_column :project_settings, :has_confluence
end
end
end

View file

@ -14191,6 +14191,7 @@ CREATE TABLE public.project_settings (
show_default_award_emojis boolean DEFAULT true,
allow_merge_on_skipped_pipeline boolean,
squash_option smallint DEFAULT 3,
has_confluence boolean DEFAULT false NOT NULL,
CONSTRAINT check_bde223416c CHECK ((show_default_award_emojis IS NOT NULL))
);
@ -23517,6 +23518,7 @@ COPY "schema_migrations" (version) FROM STDIN;
20200618105638
20200618134223
20200618134723
20200619000316
20200619154527
20200619154528
20200622040750

View file

@ -9636,6 +9636,11 @@ type Project {
state: RequirementState
): RequirementConnection
"""
SAST CI configuration for the project
"""
sastCiConfiguration: SastCiConfiguration
"""
Detailed version of a Sentry error on the project
"""
@ -11390,6 +11395,291 @@ type RunDASTScanPayload {
pipelineUrl: String
}
"""
Represents a CI configuration of SAST
"""
type SastCiConfiguration {
"""
List of analyzers entities attached to SAST configuration.
"""
analyzers(
"""
Returns the elements in the list that come after the specified cursor.
"""
after: String
"""
Returns the elements in the list that come before the specified cursor.
"""
before: String
"""
Returns the first _n_ elements from the list.
"""
first: Int
"""
Returns the last _n_ elements from the list.
"""
last: Int
): SastCiConfigurationAnalyzersEntityConnection
"""
List of global entities related to SAST configuration.
"""
global(
"""
Returns the elements in the list that come after the specified cursor.
"""
after: String
"""
Returns the elements in the list that come before the specified cursor.
"""
before: String
"""
Returns the first _n_ elements from the list.
"""
first: Int
"""
Returns the last _n_ elements from the list.
"""
last: Int
): SastCiConfigurationEntityConnection
"""
List of pipeline entities related to SAST configuration.
"""
pipeline(
"""
Returns the elements in the list that come after the specified cursor.
"""
after: String
"""
Returns the elements in the list that come before the specified cursor.
"""
before: String
"""
Returns the first _n_ elements from the list.
"""
first: Int
"""
Returns the last _n_ elements from the list.
"""
last: Int
): SastCiConfigurationEntityConnection
}
"""
Represents an analyzer entity in SAST CI configuration
"""
type SastCiConfigurationAnalyzersEntity {
"""
Analyzer description that is displayed on the form.
"""
description: String
"""
Indicates whether an analyzer is enabled.
"""
enabled: Boolean
"""
Analyzer label used in the config UI.
"""
label: String
"""
Name of the analyzer.
"""
name: String
}
"""
The connection type for SastCiConfigurationAnalyzersEntity.
"""
type SastCiConfigurationAnalyzersEntityConnection {
"""
A list of edges.
"""
edges: [SastCiConfigurationAnalyzersEntityEdge]
"""
A list of nodes.
"""
nodes: [SastCiConfigurationAnalyzersEntity]
"""
Information to aid in pagination.
"""
pageInfo: PageInfo!
}
"""
An edge in a connection.
"""
type SastCiConfigurationAnalyzersEntityEdge {
"""
A cursor for use in pagination.
"""
cursor: String!
"""
The item at the end of the edge.
"""
node: SastCiConfigurationAnalyzersEntity
}
"""
Represents an entity in SAST CI configuration
"""
type SastCiConfigurationEntity {
"""
Default value that is used if value is empty.
"""
defaultValue: String
"""
Entity description that is displayed on the form.
"""
description: String
"""
CI keyword of entity.
"""
field: String
"""
Label for entity used in the form.
"""
label: String
"""
Different possible values of the field.
"""
options(
"""
Returns the elements in the list that come after the specified cursor.
"""
after: String
"""
Returns the elements in the list that come before the specified cursor.
"""
before: String
"""
Returns the first _n_ elements from the list.
"""
first: Int
"""
Returns the last _n_ elements from the list.
"""
last: Int
): SastCiConfigurationOptionsEntityConnection
"""
Type of the field value.
"""
type: String
"""
Current value of the entity.
"""
value: String
}
"""
The connection type for SastCiConfigurationEntity.
"""
type SastCiConfigurationEntityConnection {
"""
A list of edges.
"""
edges: [SastCiConfigurationEntityEdge]
"""
A list of nodes.
"""
nodes: [SastCiConfigurationEntity]
"""
Information to aid in pagination.
"""
pageInfo: PageInfo!
}
"""
An edge in a connection.
"""
type SastCiConfigurationEntityEdge {
"""
A cursor for use in pagination.
"""
cursor: String!
"""
The item at the end of the edge.
"""
node: SastCiConfigurationEntity
}
"""
Represents an entity for options in SAST CI configuration
"""
type SastCiConfigurationOptionsEntity {
"""
Label of option entity.
"""
label: String
"""
Value of option entity.
"""
value: String
}
"""
The connection type for SastCiConfigurationOptionsEntity.
"""
type SastCiConfigurationOptionsEntityConnection {
"""
A list of edges.
"""
edges: [SastCiConfigurationOptionsEntityEdge]
"""
A list of nodes.
"""
nodes: [SastCiConfigurationOptionsEntity]
"""
Information to aid in pagination.
"""
pageInfo: PageInfo!
}
"""
An edge in a connection.
"""
type SastCiConfigurationOptionsEntityEdge {
"""
A cursor for use in pagination.
"""
cursor: String!
"""
The item at the end of the edge.
"""
node: SastCiConfigurationOptionsEntity
}
"""
Represents a resource scanned by a security scan
"""

View file

@ -28309,6 +28309,20 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "sastCiConfiguration",
"description": "SAST CI configuration for the project",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "SastCiConfiguration",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "sentryDetailedError",
"description": "Detailed version of a Sentry error on the project",
@ -33394,6 +33408,774 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "SastCiConfiguration",
"description": "Represents a CI configuration of SAST",
"fields": [
{
"name": "analyzers",
"description": "List of analyzers entities attached to SAST configuration.",
"args": [
{
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": "Returns the elements in the list that come before the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "first",
"description": "Returns the first _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "last",
"description": "Returns the last _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "SastCiConfigurationAnalyzersEntityConnection",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "global",
"description": "List of global entities related to SAST configuration.",
"args": [
{
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": "Returns the elements in the list that come before the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "first",
"description": "Returns the first _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "last",
"description": "Returns the last _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "SastCiConfigurationEntityConnection",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pipeline",
"description": "List of pipeline entities related to SAST configuration.",
"args": [
{
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": "Returns the elements in the list that come before the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "first",
"description": "Returns the first _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "last",
"description": "Returns the last _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "SastCiConfigurationEntityConnection",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "SastCiConfigurationAnalyzersEntity",
"description": "Represents an analyzer entity in SAST CI configuration",
"fields": [
{
"name": "description",
"description": "Analyzer description that is displayed on the form.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "enabled",
"description": "Indicates whether an analyzer is enabled.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "label",
"description": "Analyzer label used in the config UI.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"description": "Name of the analyzer.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "SastCiConfigurationAnalyzersEntityConnection",
"description": "The connection type for SastCiConfigurationAnalyzersEntity.",
"fields": [
{
"name": "edges",
"description": "A list of edges.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "SastCiConfigurationAnalyzersEntityEdge",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "nodes",
"description": "A list of nodes.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "SastCiConfigurationAnalyzersEntity",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pageInfo",
"description": "Information to aid in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "PageInfo",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "SastCiConfigurationAnalyzersEntityEdge",
"description": "An edge in a connection.",
"fields": [
{
"name": "cursor",
"description": "A cursor for use in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "node",
"description": "The item at the end of the edge.",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "SastCiConfigurationAnalyzersEntity",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "SastCiConfigurationEntity",
"description": "Represents an entity in SAST CI configuration",
"fields": [
{
"name": "defaultValue",
"description": "Default value that is used if value is empty.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "description",
"description": "Entity description that is displayed on the form.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "field",
"description": "CI keyword of entity.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "label",
"description": "Label for entity used in the form.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "options",
"description": "Different possible values of the field.",
"args": [
{
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": "Returns the elements in the list that come before the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "first",
"description": "Returns the first _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "last",
"description": "Returns the last _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "SastCiConfigurationOptionsEntityConnection",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "type",
"description": "Type of the field value.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "value",
"description": "Current value of the entity.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "SastCiConfigurationEntityConnection",
"description": "The connection type for SastCiConfigurationEntity.",
"fields": [
{
"name": "edges",
"description": "A list of edges.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "SastCiConfigurationEntityEdge",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "nodes",
"description": "A list of nodes.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "SastCiConfigurationEntity",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pageInfo",
"description": "Information to aid in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "PageInfo",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "SastCiConfigurationEntityEdge",
"description": "An edge in a connection.",
"fields": [
{
"name": "cursor",
"description": "A cursor for use in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "node",
"description": "The item at the end of the edge.",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "SastCiConfigurationEntity",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "SastCiConfigurationOptionsEntity",
"description": "Represents an entity for options in SAST CI configuration",
"fields": [
{
"name": "label",
"description": "Label of option entity.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "value",
"description": "Value of option entity.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "SastCiConfigurationOptionsEntityConnection",
"description": "The connection type for SastCiConfigurationOptionsEntity.",
"fields": [
{
"name": "edges",
"description": "A list of edges.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "SastCiConfigurationOptionsEntityEdge",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "nodes",
"description": "A list of nodes.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "SastCiConfigurationOptionsEntity",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pageInfo",
"description": "Information to aid in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "PageInfo",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "SastCiConfigurationOptionsEntityEdge",
"description": "An edge in a connection.",
"fields": [
{
"name": "cursor",
"description": "A cursor for use in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "node",
"description": "The item at the end of the edge.",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "SastCiConfigurationOptionsEntity",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "ScannedResource",

View file

@ -1391,6 +1391,7 @@ Information about pagination in a connection.
| `requestAccessEnabled` | Boolean | Indicates if users can request member access to the project |
| `requirement` | Requirement | Find a single requirement. Available only when feature flag `requirements_management` is enabled. |
| `requirementStatesCount` | RequirementStatesCount | Number of requirements for the project by their state |
| `sastCiConfiguration` | SastCiConfiguration | SAST CI configuration for the project |
| `sentryDetailedError` | SentryDetailedError | Detailed version of a Sentry error on the project |
| `sentryErrors` | SentryErrorCollection | Paginated collection of Sentry errors on the project |
| `serviceDeskAddress` | String | E-mail address of the service desk. |
@ -1638,6 +1639,39 @@ Autogenerated return type of RunDASTScan
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `pipelineUrl` | String | URL of the pipeline that was created. |
## SastCiConfigurationAnalyzersEntity
Represents an analyzer entity in SAST CI configuration
| Name | Type | Description |
| --- | ---- | ---------- |
| `description` | String | Analyzer description that is displayed on the form. |
| `enabled` | Boolean | Indicates whether an analyzer is enabled. |
| `label` | String | Analyzer label used in the config UI. |
| `name` | String | Name of the analyzer. |
## SastCiConfigurationEntity
Represents an entity in SAST CI configuration
| Name | Type | Description |
| --- | ---- | ---------- |
| `defaultValue` | String | Default value that is used if value is empty. |
| `description` | String | Entity description that is displayed on the form. |
| `field` | String | CI keyword of entity. |
| `label` | String | Label for entity used in the form. |
| `type` | String | Type of the field value. |
| `value` | String | Current value of the entity. |
## SastCiConfigurationOptionsEntity
Represents an entity for options in SAST CI configuration
| Name | Type | Description |
| --- | ---- | ---------- |
| `label` | String | Label of option entity. |
| `value` | String | Value of option entity. |
## ScannedResource
Represents a resource scanned by a security scan

View file

@ -0,0 +1,28 @@
# 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

View file

@ -0,0 +1,11 @@
# 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

View file

@ -0,0 +1,11 @@
# 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

View file

@ -0,0 +1,11 @@
# 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

View file

@ -0,0 +1,11 @@
# 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

View file

@ -26,7 +26,7 @@ RSpec.describe GitlabSchema.types['Project'] do
grafanaIntegration autocloseReferencedIssues suggestion_commit_message environments
boards jira_import_status jira_imports services releases release
alert_management_alerts alert_management_alert alert_management_alert_status_counts
container_expiration_policy
container_expiration_policy sast_ci_configuration
]
expect(described_class).to include_graphql_fields(*expected_fields)
@ -140,5 +140,93 @@ 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

View file

@ -705,6 +705,7 @@ ProjectCiCdSetting:
- group_runners_enabled
ProjectSetting:
- allow_merge_on_skipped_pipeline
- has_confluence
ProtectedEnvironment:
- id
- project_id

View file

@ -0,0 +1,85 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'metrics dashboard page' do
let_it_be(:project) { create(:project) }
let_it_be(:environment) { create(:environment, project: project) }
let_it_be(:environment2) { create(:environment, project: project) }
let_it_be(:user) { project.owner }
before do
project.add_developer(user)
login_as(user)
end
describe 'GET /:namespace/:project/-/metrics' do
it 'returns 200' do
send_request
expect(response).to have_gitlab_http_status(:ok)
end
it 'assigns environment' do
send_request
expect(assigns(:environment).id).to eq(environment.id)
end
end
describe 'GET /:namespace/:project/-/metrics?environment=:environment.id' do
it 'returns 200' do
send_request(environment: environment2.id)
expect(response).to have_gitlab_http_status(:ok)
end
it 'assigns query param environment' do
send_request(environment: environment2.id)
expect(assigns(:environment).id).to eq(environment2.id)
end
context 'when query param environment does not exist' do
it 'responds with 404' do
send_request(environment: 99)
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
describe 'GET /:namespace/:project/-/metrics/:dashboard_path' do
let(:dashboard_path) { '.gitlab/dashboards/dashboard_path.yml' }
it 'returns 200' do
send_request(dashboard_path: dashboard_path)
expect(response).to have_gitlab_http_status(:ok)
end
it 'assigns environment' do
send_request(dashboard_path: dashboard_path)
expect(assigns(:environment).id).to eq(environment.id)
end
end
describe 'GET :/namespace/:project/-/metrics/:dashboard_path?environment=:environment.id' do
let(:dashboard_path) { '.gitlab/dashboards/dashboard_path.yml' }
it 'returns 200' do
send_request(dahboard_path: dashboard_path, environment: environment.id)
expect(response).to have_gitlab_http_status(:ok)
end
it 'assigns query param environment' do
send_request(dashboard_path: dashboard_path, environment: environment2.id)
expect(assigns(:environment).id).to eq(environment2.id)
end
context 'when query param environment does not exist' do
it 'responds with 404' do
send_request(dashboard_path: dashboard_path, environment: 99)
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
def send_request(params = {})
get namespace_project_metrics_dashboard_path(namespace_id: project.namespace, project_id: project, **params)
end
end