Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-08-18 12:11:19 +00:00
parent 3b4c0d27d5
commit fba0187263
57 changed files with 367 additions and 877 deletions

View File

@ -6,10 +6,12 @@ import { mapState, mapGetters, mapActions } from 'vuex';
import BoardAddNewColumn from 'ee_else_ce/boards/components/board_add_new_column.vue';
import defaultSortableConfig from '~/sortable/sortable_config';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { DraggableItemTypes } from '../constants';
import BoardColumn from './board_column.vue';
import BoardColumnDeprecated from './board_column_deprecated.vue';
export default {
draggableItemTypes: DraggableItemTypes,
components: {
BoardAddNewColumn,
BoardColumn,
@ -99,6 +101,7 @@ export default {
:key="index"
ref="board"
:list="list"
:data-draggable-item-type="$options.draggableItemTypes.list"
:disabled="disabled"
/>

View File

@ -6,12 +6,13 @@ import { sortableStart, sortableEnd } from '~/boards/mixins/sortable_default_opt
import { sprintf, __ } from '~/locale';
import defaultSortableConfig from '~/sortable/sortable_config';
import Tracking from '~/tracking';
import { toggleFormEventPrefix } from '../constants';
import { toggleFormEventPrefix, DraggableItemTypes } from '../constants';
import eventHub from '../eventhub';
import BoardCard from './board_card.vue';
import BoardNewIssue from './board_new_issue.vue';
export default {
draggableItemTypes: DraggableItemTypes,
name: 'BoardList',
i18n: {
loading: __('Loading'),
@ -27,11 +28,6 @@ export default {
GlIntersectionObserver,
},
mixins: [Tracking.mixin()],
inject: {
canAdminList: {
default: false,
},
},
props: {
disabled: {
type: Boolean,
@ -89,8 +85,8 @@ export default {
return !this.isEpicBoard && this.list.listType !== 'closed' && this.showIssueForm;
},
listRef() {
// When list is draggable, the reference to the list needs to be accessed differently
return this.canAdminList ? this.$refs.list.$el : this.$refs.list;
// When list is draggable, the reference to the list needs to be accessed differently
return this.canMoveIssue ? this.$refs.list.$el : this.$refs.list;
},
showingAllItems() {
return this.boardItems.length === this.listItemsCount;
@ -100,8 +96,11 @@ export default {
? this.$options.i18n.showingAllEpics
: this.$options.i18n.showingAllIssues;
},
canMoveIssue() {
return !this.disabled;
},
treeRootWrapper() {
return this.canAdminList && !this.listsFlags[this.list.id]?.addItemToListInProgress
return this.canMoveIssue && !this.listsFlags[this.list.id]?.addItemToListInProgress
? Draggable
: 'ul';
},
@ -116,7 +115,7 @@ export default {
value: this.boardItems,
};
return this.canAdminList ? options : {};
return this.canMoveIssue ? options : {};
},
},
watch: {
@ -172,15 +171,33 @@ export default {
this.loadNextPage();
}
},
handleDragOnStart() {
handleDragOnStart({
item: {
dataset: { draggableItemType },
},
}) {
if (draggableItemType !== DraggableItemTypes.card) {
return;
}
sortableStart();
this.track('drag_card', { label: 'board' });
},
handleDragOnEnd(params) {
handleDragOnEnd({
newIndex: originalNewIndex,
oldIndex,
from,
to,
item: {
dataset: { draggableItemType, itemId, itemIid, itemPath },
},
}) {
if (draggableItemType !== DraggableItemTypes.card) {
return;
}
sortableEnd();
const { oldIndex, from, to, item } = params;
let { newIndex } = params;
const { itemId, itemIid, itemPath } = item.dataset;
let newIndex = originalNewIndex;
let { children } = to;
let moveBeforeId;
let moveAfterId;
@ -267,6 +284,7 @@ export default {
:index="index"
:list="list"
:item="item"
:data-draggable-item-type="$options.draggableItemTypes.card"
:disabled="disabled"
/>
<gl-intersection-observer @appear="onReachingListBottom">

View File

@ -114,6 +114,11 @@ export const FilterFields = {
],
};
export const DraggableItemTypes = {
card: 'card',
list: 'list',
};
export default {
BoardType,
ListType,

View File

@ -14,6 +14,7 @@ import {
issuableTypes,
FilterFields,
ListTypeTitles,
DraggableItemTypes,
} from 'ee_else_ce/boards/constants';
import createBoardListMutation from 'ee_else_ce/boards/graphql/board_list_create.mutation.graphql';
import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql';
@ -267,12 +268,16 @@ export default {
{ state: { boardLists }, commit, dispatch },
{
item: {
dataset: { listId: movedListId },
dataset: { listId: movedListId, draggableItemType },
},
newIndex,
to: { children },
},
) => {
if (draggableItemType !== DraggableItemTypes.list) {
return;
}
const displacedListId = children[newIndex].dataset.listId;
if (movedListId === displacedListId) {
return;

View File

@ -1,4 +1,5 @@
export const TYPE_CI_RUNNER = 'Ci::Runner';
export const TYPE_EPIC = 'Epic';
export const TYPE_GROUP = 'Group';
export const TYPE_ISSUE = 'Issue';
export const TYPE_ITERATION = 'Iteration';

View File

@ -4,6 +4,7 @@
# - a `#container` accessor
# - a `#project` accessor
# - a `#user` accessor
# - a `#deploy_token` accessor
# - a `#authentication_result` accessor
# - a `#can?(object, action, subject)` method
# - a `#ci?` method
@ -83,26 +84,18 @@ module LfsRequest
end
def deploy_token_can_download_code?
deploy_token_present? &&
deploy_token.present? &&
deploy_token.project == project &&
deploy_token.active? &&
deploy_token.read_repository?
end
def deploy_token_present?
user && user.is_a?(DeployToken)
end
def deploy_token
user
end
def lfs_upload_access?
strong_memoize(:lfs_upload_access) do
next false unless has_authentication_ability?(:push_code)
next false if limit_exceeded?
lfs_deploy_token? || can?(user, :push_code, project)
lfs_deploy_token? || can?(user, :push_code, project) || can?(deploy_token, :push_code, project)
end
end
@ -111,7 +104,7 @@ module LfsRequest
end
def user_can_download_code?
has_authentication_ability?(:download_code) && can?(user, :download_code, project) && !deploy_token_present?
has_authentication_ability?(:download_code) && can?(user, :download_code, project)
end
def build_can_download_code?

View File

@ -3,19 +3,14 @@
module Projects
module Packages
class InfrastructureRegistryController < Projects::ApplicationController
before_action :verify_feature_enabled!
include PackagesAccess
feature_category :infrastructure_as_code
def show
@package = project.packages.find(params[:id])
@package_files = @package.package_files.recent
end
private
def verify_feature_enabled!
render_404 unless Feature.enabled?(:infrastructure_registry_page, default_enabled: :yaml)
end
end
end
end

View File

@ -10,6 +10,10 @@ module Repositories
skip_before_action :lfs_check_access!, only: [:deprecated]
before_action :lfs_check_batch_operation!, only: [:batch]
# added here as a part of the refactor, will be removed
# https://gitlab.com/gitlab-org/gitlab/-/issues/328692
delegate :deploy_token, :user, to: :authentication_result, allow_nil: true
def batch
unless objects.present?
render_lfs_not_found
@ -141,7 +145,7 @@ module Repositories
end
def lfs_auth_header
return unless user.is_a?(User)
return unless user
Gitlab::LfsToken.new(user).basic_encoding
end

View File

@ -4,6 +4,10 @@ module Repositories
class LfsLocksApiController < Repositories::GitHttpClientController
include LfsRequest
# added here as a part of the refactor, will be removed
# https://gitlab.com/gitlab-org/gitlab/-/issues/328692
delegate :deploy_token, :user, to: :authentication_result, allow_nil: true
def create
@result = Lfs::LockFileService.new(project, user, lfs_params).execute

View File

@ -8,6 +8,10 @@ module Repositories
skip_before_action :verify_workhorse_api!, only: :download
# added here as a part of the refactor, will be removed
# https://gitlab.com/gitlab-org/gitlab/-/issues/328692
delegate :deploy_token, :user, to: :authentication_result, allow_nil: true
def download
lfs_object = LfsObject.find_by_oid(oid)
unless lfs_object && lfs_object.file.exists?

View File

@ -32,13 +32,14 @@ module IssuablesDescriptionTemplatesHelper
@template_types[project.id][issuable_type] ||= TemplateFinder.all_template_names(project, issuable_type.pluralize)
end
def issuable_templates_names(issuable)
# Overriden on EE::IssuablesDescriptionTemplatesHelper to include inherited templates names
def issuable_templates_names(issuable, include_inherited_templates = false)
all_templates = issuable_templates(ref_project, issuable.to_ability_name)
all_templates.values.flatten.map { |tpl| tpl[:name] if tpl[:project_id] == ref_project.id }.compact.uniq
end
def selected_template(issuable)
params[:issuable_template] if issuable_templates_names(issuable).any? { |tmpl_name| tmpl_name == params[:issuable_template] }
params[:issuable_template] if issuable_templates_names(issuable, true).any? { |tmpl_name| tmpl_name == params[:issuable_template] }
end
def template_names_path(parent, issuable)
@ -47,3 +48,5 @@ module IssuablesDescriptionTemplatesHelper
project_template_names_path(parent, template_type: issuable.to_ability_name)
end
end
IssuablesDescriptionTemplatesHelper.prepend_mod

View File

@ -16,7 +16,6 @@ module Ci
Gitlab::Ci::Pipeline::Chain::Config::Process,
Gitlab::Ci::Pipeline::Chain::Validate::AfterConfig,
Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs,
Gitlab::Ci::Pipeline::Chain::LegacySkip,
Gitlab::Ci::Pipeline::Chain::SeedBlock,
Gitlab::Ci::Pipeline::Chain::EvaluateWorkflowRules,
Gitlab::Ci::Pipeline::Chain::Seed,

View File

@ -1,8 +0,0 @@
---
name: ci_skip_before_parsing_yaml
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66147
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337167
milestone: '14.2'
type: development
group: group::pipeline execution
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: infrastructure_registry_page
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57338
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326460
milestone: '13.11'
type: development
group: group::package
default_enabled: true

View File

@ -20,12 +20,7 @@ Gitlab.ee do
end
end
db_config = Gitlab::Database.main.config ||
Rails.application.config.database_configuration[Rails.env]
ActiveRecord::Base.establish_connection(
db_config.merge(pool: Gitlab::Database.main.default_pool_size)
)
ActiveRecord::Base.establish_connection(Gitlab::Database.main.db_config_with_default_pool_size)
Gitlab.ee do
if Gitlab::Runtime.sidekiq? && Gitlab::Geo.geo_database_configured?

View File

@ -1,20 +0,0 @@
---
data_category: operational
key_path: usage_activity_by_stage_monthly.secure.user_dast_jobs
description: Users who run a DAST job
product_section: sec
product_stage: secure
product_group: group::dynamic analysis
product_category: dynamic_application_security_testing
value_type: number
status: data_available
time_frame: 28d
data_source:
distribution:
- ce
tier:
- free
skip_validation: true
performance_indicator_type:
- gmau
- paid_gmau

View File

@ -1,18 +0,0 @@
---
data_category: operational
key_path: usage_activity_by_stage_monthly.secure.dast_pipeline
description: Count of pipelines that have at least 1 DAST job
product_section: sec
product_stage: secure
product_group: group::dynamic analysis
product_category: dynamic_application_security_testing
value_type: number
status: data_available
time_frame: 28d
data_source:
distribution:
- ce
tier:
- ultimate
skip_validation: true
performance_indicator_type: []

View File

@ -1,18 +0,0 @@
---
data_category: operational
key_path: usage_activity_by_stage_monthly.secure.user_api_fuzzing_jobs
description: Count of API Fuzzing jobs by job name
product_section: sec
product_stage: secure
product_group: group::fuzz testing
product_category:
value_type: number
status: data_available
time_frame: 28d
data_source:
distribution:
- ce
tier:
- free
skip_validation: true
performance_indicator_type: []

View File

@ -1,17 +0,0 @@
---
data_category: operational
key_path: usage_activity_by_stage_monthly.secure.user_api_fuzzing_dnd_jobs
description: Count of API Fuzzing `docker-in-docker` jobs by job names
product_section: sec
product_stage: secure
product_group: group::fuzz testing
product_category:
value_type: number
status: data_available
time_frame: 28d
data_source:
distribution:
- ce
tier:
- free
skip_validation: true

View File

@ -1,20 +0,0 @@
---
data_category: operational
key_path: usage_activity_by_stage_monthly.secure.user_coverage_fuzzing_jobs
description: ''
product_section: ''
product_stage: ''
product_group: ''
product_category: ''
value_type: number
status: data_available
time_frame: 28d
data_source:
distribution:
- ce
tier:
- free
skip_validation: true
performance_indicator_type:
- gmau
- paid_gmau

View File

@ -1,18 +0,0 @@
---
data_category: operational
key_path: usage_activity_by_stage_monthly.secure.dast_scans
description: ''
product_section: ''
product_stage: ''
product_group: ''
product_category: ''
value_type: number
status: data_available
time_frame: 28d
data_source:
distribution:
- ce
tier:
- free
skip_validation: true
performance_indicator_type: []

View File

@ -1,18 +0,0 @@
---
data_category: operational
key_path: usage_activity_by_stage_monthly.secure.coverage_fuzzing_scans
description: ''
product_section: ''
product_stage: ''
product_group: ''
product_category: ''
value_type: number
status: data_available
time_frame: 28d
data_source:
distribution:
- ce
tier:
- free
skip_validation: true
performance_indicator_type: []

View File

@ -1,18 +0,0 @@
---
data_category: operational
key_path: usage_activity_by_stage_monthly.secure.api_fuzzing_scans
description: ''
product_section: ''
product_stage: ''
product_group: ''
product_category: ''
value_type: number
status: data_available
time_frame: 28d
data_source:
distribution:
- ce
tier:
- free
skip_validation: true
performance_indicator_type: []

View File

@ -1,18 +0,0 @@
---
data_category: operational
key_path: counts.dast_jobs
description: Count of DAST jobs run
product_section: sec
product_stage: secure
product_group: group::dynamic analysis
product_category: dynamic_application_security_testing
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
tier:
- free
skip_validation: true
performance_indicator_type: []

View File

@ -1,17 +0,0 @@
---
data_category: operational
key_path: usage_activity_by_stage.secure.user_dast_jobs
description: Count of DAST jobs
product_section: sec
product_stage: secure
product_group: group::dynamic analysis
product_category: dynamic_application_security_testing
value_type: number
status: data_available
time_frame: all
data_source:
distribution:
- ce
tier:
- free
skip_validation: true

View File

@ -1,18 +0,0 @@
---
data_category: optional
key_path: counts.api_fuzzing_jobs
description: Count of API Fuzzing jobs run by job name
product_section: sec
product_stage: secure
product_group: group::fuzz testing
product_category:
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
tier:
- free
skip_validation: true
performance_indicator_type: []

View File

@ -1,17 +0,0 @@
---
data_category: optional
key_path: counts.api_fuzzing_dnd_jobs
description: Count of API Fuzzing `docker-in-docker` jobs run by job name
product_section: sec
product_stage: secure
product_group: group::fuzz testing
product_category:
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
tier:
- free
skip_validation: true

View File

@ -1,17 +0,0 @@
---
data_category: operational
key_path: usage_activity_by_stage.secure.user_api_fuzzing_jobs
description: Count of API Fuzzing jobs by job name
product_section: sec
product_stage: secure
product_group: group::fuzz testing
product_category:
value_type: number
status: data_available
time_frame: all
data_source:
distribution:
- ce
tier:
- free
skip_validation: true

View File

@ -1,17 +0,0 @@
---
data_category: operational
key_path: usage_activity_by_stage.secure.user_api_fuzzing_dnd_jobs
description: Count of API Fuzzing `docker-in-docker` jobs by job name
product_section: sec
product_stage: secure
product_group: group::fuzz testing
product_category:
value_type: number
status: data_available
time_frame: all
data_source:
distribution:
- ce
tier:
- free
skip_validation: true

View File

@ -1,18 +0,0 @@
---
data_category: optional
key_path: counts.coverage_fuzzing_jobs
description: ''
product_section: ''
product_stage: ''
product_group: ''
product_category: ''
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
tier:
- free
skip_validation: true
performance_indicator_type: []

View File

@ -1,18 +0,0 @@
---
data_category: optional
key_path: counts.dast_on_demand_pipelines
description: ''
product_section: ''
product_stage: ''
product_group: ''
product_category: ''
value_type: number
status: data_available
time_frame: all
data_source: database
distribution:
- ce
tier:
- free
skip_validation: true
performance_indicator_type: []

View File

@ -1,17 +0,0 @@
---
data_category: operational
key_path: usage_activity_by_stage.secure.user_coverage_fuzzing_jobs
description: ''
product_section: ''
product_stage: ''
product_group: ''
product_category: ''
value_type: number
status: data_available
time_frame: all
data_source:
distribution:
- ce
tier:
- free
skip_validation: true

View File

@ -3922,19 +3922,28 @@ image: registry.gitlab.com/gitlab-org/release-cli:latest
#### `release-cli` for shell executors
> [Introduced](https://gitlab.com/gitlab-org/release-cli/-/issues/21) in GitLab 13.8.
> - [Introduced](https://gitlab.com/gitlab-org/release-cli/-/issues/21) in GitLab 13.8.
> - [Changed](https://gitlab.com/gitlab-org/release-cli/-/merge_requests/108): the `release-cli` binaries are also
[available in the Package Registry](https://gitlab.com/jaime/release-cli/-/packages)
starting from GitLab 14.2.
For GitLab Runner shell executors, you can download and install the `release-cli` manually for your [supported OS and architecture](https://release-cli-downloads.s3.amazonaws.com/latest/index.html).
Once installed, the `release` keyword should be available to you.
**Install on Unix/Linux**
1. Download the binary for your system, in the following example for amd64 systems:
1. Download the binary for your system from S3, in the following example for amd64 systems:
```shell
curl --location --output /usr/local/bin/release-cli "https://release-cli-downloads.s3.amazonaws.com/latest/release-cli-linux-amd64"
```
Or from the GitLab package registry:
```shell
curl --location --output /usr/local/bin/release-cli "https://gitlab.com/api/v4/projects/gitlab-org%2Frelease-cli/packages/generic/release-cli/latest/release-cli-darwin-amd64"
```
1. Give it permissions to execute:
```shell

View File

@ -7,8 +7,6 @@ module API
content_type :txt, 'text/plain'
feature_category :runner
resource :runners do
desc 'Registers a new Runner' do
success Entities::Ci::RunnerRegistrationDetails
@ -26,7 +24,7 @@ module API
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: %q(List of Runner's tags)
optional :maximum_timeout, type: Integer, desc: 'Maximum timeout set when this Runner will handle the job'
end
post '/' do
post '/', feature_category: :runner do
attributes = attributes_for_keys([:description, :active, :locked, :run_untagged, :tag_list, :access_level, :maximum_timeout])
.merge(get_runner_details_from_request)
@ -59,7 +57,7 @@ module API
params do
requires :token, type: String, desc: %q(Runner's authentication token)
end
delete '/' do
delete '/', feature_category: :runner do
authenticate_runner!
destroy_conditionally!(current_runner)
@ -71,7 +69,7 @@ module API
params do
requires :token, type: String, desc: %q(Runner's authentication token)
end
post '/verify' do
post '/verify', feature_category: :runner do
authenticate_runner!
status 200
body "200"
@ -123,7 +121,7 @@ module API
formatter :build_json, ->(object, _) { object }
parser :build_json, ::Grape::Parser::Json
post '/request' do
post '/request', feature_category: :continuous_integration do
authenticate_runner!
unless current_runner.active?
@ -177,7 +175,7 @@ module API
end
optional :exit_code, type: Integer, desc: %q(Job's exit code)
end
put '/:id' do
put '/:id', feature_category: :continuous_integration do
job = authenticate_job!
Gitlab::Metrics.add_event(:update_build)
@ -204,7 +202,7 @@ module API
requires :id, type: Integer, desc: %q(Job's ID)
optional :token, type: String, desc: %q(Job's authentication token)
end
patch '/:id/trace' do
patch '/:id/trace', feature_category: :continuous_integration do
job = authenticate_job!
error!('400 Missing header Content-Range', 400) unless request.headers.key?('Content-Range')
@ -249,7 +247,7 @@ module API
optional :artifact_type, type: String, desc: %q(The type of artifact),
default: 'archive', values: ::Ci::JobArtifact.file_types.keys
end
post '/:id/artifacts/authorize' do
post '/:id/artifacts/authorize', feature_category: :build_artifacts do
not_allowed! unless Gitlab.config.artifacts.enabled
require_gitlab_workhorse!
@ -285,7 +283,7 @@ module API
default: 'zip', values: ::Ci::JobArtifact.file_formats.keys
optional :metadata, type: ::API::Validations::Types::WorkhorseFile, desc: %(The artifact metadata to store (generated by Multipart middleware))
end
post '/:id/artifacts' do
post '/:id/artifacts', feature_category: :build_artifacts do
not_allowed! unless Gitlab.config.artifacts.enabled
require_gitlab_workhorse!
@ -314,7 +312,7 @@ module API
optional :token, type: String, desc: %q(Job's authentication token)
optional :direct_download, default: false, type: Boolean, desc: %q(Perform direct download from remote storage instead of proxying artifacts)
end
get '/:id/artifacts' do
get '/:id/artifacts', feature_category: :build_artifacts do
job = authenticate_job!(require_running: false)
present_carrierwave_file!(job.artifacts_file, supports_direct_download: params[:direct_download])

View File

@ -1,56 +0,0 @@
# frozen_string_literal: true
module Gitlab
module Ci
module Pipeline
module Chain
# This will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/337167
class LegacySkip < Chain::Skip
include ::Gitlab::Utils::StrongMemoize
SKIP_PATTERN = /\[(ci[ _-]skip|skip[ _-]ci)\]/i.freeze
def perform!
return if ::Feature.enabled?(:ci_skip_before_parsing_yaml, project, default_enabled: :yaml)
if skipped?
if @command.save_incompleted
# Project iid must be called outside a transaction, so we ensure it is set here
# otherwise it may be set within the state transition transaction of the skip call
# which it will lock the InternalId row for the whole transaction
@pipeline.ensure_project_iid!
@pipeline.skip
end
end
end
def break?
return if ::Feature.enabled?(:ci_skip_before_parsing_yaml, project, default_enabled: :yaml)
skipped?
end
private
def skipped?
!@command.ignore_skip_ci && (commit_message_skips_ci? || push_option_skips_ci?)
end
def commit_message_skips_ci?
return false unless @pipeline.git_commit_message
strong_memoize(:commit_message_skips_ci) do
!!(@pipeline.git_commit_message =~ SKIP_PATTERN)
end
end
def push_option_skips_ci?
@command.push_options.present? &&
@command.push_options.deep_symbolize_keys.dig(:ci, :skip).present?
end
end
end
end
end
end

View File

@ -10,8 +10,6 @@ module Gitlab
SKIP_PATTERN = /\[(ci[ _-]skip|skip[ _-]ci)\]/i.freeze
def perform!
return unless ::Feature.enabled?(:ci_skip_before_parsing_yaml, project, default_enabled: :yaml)
if skipped?
if @command.save_incompleted
# Project iid must be called outside a transaction, so we ensure it is set here
@ -25,8 +23,6 @@ module Gitlab
end
def break?
return unless ::Feature.enabled?(:ci_skip_before_parsing_yaml, project, default_enabled: :yaml)
skipped?
end

View File

@ -252,6 +252,7 @@ semgrep-sast:
- '**/*.jsx'
- '**/*.ts'
- '**/*.tsx'
- '**/*.c'
sobelow-sast:
extends: .sast-analyzer

View File

@ -1,294 +0,0 @@
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/sast/
#
# Configure SAST with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/index.html).
# List of available variables: https://docs.gitlab.com/ee/user/application_security/sast/index.html#available-variables
variables:
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
SAST_EXCLUDED_ANALYZERS: ""
SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
SCAN_KUBERNETES_MANIFESTS: "false"
sast:
stage: test
artifacts:
reports:
sast: gl-sast-report.json
rules:
- when: never
variables:
SEARCH_MAX_DEPTH: 4
script:
- echo "$CI_JOB_NAME is used for configuration only, and its script should not be executed"
- exit 1
.sast-analyzer:
extends: sast
allow_failure: true
# `rules` must be overridden explicitly by each child job
# see https://gitlab.com/gitlab-org/gitlab/-/issues/218444
script:
- /analyzer run
bandit-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 2
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/bandit:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /bandit/
when: never
- if: $CI_COMMIT_BRANCH
exists:
- '**/*.py'
brakeman-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 2
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/brakeman:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /brakeman/
when: never
- if: $CI_COMMIT_BRANCH
exists:
- '**/*.rb'
- '**/Gemfile'
eslint-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 2
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/eslint:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /eslint/
when: never
- if: $CI_COMMIT_BRANCH
exists:
- '**/*.html'
- '**/*.js'
- '**/*.jsx'
- '**/*.ts'
- '**/*.tsx'
flawfinder-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 2
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/flawfinder:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /flawfinder/
when: never
- if: $CI_COMMIT_BRANCH
exists:
- '**/*.c'
- '**/*.cpp'
kubesec-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 2
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/kubesec:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /kubesec/
when: never
- if: $CI_COMMIT_BRANCH &&
$SCAN_KUBERNETES_MANIFESTS == 'true'
gosec-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 3
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gosec:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /gosec/
when: never
- if: $CI_COMMIT_BRANCH
exists:
- '**/*.go'
.mobsf-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 2
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/mobsf:$SAST_ANALYZER_IMAGE_TAG"
mobsf-android-sast:
extends: .mobsf-sast
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /mobsf/
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_EXPERIMENTAL_FEATURES == 'true'
exists:
- '**/*.apk'
- '**/AndroidManifest.xml'
mobsf-ios-sast:
extends: .mobsf-sast
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /mobsf/
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_EXPERIMENTAL_FEATURES == 'true'
exists:
- '**/*.ipa'
- '**/*.xcodeproj/*'
nodejs-scan-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 2
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/nodejs-scan:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /nodejs-scan/
when: never
- if: $CI_COMMIT_BRANCH
exists:
- '**/package.json'
phpcs-security-audit-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 2
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/phpcs-security-audit:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /phpcs-security-audit/
when: never
- if: $CI_COMMIT_BRANCH
exists:
- '**/*.php'
pmd-apex-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 2
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/pmd-apex:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /pmd-apex/
when: never
- if: $CI_COMMIT_BRANCH
exists:
- '**/*.cls'
security-code-scan-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 2
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/security-code-scan:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /security-code-scan/
when: never
- if: $CI_COMMIT_BRANCH
exists:
- '**/*.csproj'
- '**/*.vbproj'
semgrep-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 2
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/semgrep:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /semgrep/
when: never
- if: $CI_COMMIT_BRANCH
exists:
- '**/*.py'
- '**/*.js'
- '**/*.jsx'
- '**/*.ts'
- '**/*.tsx'
- '**/*.c'
sobelow-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 2
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/sobelow:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /sobelow/
when: never
- if: $CI_COMMIT_BRANCH
exists:
- 'mix.exs'
spotbugs-sast:
extends: .sast-analyzer
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
SAST_ANALYZER_IMAGE_TAG: 2
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/spotbugs:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_EXCLUDED_ANALYZERS =~ /spotbugs/
when: never
- if: $SAST_EXPERIMENTAL_FEATURES == 'true'
exists:
- '**/AndroidManifest.xml'
when: never
- if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH
exists:
- '**/*.groovy'
- '**/*.java'
- '**/*.scala'
- '**/*.kt'

View File

@ -75,6 +75,17 @@ module Gitlab
adapter_name.casecmp('postgresql') == 0
end
def db_config_with_default_pool_size
db_config_object = scope.connection_db_config
config = db_config_object.configuration_hash.merge(pool: default_pool_size)
ActiveRecord::DatabaseConfigurations::HashConfig.new(
db_config_object.env_name,
db_config_object.name,
config
)
end
# Disables prepared statements for the current database connection.
def disable_prepared_statements
scope.establish_connection(config.merge(prepared_statements: false))

View File

@ -6,8 +6,8 @@ module Gitlab
module Observers
class QueryDetails < MigrationObserver
def before
@file_path = File.join(Instrumentation::RESULT_DIR, 'current-details.json')
@file = File.open(@file_path, 'wb')
file_path = File.join(Instrumentation::RESULT_DIR, "#{observation.version}_#{observation.name}-query-details.json")
@file = File.open(file_path, 'wb')
@writer = Oj::StreamWriter.new(@file, {})
@writer.push_array
@subscriber = ActiveSupport::Notifications.subscribe('sql.active_record') do |*args|
@ -23,7 +23,7 @@ module Gitlab
end
def record
File.rename(@file_path, File.join(Instrumentation::RESULT_DIR, "#{observation.version}_#{observation.name}-query-details.json"))
# no-op
end
def record_sql_event(_name, started, finished, _unique_id, payload)

View File

@ -7,8 +7,8 @@ module Gitlab
class QueryLog < MigrationObserver
def before
@logger_was = ActiveRecord::Base.logger
@log_file_path = File.join(Instrumentation::RESULT_DIR, 'current.log')
@logger = Logger.new(@log_file_path)
file_path = File.join(Instrumentation::RESULT_DIR, "#{observation.version}_#{observation.name}.log")
@logger = Logger.new(file_path)
ActiveRecord::Base.logger = @logger
end
@ -18,7 +18,7 @@ module Gitlab
end
def record
File.rename(@log_file_path, File.join(Instrumentation::RESULT_DIR, "#{observation.version}_#{observation.name}.log"))
# no-op
end
end
end

View File

@ -58,7 +58,7 @@ module Sidebars
end
def infrastructure_registry_menu_item
if Feature.disabled?(:infrastructure_registry_page, context.current_user, default_enabled: :yaml) || packages_registry_disabled?
if packages_registry_disabled?
return ::Sidebars::NilMenuItem.new(item_id: :infrastructure_registry)
end

View File

@ -18,9 +18,9 @@ RSpec.describe Projects::Packages::InfrastructureRegistryController do
it_behaves_like 'returning response status', :ok
context 'when the feature is disabled' do
context 'when the packages registry is not available' do
before do
stub_feature_flags(infrastructure_registry_page: false)
stub_config(packages: { enabled: false })
end
it_behaves_like 'returning response status', :not_found
@ -34,9 +34,9 @@ RSpec.describe Projects::Packages::InfrastructureRegistryController do
it_behaves_like 'returning response status', :ok
context 'when the feature is disabled' do
context 'when the packages registry is not available' do
before do
stub_feature_flags(infrastructure_registry_page: false)
stub_config(packages: { enabled: false })
end
it_behaves_like 'returning response status', :not_found

View File

@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe 'Project issue boards', :js do
include DragTo
include MobileHelpers
include BoardHelpers
let_it_be(:group) { create(:group, :nested) }
let_it_be(:project) { create(:project, :public, namespace: group) }
@ -546,23 +547,6 @@ RSpec.describe 'Project issue boards', :js do
end
end
def drag(selector: '.board-list', list_from_index: 0, from_index: 0, to_index: 0, list_to_index: 0, perform_drop: true)
# ensure there is enough horizontal space for four boards
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
resize_window(2000, 800)
drag_to(selector: selector,
scrollable: '#board-app',
list_from_index: list_from_index,
from_index: from_index,
to_index: to_index,
list_to_index: list_to_index,
perform_drop: perform_drop)
end
wait_for_requests
end
def wait_for_board_cards(board_number, expected_cards)
page.within(find(".board:nth-child(#{board_number})")) do
expect(page.find('.board-header')).to have_content(expected_cards.to_s)

View File

@ -3,16 +3,21 @@
require 'spec_helper'
RSpec.describe 'Group Boards' do
let(:group) { create(:group) }
let!(:project) { create(:project_empty_repo, group: group) }
let(:user) { create(:group_member, :maintainer, user: create(:user), group: group ).user }
include DragTo
include MobileHelpers
include BoardHelpers
before do
sign_in(user)
end
let_it_be(:group) { create(:group) }
let_it_be(:user) { create(:user) }
context 'Creates an issue', :js do
let_it_be(:project) { create(:project_empty_repo, group: group) }
context 'Creates a an issue', :js do
before do
group.add_maintainer(user)
sign_in(user)
visit group_boards_path(group)
end
@ -39,4 +44,58 @@ RSpec.describe 'Group Boards' do
end
end
end
context "when user is a Reporter in one of the group's projects", :js do
let_it_be(:board) { create(:board, group: group) }
let_it_be(:backlog_list) { create(:backlog_list, board: board) }
let_it_be(:group_label1) { create(:group_label, title: "bug", group: group) }
let_it_be(:group_label2) { create(:group_label, title: "dev", group: group) }
let_it_be(:list1) { create(:list, board: board, label: group_label1, position: 0) }
let_it_be(:list2) { create(:list, board: board, label: group_label2, position: 1) }
let_it_be(:project1) { create(:project_empty_repo, :private, group: group) }
let_it_be(:project2) { create(:project_empty_repo, :private, group: group) }
let_it_be(:issue1) { create(:issue, title: 'issue1', project: project1, labels: [group_label2]) }
let_it_be(:issue2) { create(:issue, title: 'issue2', project: project2) }
before do
project1.add_guest(user)
project2.add_reporter(user)
sign_in(user)
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
visit group_boards_path(group)
end
end
it 'allows user to move issue of project where they are a Reporter' do
expect(find('.board:nth-child(1)')).to have_content(issue2.title)
drag(list_from_index: 0, from_index: 0, list_to_index: 1)
expect(find('.board:nth-child(2)')).to have_content(issue2.title)
expect(issue2.reload.labels).to contain_exactly(group_label1)
end
it 'does not allow user to move issue of project where they are a Guest' do
expect(find('.board:nth-child(3)')).to have_content(issue1.title)
drag(list_from_index: 2, from_index: 0, list_to_index: 1)
expect(find('.board:nth-child(3)')).to have_content(issue1.title)
expect(issue1.reload.labels).to contain_exactly(group_label2)
expect(issue2.reload.labels).to eq([])
end
it 'does not allow user to re-position lists' do
drag(list_from_index: 1, list_to_index: 2, selector: '.board-header')
expect(find('.board:nth-child(2) [data-testid="board-list-header"]')).to have_content(group_label1.title)
expect(find('.board:nth-child(3) [data-testid="board-list-header"]')).to have_content(group_label2.title)
expect(list1.reload.position).to eq(0)
expect(list2.reload.position).to eq(1)
end
end
end

View File

@ -11,9 +11,9 @@ RSpec.describe 'Infrastructure Registry' do
project.add_maintainer(user)
end
context 'when feature is not available' do
context 'when packages registry is not enabled' do
before do
stub_feature_flags(infrastructure_registry_page: false)
stub_config(packages: { enabled: false })
end
it 'gives 404' do
@ -23,7 +23,7 @@ RSpec.describe 'Infrastructure Registry' do
end
end
context 'when feature is available', :js do
context 'when packages registry is enabled', :js do
before do
visit_project_infrastructure_registry
end

View File

@ -1,3 +1,5 @@
import Draggable from 'vuedraggable';
import { DraggableItemTypes } from 'ee_else_ce/boards/constants';
import { useFakeRequestAnimationFrame } from 'helpers/fake_request_animation_frame';
import createComponent from 'jest/boards/board_list_helper';
import BoardCard from '~/boards/components/board_card.vue';
@ -10,6 +12,23 @@ describe('Board list component', () => {
const findByTestId = (testId) => wrapper.find(`[data-testid="${testId}"]`);
const findIssueCountLoadingIcon = () => wrapper.find('[data-testid="count-loading-icon"]');
const findDraggable = () => wrapper.findComponent(Draggable);
const startDrag = (
params = {
item: {
dataset: {
draggableItemType: DraggableItemTypes.card,
},
},
},
) => {
findByTestId('tree-root-wrapper').vm.$emit('start', params);
};
const endDrag = (params) => {
findByTestId('tree-root-wrapper').vm.$emit('end', params);
};
useFakeRequestAnimationFrame();
@ -155,40 +174,89 @@ describe('Board list component', () => {
});
describe('drag & drop issue', () => {
beforeEach(() => {
wrapper = createComponent();
});
describe('when dragging is allowed', () => {
beforeEach(() => {
wrapper = createComponent({
componentProps: {
disabled: false,
},
});
});
describe('handleDragOnStart', () => {
it('adds a class `is-dragging` to document body', () => {
expect(document.body.classList.contains('is-dragging')).toBe(false);
it('Draggable is used', () => {
expect(findDraggable().exists()).toBe(true);
});
findByTestId('tree-root-wrapper').vm.$emit('start');
describe('handleDragOnStart', () => {
it('adds a class `is-dragging` to document body', () => {
expect(document.body.classList.contains('is-dragging')).toBe(false);
expect(document.body.classList.contains('is-dragging')).toBe(true);
startDrag();
expect(document.body.classList.contains('is-dragging')).toBe(true);
});
});
describe('handleDragOnEnd', () => {
beforeEach(() => {
jest.spyOn(wrapper.vm, 'moveItem').mockImplementation(() => {});
startDrag();
});
it('removes class `is-dragging` from document body', () => {
document.body.classList.add('is-dragging');
endDrag({
oldIndex: 1,
newIndex: 0,
item: {
dataset: {
draggableItemType: DraggableItemTypes.card,
itemId: mockIssues[0].id,
itemIid: mockIssues[0].iid,
itemPath: mockIssues[0].referencePath,
},
},
to: { children: [], dataset: { listId: 'gid://gitlab/List/1' } },
from: { dataset: { listId: 'gid://gitlab/List/2' } },
});
expect(document.body.classList.contains('is-dragging')).toBe(false);
});
it(`should not handle the event if the dragged item is not a "${DraggableItemTypes.card}"`, () => {
endDrag({
oldIndex: 1,
newIndex: 0,
item: {
dataset: {
draggableItemType: DraggableItemTypes.list,
itemId: mockIssues[0].id,
itemIid: mockIssues[0].iid,
itemPath: mockIssues[0].referencePath,
},
},
to: { children: [], dataset: { listId: 'gid://gitlab/List/1' } },
from: { dataset: { listId: 'gid://gitlab/List/2' } },
});
expect(document.body.classList.contains('is-dragging')).toBe(true);
});
});
});
describe('handleDragOnEnd', () => {
it('removes class `is-dragging` from document body', () => {
jest.spyOn(wrapper.vm, 'moveItem').mockImplementation(() => {});
document.body.classList.add('is-dragging');
findByTestId('tree-root-wrapper').vm.$emit('end', {
oldIndex: 1,
newIndex: 0,
item: {
dataset: {
itemId: mockIssues[0].id,
itemIid: mockIssues[0].iid,
itemPath: mockIssues[0].referencePath,
},
describe('when dragging is not allowed', () => {
beforeEach(() => {
wrapper = createComponent({
componentProps: {
disabled: true,
},
to: { children: [], dataset: { listId: 'gid://gitlab/List/1' } },
from: { dataset: { listId: 'gid://gitlab/List/2' } },
});
});
expect(document.body.classList.contains('is-dragging')).toBe(false);
it('Draggable is not used', () => {
expect(findDraggable().exists()).toBe(false);
});
});
});

View File

@ -9,6 +9,7 @@ import {
issuableTypes,
BoardType,
listsQuery,
DraggableItemTypes,
} from 'ee_else_ce/boards/constants';
import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql';
import testAction from 'helpers/vuex_action_helper';
@ -525,6 +526,21 @@ describe('moveList', () => {
const movableListsOrder = ['gid://3', 'gid://4', 'gid://5'];
const allListsOrder = [backlogListId, ...movableListsOrder, closedListId];
it(`should not handle the event if the dragged item is not a "${DraggableItemTypes.list}"`, () => {
return testAction({
action: actions.moveList,
payload: {
item: { dataset: { listId: '', draggableItemType: DraggableItemTypes.card } },
to: {
children: [],
},
},
state: {},
expectedMutations: [],
expectedActions: [],
});
});
describe.each`
draggableFrom | draggableTo | boardLists | boardListsOrder | expectedMovableListsOrder
${0} | ${2} | ${boardLists1} | ${movableListsOrder} | ${['gid://4', 'gid://5', 'gid://3']}
@ -544,7 +560,12 @@ describe('moveList', () => {
const displacedListId = boardListsOrder[draggableTo];
const buildDraggablePayload = () => {
return {
item: { dataset: { listId: boardListsOrder[draggableFrom] } },
item: {
dataset: {
listId: boardListsOrder[draggableFrom],
draggableItemType: DraggableItemTypes.list,
},
},
newIndex: draggableTo,
to: {
children: boardListsOrder.map((listId) => ({ dataset: { listId } })),
@ -584,7 +605,7 @@ describe('moveList', () => {
return testAction({
action: actions.moveList,
payload: {
item: { dataset: { listId } },
item: { dataset: { listId, draggbaleItemType: DraggableItemTypes.list } },
newIndex: 0,
to: {
children: [{ dataset: { listId } }],

View File

@ -41,19 +41,6 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
context 'when project parent group does not have a file template project' do
it_behaves_like 'project issuable templates'
end
context 'when project parent group has a file template project' do
let_it_be(:file_template_project) { create(:project, :custom_repo, group: parent_group, files: issuable_template_files) }
let_it_be(:group, reload: true) { create(:group, parent: parent_group) }
let_it_be(:project, reload: true) { create(:project, :custom_repo, group: group, files: issuable_template_files) }
before do
project.update!(group: group)
parent_group.update_columns(file_template_project_id: file_template_project.id)
end
it_behaves_like 'project issuable templates'
end
end
end
@ -65,16 +52,12 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
allow(helper).to receive(:issuable_templates).and_return(templates)
end
context 'with matching project templates' do
context 'with project templates' do
let(:templates) do
{
"" => [
{ name: "another_issue_template", id: "another_issue_template", project_id: project.id },
{ name: "custom_issue_template", id: "custom_issue_template", project_id: project.id }
],
"Instance" => [
{ name: "first_issue_issue_template", id: "first_issue_issue_template", project_id: non_existing_record_id },
{ name: "second_instance_issue_template", id: "second_instance_issue_template", project_id: non_existing_record_id }
{ name: "another_issue_template", id: "another_issue_template" },
{ name: "custom_issue_template", id: "custom_issue_template" }
]
}
end
@ -90,10 +73,6 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
"Project Templates" => [
{ name: "another_issue_template", id: "another_issue_template", project_id: non_existing_record_id },
{ name: "custom_issue_template", id: "custom_issue_template", project_id: non_existing_record_id }
],
"Instance" => [
{ name: "first_issue_issue_template", id: "first_issue_issue_template", project_id: non_existing_record_id },
{ name: "second_instance_issue_template", id: "second_instance_issue_template", project_id: non_existing_record_id }
]
}
end

View File

@ -21,6 +21,14 @@ RSpec.describe 'Database config initializer' do
let(:max_threads) { 8 }
it 'retains the correct database name for the connection' do
previous_db_name = Gitlab::Database.main.scope.connection.pool.db_config.name
subject
expect(Gitlab::Database.main.scope.connection.pool.db_config.name).to eq(previous_db_name)
end
context 'when no custom headroom is specified' do
it 'sets the pool size based on the number of worker threads' do
old = ActiveRecord::Base.connection_db_config.pool

View File

@ -127,6 +127,20 @@ RSpec.describe Gitlab::Database::Connection do
end
end
describe '#db_config_with_default_pool_size' do
it 'returns db_config with our default pool size' do
allow(connection).to receive(:default_pool_size).and_return(9)
expect(connection.db_config_with_default_pool_size.pool).to eq(9)
end
it 'returns db_config with the correct database name' do
db_name = connection.scope.connection.pool.db_config.name
expect(connection.db_config_with_default_pool_size.name).to eq(db_name)
end
end
describe '#disable_prepared_statements' do
around do |example|
original_config = ::Gitlab::Database.main.config

View File

@ -8,7 +8,6 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryLog do
let(:connection) { ActiveRecord::Base.connection }
let(:query) { 'select 1' }
let(:directory_path) { Dir.mktmpdir }
let(:log_file) { "#{directory_path}/current.log" }
let(:migration_version) { 20210422152437 }
let(:migration_name) { 'test' }

View File

@ -124,34 +124,22 @@ RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu do
describe 'Infrastructure Registry' do
let(:item_id) { :infrastructure_registry }
context 'when feature flag :infrastructure_registry_page is enabled' do
it 'the menu item is added to list of menu items' do
stub_feature_flags(infrastructure_registry_page: true)
it 'the menu item is added to list of menu items' do
is_expected.not_to be_nil
end
is_expected.not_to be_nil
end
context 'when config package setting is disabled' do
it 'does not add the menu item to the list' do
stub_config(packages: { enabled: false })
context 'when config package setting is disabled' do
it 'does not add the menu item to the list' do
stub_config(packages: { enabled: false })
is_expected.to be_nil
end
end
context 'when user cannot read packages' do
let(:user) { nil }
it 'does not add the menu item to the list' do
is_expected.to be_nil
end
is_expected.to be_nil
end
end
context 'when feature flag :infrastructure_registry_page is disabled' do
it 'does not add the menu item to the list' do
stub_feature_flags(infrastructure_registry_page: false)
context 'when user cannot read packages' do
let(:user) { nil }
it 'does not add the menu item to the list' do
is_expected.to be_nil
end
end

View File

@ -708,14 +708,6 @@ RSpec.describe Ci::CreatePipelineService do
let(:commit_message) { skip_commit_message }
it_behaves_like 'skipping a pipeline'
context 'when the FF ci_skip_before_parsing_yaml is disabled' do
before do
stub_feature_flags(ci_skip_before_parsing_yaml: false)
end
it_behaves_like 'skipping a pipeline'
end
end
end
@ -723,14 +715,6 @@ RSpec.describe Ci::CreatePipelineService do
let(:commit_message) { 'some message' }
it_behaves_like 'creating a pipeline'
context 'when the FF ci_skip_before_parsing_yaml is disabled' do
before do
stub_feature_flags(ci_skip_before_parsing_yaml: false)
end
it_behaves_like 'creating a pipeline'
end
end
context 'when commit message is nil' do
@ -748,19 +732,6 @@ RSpec.describe Ci::CreatePipelineService do
end
it_behaves_like 'skipping a pipeline'
context 'when the FF ci_skip_before_parsing_yaml is disabled' do
before do
stub_feature_flags(ci_skip_before_parsing_yaml: false)
end
it 'creates the pipeline with error' do
pipeline = execute_service.payload
expect(pipeline).to be_persisted
expect(pipeline.status).to eq("failed")
end
end
end
end

View File

@ -23,4 +23,21 @@ module BoardHelpers
wait_for_requests
end
end
def drag(selector: '.board-list', list_from_index: 0, from_index: 0, to_index: 0, list_to_index: 0, perform_drop: true)
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
# ensure there is enough horizontal space for four board lists
resize_window(2000, 800)
drag_to(selector: selector,
scrollable: '#board-app',
list_from_index: list_from_index,
from_index: from_index,
to_index: to_index,
list_to_index: list_to_index,
perform_drop: perform_drop)
end
wait_for_requests
end
end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
let(:db_config_name) { ::Gitlab::Database.db_config_name(ApplicationRecord.connection) }
let(:db_config_name) { ::Gitlab::Database.db_config_names.first }
let(:expected_payload_defaults) do
metrics =
@ -14,13 +14,21 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
end
end
def transform_hash(hash, another_hash)
another_hash.each do |key, value|
raise "Unexpected key: #{key}" unless hash[key]
end
hash.merge(another_hash)
end
it 'prevents db counters from leaking to the next transaction' do
2.times do
Gitlab::WithRequestStore.with_request_store do
subscriber.sql(event)
expected = if db_role == :primary
expected_payload_defaults.merge({
transform_hash(expected_payload_defaults, {
db_count: record_query ? 1 : 0,
db_write_count: record_write_query ? 1 : 0,
db_cached_count: record_cached_query ? 1 : 0,
@ -36,7 +44,7 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
"db_primary_#{db_config_name}_wal_cached_count": record_wal_query && record_cached_query ? 1 : 0
})
elsif db_role == :replica
expected_payload_defaults.merge({
transform_hash(expected_payload_defaults, {
db_count: record_query ? 1 : 0,
db_write_count: record_write_query ? 1 : 0,
db_cached_count: record_cached_query ? 1 : 0,

View File

@ -640,9 +640,9 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
expect(rendered).to have_link('Infrastructure Registry', href: project_infrastructure_registry_index_path(project))
end
context 'when feature flag :infrastructure_registry_page is disabled' do
context 'when package registry config is disabled' do
it 'does not show link to package registry page' do
stub_feature_flags(infrastructure_registry_page: false)
stub_config(packages: { enabled: false })
render