Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-07-19 09:08:45 +00:00
parent 7f12b2dc74
commit 035cd5ee5e
78 changed files with 904 additions and 582 deletions

View File

@ -1465,24 +1465,6 @@
- <<: *if-merge-request
changes: *static-analysis-patterns
.semgrep-appsec-custom-rules:rules:
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request
changes: *code-backstage-qa-patterns
.ping-appsec-for-sast-findings:rules:
rules:
# Requiring $CUSTOM_SAST_RULES_BOT_PAT prevents the bot from running on forks or CE
# Without it the script would fail too.
- if: "$CUSTOM_SAST_RULES_BOT_PAT == null"
when: never
- <<: *if-not-ee
when: never
- <<: *if-merge-request
changes: *code-backstage-qa-patterns
#######################
# Vendored gems rules #
#######################
@ -1569,6 +1551,7 @@
- '**/*.tsx'
- '**/*.c'
- '**/*.go'
- '**/*.rb'
.reports:rules:secret_detection:
rules:

View File

@ -7,7 +7,6 @@
variables:
SETUP_DB: "false"
ENABLE_SPRING: "1"
SKIP_LOG_INITIALIZER_CONNECTIONS: "1"
# Disable warnings in browserslist which can break on backports
# https://github.com/browserslist/browserslist/blob/a287ec6/node.js#L367-L384
BROWSERSLIST_IGNORE_OLD_DATA: "true"
@ -160,39 +159,3 @@ feature-flags-usage:
when: always
paths:
- tmp/feature_flags/
semgrep-appsec-custom-rules:
stage: lint
extends:
- .semgrep-appsec-custom-rules:rules
image: returntocorp/semgrep
needs: []
script:
# Required to avoid a timeout https://github.com/returntocorp/semgrep/issues/5395
- git fetch origin master
# Include/exclude list isn't ideal https://github.com/returntocorp/semgrep/issues/5399
- |
semgrep ci --gitlab-sast --metrics off --config $CUSTOM_RULES_URL \
--include app --include lib --include workhorse \
--exclude '*_test.go' --exclude spec --exclude qa > gl-sast-report.json || true
variables:
CUSTOM_RULES_URL: https://gitlab.com/gitlab-com/gl-security/appsec/sast-custom-rules/-/raw/main/appsec-pings/rules.yml
artifacts:
paths:
- gl-sast-report.json
reports:
sast: gl-sast-report.json
ping-appsec-for-sast-findings:
stage: lint
image: alpine:latest
extends:
- .ping-appsec-for-sast-findings:rules
variables:
# Project Access Token bot ID for /gitlab-com/gl-security/appsec/sast-custom-rules
BOT_USER_ID: 11727358
needs:
- semgrep-appsec-custom-rules
script:
- apk add jq curl
- scripts/process_custom_semgrep_results.sh

10
.gitlab/sast-ruleset.toml Normal file
View File

@ -0,0 +1,10 @@
[semgrep]
description = 'semgrep custom rules configuration'
targetdir = "/sgrules"
validate = true
[[semgrep.passthrough]]
type = "git"
value = "https://gitlab.com/gitlab-com/gl-security/appsec/sast-custom-rules.git"
ref = "refs/heads/main"
subdir = "appsec-pings"

View File

@ -15,10 +15,11 @@ import currentUserQuery from '~/graphql_shared/queries/current_user.query.graphq
import userSearchQuery from '~/graphql_shared/queries/users_search.query.graphql';
import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
import { n__, s__ } from '~/locale';
import Tracking from '~/tracking';
import SidebarParticipant from '~/sidebar/components/assignees/sidebar_participant.vue';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import localUpdateWorkItemMutation from '../graphql/local_update_work_item.mutation.graphql';
import { i18n } from '../constants';
import { i18n, TRACKING_CATEGORY_SHOW } from '../constants';
function isTokenSelectorElement(el) {
return el?.classList.contains('gl-token-close') || el?.classList.contains('dropdown-item');
@ -44,6 +45,7 @@ export default {
GlDropdownItem,
GlDropdownDivider,
},
mixins: [Tracking.mixin()],
inject: ['fullPath'],
props: {
workItemId: {
@ -58,6 +60,15 @@ export default {
type: Boolean,
required: true,
},
workItemType: {
type: String,
required: true,
},
canUpdate: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
@ -95,6 +106,13 @@ export default {
},
},
computed: {
tracking() {
return {
category: TRACKING_CATEGORY_SHOW,
label: 'item_assignees',
property: `type_${this.workItemType}`,
};
},
assigneeListEmpty() {
return this.assignees.length === 0;
},
@ -163,6 +181,7 @@ export default {
},
},
});
this.track('updated_assignees');
},
handleFocus() {
this.isEditing = true;
@ -208,9 +227,11 @@ export default {
ref="tokenSelector"
:selected-tokens="localAssignees"
:container-class="containerClass"
class="assignees-selector gl-flex-grow-1 gl-border gl-border-white gl-hover-border-gray-200 gl-rounded-base col-9 gl-align-self-start gl-px-0!"
class="assignees-selector gl-flex-grow-1 gl-border gl-border-white gl-rounded-base col-9 gl-align-self-start gl-px-0!"
:class="{ 'gl-hover-border-gray-200': canUpdate }"
:dropdown-items="dropdownItems"
:loading="isLoadingUsers"
:view-only="!canUpdate"
@input="handleAssigneesInput"
@text-input="debouncedSearchKeyUpdate"
@focus="handleFocus"

View File

@ -216,9 +216,11 @@ export default {
<template v-if="workItemsMvc2Enabled">
<work-item-assignees
v-if="workItemAssignees"
:can-update="canUpdate"
:work-item-id="workItem.id"
:assignees="workItemAssignees.assignees.nodes"
:allows-multiple-assignees="workItemAssignees.allowsMultipleAssignees"
:work-item-type="workItemType"
@error="error = $event"
/>
<work-item-labels

View File

@ -124,8 +124,16 @@ ul.related-merge-requests > li gl-emoji {
.new-branch-col {
.discussion-filter-container {
&:not(:only-child) {
margin-right: $gl-padding-8;
&:not(:last-child) {
margin-right: $gl-spacing-scale-3;
}
}
@include media-breakpoint-down(xs) {
width: 100%;
> div:not(:last-child) {
margin-bottom: $gl-spacing-scale-3;
}
}
}
@ -147,6 +155,16 @@ ul.related-merge-requests > li gl-emoji {
.btn-group:not(.hidden) {
display: flex;
@include media-breakpoint-down(xs) {
.btn.btn-confirm {
@include gl-justify-content-start;
&.dropdown-toggle {
@include gl-flex-grow-0;
}
}
}
}
.js-create-merge-request {

View File

@ -42,13 +42,19 @@ class SearchController < ApplicationController
@sort = params[:sort] || default_sort
@search_service = Gitlab::View::Presenter::Factory.new(search_service, current_user: current_user).fabricate!
@scope = @search_service.scope
@without_count = @search_service.without_count?
@show_snippets = @search_service.show_snippets?
@search_results = @search_service.search_results
@search_objects = @search_service.search_objects
@search_highlight = @search_service.search_highlight
@aggregations = @search_service.search_aggregations
@search_level = @search_service.level
@search_type = search_type
@global_search_duration_s = Benchmark.realtime do
@scope = @search_service.scope
@without_count = @search_service.without_count?
@show_snippets = @search_service.show_snippets?
@search_results = @search_service.search_results
@search_objects = @search_service.search_objects
@search_highlight = @search_service.search_highlight
@aggregations = @search_service.search_aggregations
end
increment_search_counters
end
@ -144,7 +150,9 @@ class SearchController < ApplicationController
payload[:metadata]['meta.search.filters.state'] = params[:state]
payload[:metadata]['meta.search.force_search_results'] = params[:force_search_results]
payload[:metadata]['meta.search.project_ids'] = params[:project_ids]
payload[:metadata]['meta.search.search_level'] = params[:search_level]
payload[:metadata]['meta.search.type'] = @search_type if @search_type.present?
payload[:metadata]['meta.search.level'] = @search_level if @search_level.present?
payload[:metadata][:global_search_duration_s] = @global_search_duration_s if @global_search_duration_s.present?
if search_service.abuse_detected?
payload[:metadata]['abuse.confidence'] = Gitlab::Abuse.confidence(:certain)
@ -207,6 +215,10 @@ class SearchController < ApplicationController
def tracking_namespace_source
search_service.project&.namespace || search_service.group
end
def search_type
'basic'
end
end
SearchController.prepend_mod_with('SearchController')

View File

@ -5,11 +5,17 @@ module Mutations
module Widgetable
extend ActiveSupport::Concern
def extract_widget_params(work_item_type, attributes)
def extract_widget_params!(work_item_type, attributes)
# Get the list of widgets for the work item's type to extract only the supported attributes
widget_keys = work_item_type.widgets.map(&:api_symbol)
widget_keys = ::WorkItems::Type.available_widgets.map(&:api_symbol)
widget_params = attributes.extract!(*widget_keys)
not_supported_keys = widget_params.keys - work_item_type.widgets.map(&:api_symbol)
if not_supported_keys.present?
raise Gitlab::Graphql::Errors::ArgumentError,
"Following widget keys are not supported by #{work_item_type.name} type: #{not_supported_keys}"
end
# Cannot use prepare to use `.to_h` on each input due to
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87472#note_945199865
widget_params.transform_values { |values| values.to_h }

View File

@ -43,7 +43,7 @@ module Mutations
spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
params = global_id_compatibility_params(attributes).merge(author_id: current_user.id)
type = ::WorkItems::Type.find(attributes[:work_item_type_id])
widget_params = extract_widget_params(type, params)
widget_params = extract_widget_params!(type, params)
create_result = ::WorkItems::CreateService.new(
project: project,

View File

@ -25,7 +25,7 @@ module Mutations
end
spam_params = ::Spam::SpamParams.new_from_request(request: context[:request])
widget_params = extract_widget_params(work_item.work_item_type, attributes)
widget_params = extract_widget_params!(work_item.work_item_type, attributes)
update_result = ::WorkItems::UpdateService.new(
project: work_item.project,

View File

@ -14,7 +14,8 @@ module Types
argument :children_ids, [::Types::GlobalIDType[::WorkItem]],
required: false,
description: 'Global IDs of children work items.',
prepare: ->(ids, _) { ids.map(&:model_id) }
loads: ::Types::WorkItemType,
as: :children
end
end
end

View File

@ -1064,7 +1064,11 @@ module Ci
end
def has_reports?(reports_scope)
complete? && latest_report_builds(reports_scope).exists?
if Feature.enabled?(:mr_show_reports_immediately, project, type: :development)
latest_report_builds(reports_scope).exists?
else
complete? && latest_report_builds(reports_scope).exists?
end
end
def has_coverage_reports?

View File

@ -343,6 +343,10 @@ class Namespace < ApplicationRecord
end
end
def emails_enabled?
!emails_disabled?
end
def lfs_enabled?
# User namespace will always default to the global setting
Gitlab.config.lfs.enabled

View File

@ -125,6 +125,10 @@ class NotificationRecipient
@project ? @project.emails_disabled? : @group&.emails_disabled?
end
def emails_enabled?
!emails_disabled?
end
def read_ability
return if @skip_read_ability
return @read_ability if instance_variable_defined?(:@read_ability)

View File

@ -1038,6 +1038,9 @@ class Project < ApplicationRecord
end
end
def emails_enabled?
!emails_disabled?
end
override :lfs_enabled?
def lfs_enabled?
return namespace.lfs_enabled? if self[:lfs_enabled].nil?

View File

@ -91,6 +91,17 @@ class SearchService
end
end
def level
@level ||=
if project
'project'
elsif group
'group'
else
'global'
end
end
private
def page

View File

@ -38,12 +38,7 @@ module WorkItems
end
def extract_references
params[:issuable_references].map do |id|
::WorkItem.find(id)
rescue ActiveRecord::RecordNotFound
@errors << _("Task with ID: %{id} could not be found.") % { id: id }
next
end.compact
params[:issuable_references]
end
# TODO: Create system notes when work item's parent or children are updated

View File

@ -12,8 +12,8 @@ module WorkItems
if params.key?(:parent)
update_work_item_parent(params.delete(:parent))
elsif params.key?(:children_ids)
update_work_item_children(params.delete(:children_ids))
elsif params.key?(:children)
update_work_item_children(params.delete(:children))
else
invalid_args_error
end
@ -42,9 +42,9 @@ module WorkItems
end
# rubocop: enable CodeReuse/ActiveRecord
def update_work_item_children(children_ids)
def update_work_item_children(children)
::WorkItems::ParentLinks::CreateService
.new(widget.work_item, current_user, { issuable_references: children_ids })
.new(widget.work_item, current_user, { issuable_references: children })
.execute
end
@ -53,7 +53,7 @@ module WorkItems
end
def incompatible_args?(params)
params[:children_ids] && params[:parent]
params[:children] && params[:parent]
end
def feature_flag_error

View File

@ -504,19 +504,6 @@ module Gitlab
end
end
# We know Rails closes database connections in the
# active_record.clear_active_connections initializer, so only log database
# connections opened after that.
initializer :start_logging_new_postgresql_connections, after: :finisher_hook do
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.warn_on_new_connection = true
end
# It is legitimate to open database connections after initializers so stop
# logging
initializer :stop_logging_new_postgresql_connections, after: :set_routes_reloader_hook do
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.warn_on_new_connection = false
end
# Add assets for variants of GitLab. They should take precedence over CE.
# This means if multiple files exist, e.g.:
#

View File

@ -0,0 +1,8 @@
---
name: mr_show_reports_immediately
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76612
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367027
milestone: '15.2'
type: development
group: group::pipeline insights
default_enabled: false

View File

@ -1,26 +0,0 @@
# frozen_string_literal: true
module NewConnectionLogger
extend ActiveSupport::Concern
prepended do |base|
base.class_attribute :warn_on_new_connection, default: false
end
class_methods do
def new_client(...)
if warn_on_new_connection && !ENV['SKIP_LOG_INITIALIZER_CONNECTIONS']
cleaned_caller = Gitlab::BacktraceCleaner.clean_backtrace(caller)
message = "Database connection should not be called during initializers. Read more at https://docs.gitlab.com/ee/development/rails_initializers.html#database-connections-in-initializers"
ActiveSupport::Deprecation.warn(message, cleaned_caller)
warn caller if ENV['DEBUG_INITIALIZER_CONNECTIONS']
end
super
end
end
end
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(NewConnectionLogger)

View File

@ -1,6 +1,12 @@
# frozen_string_literal: true
Gitlab.ee do
if Gitlab::Geo.geo_database_configured?
# Make sure connects_to for geo gets called outside of config/routes.rb first
# See InitializerConnections.with_disabled_database_connections
Geo::TrackingBase
end
if Gitlab::Runtime.sidekiq? && Gitlab::Geo.geo_database_configured?
# The Geo::TrackingBase model does not yet use connects_to. So,
# this will not properly support geo: from config/databse.yml

View File

@ -4,336 +4,338 @@ require 'sidekiq/web'
require 'sidekiq/cron/web'
require 'product_analytics/collector_app'
Rails.application.routes.draw do
concern :access_requestable do
post :request_access, on: :collection
post :approve_access_request, on: :member
end
concern :awardable do
post :toggle_award_emoji, on: :member
end
favicon_redirect = redirect do |_params, _request|
ActionController::Base.helpers.asset_url(Gitlab::Favicon.main)
end
get 'favicon.png', to: favicon_redirect
get 'favicon.ico', to: favicon_redirect
draw :development
use_doorkeeper do
controllers applications: 'oauth/applications',
authorized_applications: 'oauth/authorized_applications',
authorizations: 'oauth/authorizations',
token_info: 'oauth/token_info',
tokens: 'oauth/tokens'
end
# This prefixless path is required because Jira gets confused if we set it up with a path
# More information: https://gitlab.com/gitlab-org/gitlab/issues/6752
scope path: '/login/oauth', controller: 'oauth/jira_dvcs/authorizations', as: :oauth_jira_dvcs do
get :authorize, action: :new
get :callback
post :access_token
match '*all', via: [:get, :post], to: proc { [404, {}, ['']] }
end
draw :oauth
use_doorkeeper_openid_connect do
controllers discovery: 'jwks'
end
# Add OPTIONS method for CORS preflight requests
match '/oauth/userinfo' => 'doorkeeper/openid_connect/userinfo#show', via: :options
match '/oauth/discovery/keys' => 'jwks#keys', via: :options
match '/.well-known/openid-configuration' => 'jwks#provider', via: :options
match '/.well-known/webfinger' => 'jwks#webfinger', via: :options
match '/oauth/token' => 'oauth/tokens#create', via: :options
match '/oauth/revoke' => 'oauth/tokens#revoke', via: :options
match '/-/jira_connect/oauth_application_id' => 'jira_connect/oauth_application_ids#show', via: :options
# Sign up
scope path: '/users/sign_up', module: :registrations, as: :users_sign_up do
resource :welcome, only: [:show, :update], controller: 'welcome' do
Gitlab.ee do
get :trial_getting_started, on: :collection
get :trial_onboarding_board, on: :collection
get :continuous_onboarding_getting_started, on: :collection
end
InitializerConnections.with_disabled_database_connections do
Rails.application.routes.draw do
concern :access_requestable do
post :request_access, on: :collection
post :approve_access_request, on: :member
end
Gitlab.ee do
resource :company, only: [:new, :create], controller: 'company'
resources :groups, only: [:new, :create]
resources :projects, only: [:new, :create]
resources :groups_projects, only: [:new, :create] do
collection do
post :import
put :exit
end
end
draw :verification
end
end
# Search
get 'search' => 'search#show', as: :search
get 'search/autocomplete' => 'search#autocomplete', as: :search_autocomplete
get 'search/count' => 'search#count', as: :search_count
get 'search/opensearch' => 'search#opensearch', as: :search_opensearch
# JSON Web Token
get 'jwt/auth' => 'jwt#auth'
# Health check
get 'health_check(/:checks)' => 'health_check#index', as: :health_check
# Terraform service discovery
get '.well-known/terraform.json' => 'terraform/services#index', as: :terraform_services
# Begin of the /-/ scope.
# Use this scope for all new global routes.
scope path: '-' do
# Autocomplete
get '/autocomplete/users' => 'autocomplete#users'
get '/autocomplete/users/:id' => 'autocomplete#user'
get '/autocomplete/projects' => 'autocomplete#projects'
get '/autocomplete/award_emojis' => 'autocomplete#award_emojis'
get '/autocomplete/merge_request_target_branches' => 'autocomplete#merge_request_target_branches'
get '/autocomplete/deploy_keys_with_owners' => 'autocomplete#deploy_keys_with_owners'
Gitlab.ee do
get '/autocomplete/project_groups' => 'autocomplete#project_groups'
get '/autocomplete/project_routes' => 'autocomplete#project_routes'
get '/autocomplete/namespace_routes' => 'autocomplete#namespace_routes'
get '/autocomplete/group_subgroups' => 'autocomplete#group_subgroups'
concern :awardable do
post :toggle_award_emoji, on: :member
end
# sandbox
get '/sandbox/mermaid' => 'sandbox#mermaid'
get '/whats_new' => 'whats_new#index'
get 'offline' => "pwa#offline"
get 'manifest' => "pwa#manifest", constraints: lambda { |req| req.format == :json }
# '/-/health' implemented by BasicHealthCheck middleware
get 'liveness' => 'health#liveness'
get 'readiness' => 'health#readiness'
controller :metrics do
get 'metrics', action: :index
get 'metrics/system', action: :system
favicon_redirect = redirect do |_params, _request|
ActionController::Base.helpers.asset_url(Gitlab::Favicon.main)
end
mount Peek::Railtie => '/peek', as: 'peek_routes'
get 'favicon.png', to: favicon_redirect
get 'favicon.ico', to: favicon_redirect
get 'runner_setup/platforms' => 'runner_setup#platforms'
draw :development
# Boards resources shared between group and projects
resources :boards, only: [] do
resources :lists, module: :boards, only: [:index, :create, :update, :destroy] do
collection do
post :generate
end
resources :issues, only: [:index, :create, :update]
end
resources :issues, module: :boards, only: [:index, :update] do
collection do
put :bulk_move, format: :json
end
end
Gitlab.ee do
resources :users, module: :boards, only: [:index]
resources :milestones, module: :boards, only: [:index]
end
use_doorkeeper do
controllers applications: 'oauth/applications',
authorized_applications: 'oauth/authorized_applications',
authorizations: 'oauth/authorizations',
token_info: 'oauth/token_info',
tokens: 'oauth/tokens'
end
get 'acme-challenge/' => 'acme_challenges#show'
# This prefixless path is required because Jira gets confused if we set it up with a path
# More information: https://gitlab.com/gitlab-org/gitlab/issues/6752
scope path: '/login/oauth', controller: 'oauth/jira_dvcs/authorizations', as: :oauth_jira_dvcs do
get :authorize, action: :new
get :callback
post :access_token
scope :ide, as: :ide, format: false do
get '/', to: 'ide#index'
get '/project', to: 'ide#index'
scope path: 'project/:project_id', as: :project, constraints: { project_id: Gitlab::PathRegex.full_namespace_route_regex } do
%w[edit tree blob].each do |action|
get "/#{action}", to: 'ide#index'
get "/#{action}/*branch/-/*path", to: 'ide#index'
get "/#{action}/*branch/-", to: 'ide#index'
get "/#{action}/*branch", to: 'ide#index'
end
get '/merge_requests/:merge_request_id', to: 'ide#index', constraints: { merge_request_id: /\d+/ }
get '/', to: 'ide#index'
end
match '*all', via: [:get, :post], to: proc { [404, {}, ['']] }
end
draw :operations
draw :jira_connect
draw :oauth
Gitlab.ee do
draw :security
draw :smartcard
draw :trial
draw :trial_registration
draw :country
draw :country_state
draw :subscription
scope '/push_from_secondary/:geo_node_id' do
draw :git_http
end
# Used for survey responses
resources :survey_responses, only: :index
use_doorkeeper_openid_connect do
controllers discovery: 'jwks'
end
Gitlab.jh do
draw :global_jh
end
# Add OPTIONS method for CORS preflight requests
match '/oauth/userinfo' => 'doorkeeper/openid_connect/userinfo#show', via: :options
match '/oauth/discovery/keys' => 'jwks#keys', via: :options
match '/.well-known/openid-configuration' => 'jwks#provider', via: :options
match '/.well-known/webfinger' => 'jwks#webfinger', via: :options
if ENV['GITLAB_CHAOS_SECRET'] || Rails.env.development? || Rails.env.test?
resource :chaos, only: [] do
get :leakmem
get :cpu_spin
get :db_spin
get :sleep
get :kill
get :quit
post :gc
end
end
match '/oauth/token' => 'oauth/tokens#create', via: :options
match '/oauth/revoke' => 'oauth/tokens#revoke', via: :options
resources :invites, only: [:show], constraints: { id: /[A-Za-z0-9_-]+/ } do
member do
post :accept
match :decline, via: [:get, :post]
end
end
match '/-/jira_connect/oauth_application_id' => 'jira_connect/oauth_application_ids#show', via: :options
resources :sent_notifications, only: [], constraints: { id: /\h{32}/ } do
member do
get :unsubscribe
end
end
# Spam reports
resources :abuse_reports, only: [:new, :create]
# JWKS (JSON Web Key Set) endpoint
# Used by third parties to verify CI_JOB_JWT
get 'jwks' => 'jwks#index'
draw :snippets
draw :profile
post '/mailgun/webhooks' => 'mailgun/webhooks#process_webhook'
# Deprecated route for permanent failures
# https://gitlab.com/gitlab-org/gitlab/-/issues/362606
post '/members/mailgun/permanent_failures' => 'mailgun/webhooks#process_webhook'
# Product analytics collector
match '/collector/i', to: ProductAnalytics::CollectorApp.new, via: :all
end
# End of the /-/ scope.
concern :clusterable do
resources :clusters, only: [:index, :show, :update, :destroy] do
collection do
get :connect
get :new_cluster_docs
post :create_user
end
resource :integration, controller: 'clusters/integrations', only: [] do
collection do
post :create_or_update
end
end
member do
# Sign up
scope path: '/users/sign_up', module: :registrations, as: :users_sign_up do
resource :welcome, only: [:show, :update], controller: 'welcome' do
Gitlab.ee do
get :metrics, format: :json
get :environments, format: :json
get :trial_getting_started, on: :collection
get :trial_onboarding_board, on: :collection
get :continuous_onboarding_getting_started, on: :collection
end
end
get :metrics_dashboard
get :'/prometheus/api/v1/*proxy_path', to: 'clusters#prometheus_proxy', as: :prometheus_api
get :cluster_status, format: :json
delete :clear_cache
Gitlab.ee do
resource :company, only: [:new, :create], controller: 'company'
resources :groups, only: [:new, :create]
resources :projects, only: [:new, :create]
resources :groups_projects, only: [:new, :create] do
collection do
post :import
put :exit
end
end
draw :verification
end
end
end
resources :groups, only: [:index, :new, :create] do
post :preview_markdown
end
# Search
get 'search' => 'search#show', as: :search
get 'search/autocomplete' => 'search#autocomplete', as: :search_autocomplete
get 'search/count' => 'search#count', as: :search_count
get 'search/opensearch' => 'search#opensearch', as: :search_opensearch
draw :group
# JSON Web Token
get 'jwt/auth' => 'jwt#auth'
resources :projects, only: [:index, :new, :create]
# Health check
get 'health_check(/:checks)' => 'health_check#index', as: :health_check
get '/projects/:id' => 'projects/redirect#redirect_from_id'
# Terraform service discovery
get '.well-known/terraform.json' => 'terraform/services#index', as: :terraform_services
draw :git_http
draw :api
draw :customers_dot
draw :sidekiq
draw :help
draw :google_api
draw :import
draw :uploads
draw :explore
draw :admin
draw :dashboard
draw :user
draw :project
draw :unmatched_project
# Begin of the /-/ scope.
# Use this scope for all new global routes.
scope path: '-' do
# Autocomplete
get '/autocomplete/users' => 'autocomplete#users'
get '/autocomplete/users/:id' => 'autocomplete#user'
get '/autocomplete/projects' => 'autocomplete#projects'
get '/autocomplete/award_emojis' => 'autocomplete#award_emojis'
get '/autocomplete/merge_request_target_branches' => 'autocomplete#merge_request_target_branches'
get '/autocomplete/deploy_keys_with_owners' => 'autocomplete#deploy_keys_with_owners'
# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/210024
scope as: 'deprecated' do
# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/223719
get '/snippets/:id/raw',
to: 'snippets#raw',
format: false,
constraints: { id: /\d+/ }
Gitlab.ee do
get '/autocomplete/project_groups' => 'autocomplete#project_groups'
get '/autocomplete/project_routes' => 'autocomplete#project_routes'
get '/autocomplete/namespace_routes' => 'autocomplete#namespace_routes'
get '/autocomplete/group_subgroups' => 'autocomplete#group_subgroups'
end
Gitlab::Routing.redirect_legacy_paths(self, :snippets)
end
# sandbox
get '/sandbox/mermaid' => 'sandbox#mermaid'
Gitlab.ee do
get '/sitemap' => 'sitemap#show', format: :xml
end
get '/whats_new' => 'whats_new#index'
# Creates shorthand helper methods for project resources.
# For example; for the `namespace_project_path` this also creates `project_path`.
#
# TODO: We don't need the `Gitlab::Routing` module at all as we can use
# the `direct` DSL method of Rails to define url helpers. Move all the
# custom url helpers to use the `direct` DSL method and remove the `Gitlab::Routing`.
# For more information: https://gitlab.com/gitlab-org/gitlab/-/issues/299583
Gitlab::Application.routes.set.filter_map { |route| route.name if route.name&.include?('namespace_project') }.each do |name|
new_name = name.sub('namespace_project', 'project')
get 'offline' => "pwa#offline"
get 'manifest' => "pwa#manifest", constraints: lambda { |req| req.format == :json }
direct(new_name) do |project, *args|
# This is due to a bug I've found in Rails.
# For more information: https://gitlab.com/gitlab-org/gitlab/-/issues/299591
args.pop if args.last == {}
# '/-/health' implemented by BasicHealthCheck middleware
get 'liveness' => 'health#liveness'
get 'readiness' => 'health#readiness'
controller :metrics do
get 'metrics', action: :index
get 'metrics/system', action: :system
end
mount Peek::Railtie => '/peek', as: 'peek_routes'
send("#{name}_url", project&.namespace, project, *args)
get 'runner_setup/platforms' => 'runner_setup#platforms'
# Boards resources shared between group and projects
resources :boards, only: [] do
resources :lists, module: :boards, only: [:index, :create, :update, :destroy] do
collection do
post :generate
end
resources :issues, only: [:index, :create, :update]
end
resources :issues, module: :boards, only: [:index, :update] do
collection do
put :bulk_move, format: :json
end
end
Gitlab.ee do
resources :users, module: :boards, only: [:index]
resources :milestones, module: :boards, only: [:index]
end
end
get 'acme-challenge/' => 'acme_challenges#show'
scope :ide, as: :ide, format: false do
get '/', to: 'ide#index'
get '/project', to: 'ide#index'
scope path: 'project/:project_id', as: :project, constraints: { project_id: Gitlab::PathRegex.full_namespace_route_regex } do
%w[edit tree blob].each do |action|
get "/#{action}", to: 'ide#index'
get "/#{action}/*branch/-/*path", to: 'ide#index'
get "/#{action}/*branch/-", to: 'ide#index'
get "/#{action}/*branch", to: 'ide#index'
end
get '/merge_requests/:merge_request_id', to: 'ide#index', constraints: { merge_request_id: /\d+/ }
get '/', to: 'ide#index'
end
end
draw :operations
draw :jira_connect
Gitlab.ee do
draw :security
draw :smartcard
draw :trial
draw :trial_registration
draw :country
draw :country_state
draw :subscription
scope '/push_from_secondary/:geo_node_id' do
draw :git_http
end
# Used for survey responses
resources :survey_responses, only: :index
end
Gitlab.jh do
draw :global_jh
end
if ENV['GITLAB_CHAOS_SECRET'] || Rails.env.development? || Rails.env.test?
resource :chaos, only: [] do
get :leakmem
get :cpu_spin
get :db_spin
get :sleep
get :kill
get :quit
post :gc
end
end
resources :invites, only: [:show], constraints: { id: /[A-Za-z0-9_-]+/ } do
member do
post :accept
match :decline, via: [:get, :post]
end
end
resources :sent_notifications, only: [], constraints: { id: /\h{32}/ } do
member do
get :unsubscribe
end
end
# Spam reports
resources :abuse_reports, only: [:new, :create]
# JWKS (JSON Web Key Set) endpoint
# Used by third parties to verify CI_JOB_JWT
get 'jwks' => 'jwks#index'
draw :snippets
draw :profile
post '/mailgun/webhooks' => 'mailgun/webhooks#process_webhook'
# Deprecated route for permanent failures
# https://gitlab.com/gitlab-org/gitlab/-/issues/362606
post '/members/mailgun/permanent_failures' => 'mailgun/webhooks#process_webhook'
# Product analytics collector
match '/collector/i', to: ProductAnalytics::CollectorApp.new, via: :all
end
# End of the /-/ scope.
concern :clusterable do
resources :clusters, only: [:index, :show, :update, :destroy] do
collection do
get :connect
get :new_cluster_docs
post :create_user
end
resource :integration, controller: 'clusters/integrations', only: [] do
collection do
post :create_or_update
end
end
member do
Gitlab.ee do
get :metrics, format: :json
get :environments, format: :json
end
get :metrics_dashboard
get :'/prometheus/api/v1/*proxy_path', to: 'clusters#prometheus_proxy', as: :prometheus_api
get :cluster_status, format: :json
delete :clear_cache
end
end
end
resources :groups, only: [:index, :new, :create] do
post :preview_markdown
end
draw :group
resources :projects, only: [:index, :new, :create]
get '/projects/:id' => 'projects/redirect#redirect_from_id'
draw :git_http
draw :api
draw :customers_dot
draw :sidekiq
draw :help
draw :google_api
draw :import
draw :uploads
draw :explore
draw :admin
draw :dashboard
draw :user
draw :project
draw :unmatched_project
# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/210024
scope as: 'deprecated' do
# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/223719
get '/snippets/:id/raw',
to: 'snippets#raw',
format: false,
constraints: { id: /\d+/ }
Gitlab::Routing.redirect_legacy_paths(self, :snippets)
end
Gitlab.ee do
get '/sitemap' => 'sitemap#show', format: :xml
end
# Creates shorthand helper methods for project resources.
# For example; for the `namespace_project_path` this also creates `project_path`.
#
# TODO: We don't need the `Gitlab::Routing` module at all as we can use
# the `direct` DSL method of Rails to define url helpers. Move all the
# custom url helpers to use the `direct` DSL method and remove the `Gitlab::Routing`.
# For more information: https://gitlab.com/gitlab-org/gitlab/-/issues/299583
Gitlab::Application.routes.set.filter_map { |route| route.name if route.name&.include?('namespace_project') }.each do |name|
new_name = name.sub('namespace_project', 'project')
direct(new_name) do |project, *args|
# This is due to a bug I've found in Rails.
# For more information: https://gitlab.com/gitlab-org/gitlab/-/issues/299591
args.pop if args.last == {}
send("#{name}_url", project&.namespace, project, *args)
end
end
root to: "root#index"
get '*unmatched_route', to: 'application#route_not_found', format: false
end
root to: "root#index"
get '*unmatched_route', to: 'application#route_not_found', format: false
Gitlab::Routing.add_helpers(TimeboxesRoutingHelper)
end
Gitlab::Routing.add_helpers(TimeboxesRoutingHelper)

View File

@ -21,15 +21,15 @@ Get project-level DORA metrics.
GET /projects/:id/dora/metrics
```
| Attribute | Type | Required | Description |
|----------------------|------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../index.md#namespaced-path-encoding) can be accessed by the authenticated user. |
| `metric` | string | yes | One of `deployment_frequency`, `lead_time_for_changes`, `time_to_restore_service` or `change_failure_rate`. |
| `start_date` | string | no | Date range to start from. ISO 8601 Date format, for example `2021-03-01`. Default is 3 months ago. |
| `end_date` | string | no | Date range to end at. ISO 8601 Date format, for example `2021-03-01`. Default is the current date. |
| `interval` | string | no | The bucketing interval. One of `all`, `monthly` or `daily`. Default is `daily`. |
| Attribute | Type | Required | Description |
|:---------------------|:-----------------|:---------|:------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../index.md#namespaced-path-encoding) can be accessed by the authenticated user. |
| `metric` | string | yes | One of `deployment_frequency`, `lead_time_for_changes`, `time_to_restore_service` or `change_failure_rate`. |
| `end_date` | string | no | Date range to end at. ISO 8601 Date format, for example `2021-03-01`. Default is the current date. |
| `environment_tier` | string | no | The [tier of the environment](../../ci/environments/index.md#deployment-tier-of-environments). Default is `production`. Deprecated, please use `environment_tiers`. |
| `environment_tiers` | array of strings | no | The [tiers of the environments](../../ci/environments/index.md#deployment-tier-of-environments). Default is `production`. |
| `environment_tiers` | array of strings | no | The [tiers of the environments](../../ci/environments/index.md#deployment-tier-of-environments). Default is `production`. |
| `interval` | string | no | The bucketing interval. One of `all`, `monthly` or `daily`. Default is `daily`. |
| `start_date` | string | no | Date range to start from. ISO 8601 Date format, for example `2021-03-01`. Default is 3 months ago. |
Example request:
@ -62,15 +62,15 @@ Get group-level DORA metrics.
GET /groups/:id/dora/metrics
```
| Attribute | Type | Required | Description |
|---------------------|------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../index.md#namespaced-path-encoding) can be accessed by the authenticated user. |
| `metric` | string | yes | One of `deployment_frequency`, `lead_time_for_changes`, `time_to_restore_service` or `change_failure_rate`. |
| `start_date` | string | no | Date range to start from. ISO 8601 Date format, for example `2021-03-01`. Default is 3 months ago. |
| `end_date` | string | no | Date range to end at. ISO 8601 Date format, for example `2021-03-01`. Default is the current date. |
| `interval` | string | no | The bucketing interval. One of `all`, `monthly` or `daily`. Default is `daily`. |
| Attribute | Type | Required | Description |
|:--------------------|:-----------------|:---------|:------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../index.md#namespaced-path-encoding) can be accessed by the authenticated user. |
| `metric` | string | yes | One of `deployment_frequency`, `lead_time_for_changes`, `time_to_restore_service` or `change_failure_rate`. |
| `end_date` | string | no | Date range to end at. ISO 8601 Date format, for example `2021-03-01`. Default is the current date. |
| `environment_tier` | string | no | The [tier of the environment](../../ci/environments/index.md#deployment-tier-of-environments). Default is `production`. Deprecated, please use `environment_tiers`. |
| `environment_tiers` | array of strings | no | The [tiers of the environments](../../ci/environments/index.md#deployment-tier-of-environments). Default is `production`. |
| `environment_tiers` | array of strings | no | The [tiers of the environments](../../ci/environments/index.md#deployment-tier-of-environments). Default is `production`. |
| `interval` | string | no | The bucketing interval. One of `all`, `monthly` or `daily`. Default is `daily`. |
| `start_date` | string | no | Date range to start from. ISO 8601 Date format, for example `2021-03-01`. Default is 3 months ago. |
Example request:
@ -99,9 +99,9 @@ For both the project and group-level endpoints above, the `value` field in the
API response has a different meaning depending on the provided `metric` query
parameter:
| `metric` query parameter | Description of `value` in response |
| ------------------------ |--------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `deployment_frequency` | The number of successful deployments during the time period. |
| `lead_time_for_changes` | The median number of seconds between the merge of the merge request (MR) and the deployment of the MR's commits for all MRs deployed during the time period. |
| `time_to_restore_service` | The median number of seconds an incident was open during the time period. Available only for production environment. |
| `change_failure_rate` | The number of incidents divided by the number of deployments during the time period. Available only for production environment. |
| `metric` query parameter | Description of `value` in response |
|:---------------------------|:-----------------------------------|
| `change_failure_rate` | The number of incidents divided by the number of deployments during the time period. Available only for production environment. |
| `deployment_frequency` | The number of successful deployments during the time period. |
| `lead_time_for_changes` | The median number of seconds between the merge of the merge request (MR) and the deployment of the MR's commits for all MRs deployed during the time period. |
| `time_to_restore_service` | The median number of seconds an incident was open during the time period. Available only for production environment. |

View File

@ -1099,6 +1099,8 @@ that use the same cache key use the same cache, including in different pipelines
If not set, the default key is `default`. All jobs with the `cache` keyword but
no `cache:key` share the `default` cache.
Must be used with `cache: path`, or nothing is cached.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
@ -1263,6 +1265,8 @@ rspec:
Use `cache:when` to define when to save the cache, based on the status of the job.
Must be used with `cache: path`, or nothing is cached.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
@ -1301,6 +1305,8 @@ Use the `pull` policy when you have many jobs executing in parallel that use the
This policy speeds up job execution and reduces load on the cache server. You can
use a job with the `push` policy to build the cache.
Must be used with `cache: path`, or nothing is cached.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).

View File

@ -289,9 +289,32 @@ Please read [versioning](#versioning) section for introducing breaking change sa
## Versioning
Versioning allows you to introduce a new template without modifying the existing
one. This process is useful when we need to introduce a breaking change,
but don't want to affect the existing projects that depends on the current template.
To introduce a breaking change without affecting the existing projects that depend on
the current template, use [stable](#stable-version) and [latest](#latest-version) versioning.
Stable templates usually only receive breaking changes in major version releases, while
latest templates can receive breaking changes in any release. In major release milestones,
the latest template is made the new stable template (and the latest template might be deleted).
Adding a latest template is safe, but comes with a maintenance burden:
- GitLab has to choose a DRI to overwrite the stable template with the contents of the
latest template at the next major release of GitLab. The DRI is responsible for
supporting users who have trouble with the change.
- When we make a new non-breaking change, both the stable and latest templates must be updated
to match, as must as possible.
- A latest template could remain for longer than planned because many users could
directly depend on it continuing to exist.
Before adding a new latest template, see if the change can be made to the stable
template instead, even if it's a breaking change. If the template is intended for copy-paste
usage only, it might be possible to directly change the stable version. Before changing
the stable template with a breaking change in a minor milestone, make sure:
- It's a [pipeline template](#template-types) and it has a [code comment](#explain-requirements-and-expectations)
explaining that it's not designed to be used with the `includes`.
- The [CI/CD template usage metrics](#add-metrics) doesn't show any usage. If the metrics
show zero usage for the template, the template is not actively being used with `include`.
### Stable version
@ -393,7 +416,9 @@ is updated in a major version GitLab release.
### Add metrics
Every CI/CD template must also have metrics defined to track their use. The CI/CD template monthly usage report can be found in [Sisense (GitLab team members only)](https://app.periscopedata.com/app/gitlab/785953/Pipeline-Authoring-Dashboard?widget=14910475&udv=0).
Every CI/CD template must also have metrics defined to track their use. The CI/CD template monthly usage report
can be found in [Sisense (GitLab team members only)](https://app.periscopedata.com/app/gitlab/785953/Pipeline-Authoring-Dashboard?widget=13440051&udv=0).
Double click a template to see the graph for that single template.
To add a metric definition for a new template:

View File

@ -29,12 +29,18 @@ query) from an initializer means that tasks like `db:drop`, and
`db:test:prepare` will fail because an active session prevents the database from
being dropped.
To help detect when database connections are opened from initializers, we now
warn in `STDERR`. For example:
To prevent this, we stop database connections from being opened during
routes loading. Doing will result in an error:
```shell
DEPRECATION WARNING: Database connection should not be called during initializers (called from block in <module:HasVariable> at app/models/concerns/ci/has_variable.rb:22)
RuntimeError:
Database connection should not be called during initializers.
# ./config/initializers/00_connection_logger.rb:15:in `new_client'
# ./lib/gitlab/database/load_balancing/load_balancer.rb:112:in `block in read_write'
# ./lib/gitlab/database/load_balancing/load_balancer.rb:184:in `retry_with_backoff'
# ./lib/gitlab/database/load_balancing/load_balancer.rb:111:in `read_write'
# ./lib/gitlab/database/load_balancing/connection_proxy.rb:119:in `write_using_load_balancer'
# ./lib/gitlab/database/load_balancing/connection_proxy.rb:89:in `method_missing'
# ./config/routes.rb:10:in `block in <main>'
# ./config/routes.rb:9:in `<main>'
```
If you wish to print out the full backtrace, set the
`DEBUG_INITIALIZER_CONNECTIONS` environment variable.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -152,9 +152,9 @@ become eligible approvers in the project. To enable this merge request approval
1. Go to your project and select **Settings > General**.
1. Expand **Merge request (MR) approvals**.
1. Locate **Eligible users** and select the number of approvals required:
1. Locate **All eligible users** and select the number of approvals required:
![MR approvals by Code Owners](img/mr_approvals_by_code_owners_v12_7.png)
![MR approvals by Code Owners](img/mr_approvals_by_code_owners_v15_2.png)
You can also
[require code owner approval](../../protected_branches.md#require-code-owner-approval-on-a-protected-branch)

View File

@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
[Burndown](#burndown-charts) and [burnup](#burnup-charts) charts show the progress of completing a milestone.
![burndown and burnup chart](img/burndown_and_burnup_charts_v15_1.png)
![burndown and burnup chart](img/burndown_and_burnup_charts_v15_3.png)
## Burndown charts
@ -19,7 +19,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Burndown charts show the number of issues over the course of a milestone.
![burndown chart](img/burndown_chart_v15_1.png)
![burndown chart](img/burndown_chart_v15_3.png)
At a glance, you see the current state for the completion a given milestone.
Without them, you would have to organize the data from the milestone and plot it
@ -106,7 +106,7 @@ Reopened issues are considered as having been opened on the day after they were
Burnup charts show the assigned and completed work for a milestone.
![burnup chart](img/burnup_chart_v15_1.png)
![burnup chart](img/burnup_chart_v15_3.png)
To view a project's burnup chart:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -196,7 +196,7 @@ There are also tabs below these that show the following:
The milestone view contains a [burndown and burnup chart](burndown_and_burnup_charts.md),
showing the progress of completing a milestone.
![burndown chart](img/burndown_and_burnup_charts_v15_1.png)
![burndown chart](img/burndown_and_burnup_charts_v15_3.png)
### Milestone sidebar

View File

@ -1284,3 +1284,5 @@ module API
end
end
end
API::Users.prepend_mod

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,14 +1,17 @@
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Chef.gitlab-ci.yml
# This template uses Test Kitchen with the kitchen-dokken driver to
# perform functional testing. Doing so requires that your runner be a
# Docker runner configured for privileged mode. Please see
# https://docs.gitlab.com/runner/executors/docker.html#use-docker-in-docker-with-privileged-mode
# for help configuring your runner properly, or, if you want to switch
# to a different driver, see http://kitchen.ci/docs/drivers
#
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Chef.gitlab-ci.yml
image: "chef/chefdk"
services:

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,8 +1,3 @@
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml
# This is a sample GitLab CI/CD configuration file that should run without any modifications.
# It demonstrates a basic 3 stage CI/CD pipeline. Instead of real tests or scripts,
# it uses echo commands to simulate the pipeline execution.
@ -11,6 +6,14 @@
# Stages run in sequential order, but jobs within stages run in parallel.
#
# For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages
#
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml
stages: # List of stages for jobs, and their order of execution
- build

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,8 +1,3 @@
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Grails.gitlab-ci.yml
# This template uses the java:8 docker image because there isn't any
# official Grails image at this moment
#
@ -12,6 +7,14 @@
# Feel free to change GRAILS_VERSION version with your project version (3.0.1, 3.1.1,...)
# Feel free to change GRADLE_VERSION version with your gradle project version (2.13, 2.14,...)
# If you use Angular profile, this yml it's prepared to work with it
#
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Grails.gitlab-ci.yml
image: java:8

View File

@ -1,8 +1,3 @@
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Julia.gitlab-ci.yml
# This is an example .gitlab-ci.yml file to test (and optionally report the coverage
# results of) your [Julia][1] packages. Please refer to the [documentation][2]
# for more information about package development in Julia.
@ -12,6 +7,14 @@
#
# [1]: http://julialang.org/
# [2]: https://docs.julialang.org/en/v1/manual/documentation/index.html
#
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Julia.gitlab-ci.yml
# Below is the template to run your tests in Julia
.test_template: &test_definition

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,8 +1,3 @@
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Mono.gitlab-ci.yml
# This is a simple gitlab continuous integration template (compatible with the shared runner provided on gitlab.com)
# using the official mono docker image to build a visual studio project.
#
@ -15,6 +10,14 @@
#
# Please find the full example project here:
# https://gitlab.com/tobiaskoch/gitlab-ci-example-mono
#
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Mono.gitlab-ci.yml
# see https://hub.docker.com/_/mono/
image: mono:latest

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -1,3 +1,6 @@
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:

View File

@ -23,6 +23,9 @@
# You need to have the network drive mapped as Local System user for gitlab-runner service to see it
# The best way to persist the mapping is via a scheduled task
# running the following batch command: net use P: \\x.x.x.x\Projects /u:your_user your_pass /persistent:yes
#
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
# place project specific paths in variables to make the rest of the script more generic
variables:

View File

@ -1,8 +1,3 @@
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml
# This is a very simple template that mainly relies on FastLane to build and distribute your app.
# Read more about how to use this template on the blog post https://about.gitlab.com/2019/03/06/ios-publishing-with-gitlab-and-fastlane/
# You will also need fastlane and signing configuration for this to work, along with a MacOS runner.
@ -15,6 +10,14 @@
# https://docs.gitlab.com/runner/security/#usage-of-shell-executor for additional
# detail on what to keep in mind in this scenario.
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml
stages:
- build
- test

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
module InitializerConnections
# Prevents any database connections within the block
# by using an empty connection handler
# rubocop:disable Database/MultipleDatabases
def self.with_disabled_database_connections
return yield if Gitlab::Utils.to_boolean(ENV['SKIP_RAISE_ON_INITIALIZE_CONNECTIONS'])
original_handler = ActiveRecord::Base.connection_handler
dummy_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
ActiveRecord::Base.connection_handler = dummy_handler
yield
if dummy_handler&.connection_pool_names&.present?
raise "Unxpected connection_pools (#{dummy_handler.connection_pool_names}) ! Call `connects_to` before this block"
end
rescue ActiveRecord::ConnectionNotEstablished
message = "Database connection should not be called during initializers. Read more at https://docs.gitlab.com/ee/development/rails_initializers.html#database-connections-in-initializers"
raise message
ensure
ActiveRecord::Base.connection_handler = original_handler
dummy_handler&.clear_all_connections!
end
# rubocop:enable Database/MultipleDatabases
end

View File

@ -3758,6 +3758,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
msgid "All eligible users"
msgstr ""
msgid "All email addresses will be used to identify your commits."
msgstr ""
@ -14125,9 +14128,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
msgid "Eligible users"
msgstr ""
msgid "Email"
msgstr ""
@ -21916,6 +21916,9 @@ msgstr ""
msgid "Iterations|All"
msgstr ""
msgid "Iterations|Automatic scheduling"
msgstr ""
msgid "Iterations|Cadence configuration is invalid."
msgstr ""
@ -21937,6 +21940,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
msgid "Iterations|Create iterations automatically on a regular schedule."
msgstr ""
msgid "Iterations|Delete cadence"
msgstr ""
@ -21967,6 +21973,9 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
msgid "Iterations|Enable roll over"
msgstr ""
msgid "Iterations|Error loading iteration cadences."
msgstr ""
@ -21979,6 +21988,9 @@ msgstr ""
msgid "Iterations|Iterations are a way to track issues over a period of time, allowing teams to also track velocity and volatility metrics."
msgstr ""
msgid "Iterations|Iterations are scheduled to start on %{weekday}s."
msgstr ""
msgid "Iterations|Learn more about automatic scheduling"
msgstr ""
@ -22006,9 +22018,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
msgid "Iterations|No one can change this date after the cadence has begun."
msgstr ""
msgid "Iterations|No open iterations."
msgstr ""
@ -23225,7 +23234,7 @@ msgstr ""
msgid "License Compliance"
msgstr ""
msgid "License Compliance| Used by"
msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@ -38225,9 +38234,6 @@ msgstr ""
msgid "Task list"
msgstr ""
msgid "Task with ID: %{id} could not be found."
msgstr ""
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@ -42054,6 +42060,11 @@ msgstr ""
msgid "Used"
msgstr ""
msgid "Used by %d package"
msgid_plural "Used by %d packages"
msgstr[0] ""
msgstr[1] ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""

View File

@ -5,7 +5,7 @@ echo "Processing vuln report"
# Preparing the message for the comment that will be posted by the bot
# Empty string if there are no findings
jq -crM '.vulnerabilities |
map( select( .identifiers[0].name | test( "glappsec_" ) ) |
map( select( .identifiersprocess_custom_semgrep_results[0].name | test( "glappsec_" ) ) |
"- `" + .location.file + "` line " + ( .location.start_line | tostring ) +
(
if .location.start_line = .location.end_line then ""

View File

@ -408,10 +408,11 @@ RSpec.describe SearchController do
expect(payload[:metadata]['meta.search.filters.confidential']).to eq('true')
expect(payload[:metadata]['meta.search.filters.state']).to eq('true')
expect(payload[:metadata]['meta.search.project_ids']).to eq(%w(456 789))
expect(payload[:metadata]['meta.search.search_level']).to eq('multi-project')
expect(payload[:metadata]['meta.search.type']).to eq('basic')
expect(payload[:metadata]['meta.search.level']).to eq('global')
end
get :show, params: { scope: 'issues', search: 'hello world', group_id: '123', project_id: '456', project_ids: %w(456 789), search_level: 'multi-project', confidential: true, state: true, force_search_results: true }
get :show, params: { scope: 'issues', search: 'hello world', group_id: '123', project_id: '456', project_ids: %w(456 789), confidential: true, state: true, force_search_results: true }
end
it 'appends the default scope in meta.search.scope' do
@ -423,6 +424,16 @@ RSpec.describe SearchController do
get :show, params: { search: 'hello world', group_id: '123', project_id: '456' }
end
it 'appends the search time based on the search' do
expect(controller).to receive(:append_info_to_payload).and_wrap_original do |method, payload|
method.call(payload)
expect(payload[:metadata][:global_search_duration_s]).to be_a_kind_of(Numeric)
end
get :show, params: { search: 'hello world', group_id: '123', project_id: '456' }
end
end
context 'abusive searches', :aggregate_failures do

View File

@ -24,23 +24,21 @@ RSpec.describe 'Merge request > User sees versions', :js do
visit diffs_project_merge_request_path(project, merge_request, params)
end
shared_examples 'allows commenting' do |file_id:, line_code:, comment:|
shared_examples 'allows commenting' do |file_name:, line_text:, comment:|
it do
diff_file_selector = ".diff-file[id='#{file_id}']"
line_code = "#{file_id}_#{line_code}"
page.within find_by_scrolling('.diff-file', text: file_name) do
line_code_element = page.find('.diff-grid-row', text: line_text)
page.within find_by_scrolling(diff_file_selector) do
line_code_element = first("[id='#{line_code}']")
# scrolling to element's bottom is required in order for .hover action to work
# otherwise, the element could be hidden underneath a sticky header
scroll_to_elements_bottom(line_code_element)
line_code_element.hover
first("[id='#{line_code}'] [role='button']").click
page.find("[data-testid='left-comment-button']", visible: true).click
page.within("form[data-line-code='#{line_code}']") do
fill_in "note[note]", with: comment
click_button('Add comment now')
end
expect(page).to have_selector("form", count: 1)
fill_in("note[note]", with: comment)
click_button('Add comment now')
wait_for_requests
@ -59,8 +57,8 @@ RSpec.describe 'Merge request > User sees versions', :js do
end
it_behaves_like 'allows commenting',
file_id: '7445606fbf8f3683cd42bdc54b05d7a0bc2dfc44',
line_code: '1_1',
file_name: '.gitmodules',
line_text: '[submodule "six"]',
comment: 'Typo, please fix.'
end
@ -107,8 +105,8 @@ RSpec.describe 'Merge request > User sees versions', :js do
end
it_behaves_like 'allows commenting',
file_id: '7445606fbf8f3683cd42bdc54b05d7a0bc2dfc44',
line_code: '2_2',
file_name: '.gitmodules',
line_text: 'path = six',
comment: 'Typo, please fix.'
end
@ -174,9 +172,9 @@ RSpec.describe 'Merge request > User sees versions', :js do
end
it_behaves_like 'allows commenting',
file_id: '7445606fbf8f3683cd42bdc54b05d7a0bc2dfc44',
line_code: '4_4',
comment: 'Typo, please fix.'
file_name: '.gitmodules',
line_text: '[submodule "gitlab-shell"]',
comment: 'Typo, please fix.'
end
describe 'compare with same version' do
@ -241,8 +239,8 @@ RSpec.describe 'Merge request > User sees versions', :js do
end
it_behaves_like 'allows commenting',
file_id: '2f6fcd96b88b36ce98c38da085c795a27d92a3dd',
line_code: '6_6',
file_name: 'files/ruby/popen.rb',
line_text: 'RuntimeError',
comment: 'Typo, please fix.'
end
end

View File

@ -4,13 +4,14 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { mockTracking } from 'helpers/tracking_helper';
import { stripTypenames } from 'helpers/graphql_helpers';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import userSearchQuery from '~/graphql_shared/queries/users_search.query.graphql';
import currentUserQuery from '~/graphql_shared/queries/current_user.query.graphql';
import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
import WorkItemAssignees from '~/work_items/components/work_item_assignees.vue';
import { i18n } from '~/work_items/constants';
import { i18n, TASK_TYPE_NAME, TRACKING_CATEGORY_SHOW } from '~/work_items/constants';
import { temporaryConfig, resolvers } from '~/work_items/graphql/provider';
import {
projectMembersResponseWithCurrentUser,
@ -50,6 +51,7 @@ describe('WorkItemAssignees component', () => {
searchQueryHandler = successSearchQueryHandler,
currentUserQueryHandler = successCurrentUserQueryHandler,
allowsMultipleAssignees = true,
canUpdate = true,
} = {}) => {
const apolloProvider = createMockApollo(
[
@ -78,6 +80,8 @@ describe('WorkItemAssignees component', () => {
assignees,
workItemId,
allowsMultipleAssignees,
workItemType: TASK_TYPE_NAME,
canUpdate,
},
attachTo: document.body,
apolloProvider,
@ -125,6 +129,18 @@ describe('WorkItemAssignees component', () => {
expect(findTokenSelector().props('selectedTokens')).toEqual([mockAssignees[0]]);
});
it('passes `false` to `viewOnly` token selector prop if user can update assignees', () => {
createComponent();
expect(findTokenSelector().props('viewOnly')).toBe(false);
});
it('passes `true` to `viewOnly` token selector prop if user can not update assignees', () => {
createComponent({ canUpdate: false });
expect(findTokenSelector().props('viewOnly')).toBe(true);
});
describe('when searching for users', () => {
beforeEach(() => {
createComponent();
@ -357,4 +373,36 @@ describe('WorkItemAssignees component', () => {
expect(findTokenSelector().props('containerClass')).toBe('gl-shadow-none!');
});
});
describe('tracking', () => {
let trackingSpy;
beforeEach(() => {
createComponent();
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
afterEach(() => {
trackingSpy = null;
});
it('does not track updating assignees until token selector blur event', async () => {
findTokenSelector().vm.$emit('input', [mockAssignees[0]]);
await waitForPromises();
expect(trackingSpy).not.toHaveBeenCalled();
});
it('tracks editing the assignees on token selector blur', async () => {
findTokenSelector().vm.$emit('input', [mockAssignees[0]]);
findTokenSelector().vm.$emit('blur', new FocusEvent({ relatedTarget: null }));
await waitForPromises();
expect(trackingSpy).toHaveBeenCalledWith(TRACKING_CATEGORY_SHOW, 'updated_assignees', {
category: TRACKING_CATEGORY_SHOW,
label: 'item_assignees',
property: 'type_Task',
});
});
});
});

View File

@ -1,39 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ActiveRecord::ConnectionAdapters::PostgreSQLAdapter do # rubocop:disable RSpec/FilePath
before do
allow(PG).to receive(:connect)
end
let(:conn_params) { PG::Connection.conndefaults_hash }
context 'when warn_on_new_connection is enabled' do
before do
described_class.warn_on_new_connection = true
end
it 'warns on new connection' do
expect(ActiveSupport::Deprecation)
.to receive(:warn).with(/Database connection should not be called during initializers/, anything)
expect(PG).to receive(:connect).with(conn_params)
described_class.new_client(conn_params)
end
end
context 'when warn_on_new_connection is disabled' do
before do
described_class.warn_on_new_connection = false
end
it 'does not warn on new connection' do
expect(ActiveSupport::Deprecation).not_to receive(:warn)
expect(PG).to receive(:connect).with(conn_params)
described_class.new_client(conn_params)
end
end
end

View File

@ -0,0 +1,63 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe InitializerConnections do
describe '.with_disabled_database_connections', :reestablished_active_record_base do
def block_with_database_call
described_class.with_disabled_database_connections do
Project.first
end
end
def block_with_error
described_class.with_disabled_database_connections do
raise "oops, an error"
end
end
it 'prevents any database connection within the block' do
expect { block_with_database_call }.to raise_error(/Database connection should not be called during initializer/)
end
it 'does not prevent database connection if SKIP_RAISE_ON_INITIALIZE_CONNECTIONS is set' do
stub_env('SKIP_RAISE_ON_INITIALIZE_CONNECTIONS', '1')
expect { block_with_database_call }.not_to raise_error
end
it 'prevents any database connection if SKIP_RAISE_ON_INITIALIZE_CONNECTIONS is false' do
stub_env('SKIP_RAISE_ON_INITIALIZE_CONNECTIONS', 'false')
expect { block_with_database_call }.to raise_error(/Database connection should not be called during initializer/)
end
it 'restores original connection handler' do
# rubocop:disable Database/MultipleDatabases
original_handler = ActiveRecord::Base.connection_handler
expect { block_with_database_call }.to raise_error(/Database connection should not be called during initializer/)
expect(ActiveRecord::Base.connection_handler).to eq(original_handler)
# rubocop:enabled Database/MultipleDatabases
end
it 'restores original connection handler even there is an error' do
# rubocop:disable Database/MultipleDatabases
original_handler = ActiveRecord::Base.connection_handler
expect { block_with_error }.to raise_error(/an error/)
expect(ActiveRecord::Base.connection_handler).to eq(original_handler)
# rubocop:enabled Database/MultipleDatabases
end
it 'raises if any new connection_pools are established in the block' do
expect do
described_class.with_disabled_database_connections do
ApplicationRecord.connects_to database: { writing: :main, reading: :main }
end
end.to raise_error(/Unxpected connection_pools/)
end
end
end

View File

@ -3953,7 +3953,21 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline status is running' do
let(:pipeline) { create(:ci_pipeline, :running) }
it { is_expected.to be_falsey }
context 'with mr_show_reports_immediately flag enabled' do
before do
stub_feature_flags(mr_show_reports_immediately: project)
end
it { expect(subject).to be_truthy }
end
context 'with mr_show_reports_immediately flag disabled' do
before do
stub_feature_flags(mr_show_reports_immediately: false)
end
it { expect(subject).to be_falsey }
end
end
context 'when pipeline status is success' do
@ -4027,7 +4041,21 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline status is running' do
let(:pipeline) { create(:ci_pipeline, :running) }
it { expect(subject).to be_falsey }
context 'with mr_show_reports_immediately flag enabled' do
before do
stub_feature_flags(mr_show_reports_immediately: project)
end
it { expect(subject).to be_truthy }
end
context 'with mr_show_reports_immediately flag disabled' do
before do
stub_feature_flags(mr_show_reports_immediately: false)
end
it { expect(subject).to be_falsey }
end
end
context 'when pipeline status is success' do

View File

@ -1884,6 +1884,14 @@ RSpec.describe Namespace do
end
end
describe '#emails_enabled?' do
it "is the opposite of emails_disabled" do
group = create(:group, emails_disabled: false)
expect(group.emails_enabled?).to be_truthy
end
end
describe '#pages_virtual_domain' do
let(:project) { create(:project, namespace: namespace) }
let(:virtual_domain) { namespace.pages_virtual_domain }

View File

@ -3595,6 +3595,14 @@ RSpec.describe Project, factory_default: :keep do
end
end
describe '#emails_enabled?' do
let(:project) { build(:project, emails_disabled: false) }
it "is the opposite of emails_disabled" do
expect(project.emails_enabled?).to be_truthy
end
end
describe '#lfs_enabled?' do
let(:namespace) { create(:namespace) }
let(:project) { build(:project, namespace: namespace) }

View File

@ -136,6 +136,20 @@ RSpec.describe 'Create a work item' do
end
end
end
context 'when unsupported widget input is sent' do
let(:input) do
{
'title' => 'new title',
'description' => 'new description',
'workItemTypeId' => WorkItems::Type.default_by_type(:test_case).to_global_id.to_s,
'hierarchyWidget' => {}
}
end
it_behaves_like 'a mutation that returns top-level errors',
errors: ['Following widget keys are not supported by Test Case type: [:hierarchy_widget]']
end
end
context 'when the work_items feature flag is disabled' do

View File

@ -71,6 +71,20 @@ RSpec.describe 'Update a work item' do
end
end
context 'when unsupported widget input is sent' do
let_it_be(:test_case) { create(:work_item_type, :default, :test_case, name: 'some_test_case_name') }
let_it_be(:work_item) { create(:work_item, work_item_type: test_case, project: project) }
let(:input) do
{
'hierarchyWidget' => {}
}
end
it_behaves_like 'a mutation that returns top-level errors',
errors: ["Following widget keys are not supported by some_test_case_name type: [:hierarchy_widget]"]
end
it_behaves_like 'has spam protection' do
let(:mutation_class) { ::Mutations::WorkItems::Update }
end
@ -295,6 +309,19 @@ RSpec.describe 'Update a work item' do
end
end
context 'when there is a mix of existing and non existing work items' do
let(:children_ids) { [valid_child1.to_global_id.to_s, "gid://gitlab/WorkItem/#{non_existing_record_id}"] }
it 'returns a top level error and does not add valid work item' do
expect do
post_graphql_mutation(mutation, current_user: current_user)
work_item.reload
end.not_to change(work_item.work_item_children, :count)
expect(graphql_errors.first['message']).to include('No object found for `childrenIds')
end
end
context 'when child work item type is valid' do
let(:children_ids) { [valid_child1.to_global_id.to_s, valid_child2.to_global_id.to_s] }

View File

@ -49,19 +49,19 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
end
context 'when work item not found' do
let(:params) { { issuable_references: [invalid_task.id] } }
let(:params) { { issuable_references: [invalid_task] } }
it_behaves_like 'returns not found error'
end
context 'when user has no permission to link work items' do
let(:params) { { issuable_references: [guest_task.id] } }
let(:params) { { issuable_references: [guest_task] } }
it_behaves_like 'returns not found error'
end
context 'child and parent are the same work item' do
let(:params) { { issuable_references: [work_item.id] } }
let(:params) { { issuable_references: [work_item] } }
it 'no relationship is created' do
expect { subject }.not_to change(parent_link_class, :count)
@ -69,7 +69,7 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
end
context 'when there are tasks to relate' do
let(:params) { { issuable_references: [task1.id, task2.id] } }
let(:params) { { issuable_references: [task1, task2] } }
it 'creates relationships', :aggregate_failures do
expect { subject }.to change(parent_link_class, :count).by(2)
@ -85,7 +85,7 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
end
context 'when task is already assigned' do
let(:params) { { issuable_references: [task.id, task2.id] } }
let(:params) { { issuable_references: [task, task2] } }
it 'creates links only for non related tasks' do
expect { subject }.to change(parent_link_class, :count).by(1)
@ -97,7 +97,7 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
context 'when there are invalid children' do
let_it_be(:issue) { create(:work_item, project: project) }
let(:params) { { issuable_references: [task1.id, issue.id, other_project_task.id] } }
let(:params) { { issuable_references: [task1, issue, other_project_task] } }
it 'creates links only for valid children' do
expect { subject }.to change { parent_link_class.count }.by(1)
@ -124,7 +124,7 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
end
context 'when max depth is reached' do
let(:params) { { issuable_references: [task2.id] } }
let(:params) { { issuable_references: [task2] } }
before do
stub_const("#{parent_link_class}::MAX_CHILDREN", 1)
@ -138,17 +138,11 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
end
context 'when params include invalid ids' do
let(:params) { { issuable_references: [task1.id, invalid_task.id] } }
let(:params) { { issuable_references: [task1, invalid_task] } }
it 'creates links only for valid IDs' do
expect { subject }.to change(parent_link_class, :count).by(1)
end
it 'returns error for invalid ID' do
message = "Task with ID: #{invalid_task.id} could not be found."
expect(subject).to eq(service_error(message, http_status: 422))
end
end
context 'when user is a guest' do

View File

@ -148,7 +148,7 @@ RSpec.describe WorkItems::UpdateService do
let(:opts) { { title: 'changed' } }
let_it_be(:child_work_item) { create(:work_item, :task, project: project) }
let(:widget_params) { { hierarchy_widget: { children_ids: [child_work_item.id] } } }
let(:widget_params) { { hierarchy_widget: { children: [child_work_item] } } }
it 'updates the children of the work item' do
expect do

View File

@ -21,8 +21,8 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
describe '#update' do
subject { described_class.new(widget: widget, current_user: user).before_update_in_transaction(params: params) }
context 'when parent and children_ids params are present' do
let(:params) { { parent: parent_work_item, children_ids: [child_work_item.id] } }
context 'when parent and children params are present' do
let(:params) { { parent: parent_work_item, children: [child_work_item] } }
it_behaves_like 'raises a WidgetError' do
let(:message) { 'A Work Item can be a parent or a child, but not both.' }
@ -35,7 +35,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
let_it_be(:child_work_item4) { create(:work_item, :task, project: project) }
context 'when work_items_hierarchy feature flag is disabled' do
let(:params) { { children_ids: [child_work_item4.id] }}
let(:params) { { children: [child_work_item4] }}
before do
stub_feature_flags(work_items_hierarchy: false)
@ -47,7 +47,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
end
context 'when user has insufficient permissions to link work items' do
let(:params) { { children_ids: [child_work_item4.id] }}
let(:params) { { children: [child_work_item4] }}
it_behaves_like 'raises a WidgetError' do
let(:message) { not_found_error }
@ -60,7 +60,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
end
context 'with valid params' do
let(:params) { { children_ids: [child_work_item2.id, child_work_item3.id] }}
let(:params) { { children: [child_work_item2, child_work_item3] }}
it 'correctly sets work item parent' do
subject
@ -71,7 +71,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
end
context 'when child is already assigned' do
let(:params) { { children_ids: [child_work_item.id] }}
let(:params) { { children: [child_work_item] }}
it_behaves_like 'raises a WidgetError' do
let(:message) { 'Task(s) already assigned' }
@ -81,7 +81,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
context 'when child type is invalid' do
let_it_be(:child_issue) { create(:work_item, project: project) }
let(:params) { { children_ids: [child_issue.id] }}
let(:params) { { children: [child_issue] }}
it_behaves_like 'raises a WidgetError' do
let(:message) do