Add latest changes from gitlab-org/gitlab@master
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -91,6 +91,17 @@ class SearchService
|
|||
end
|
||||
end
|
||||
|
||||
def level
|
||||
@level ||=
|
||||
if project
|
||||
'project'
|
||||
elsif group
|
||||
'group'
|
||||
else
|
||||
'global'
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def page
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.:
|
||||
#
|
||||
|
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
||||
|
|
592
config/routes.rb
|
@ -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)
|
||||
|
|
|
@ -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. |
|
||||
|
|
|
@ -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).
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Before Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 11 KiB |
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
Before Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 26 KiB |
|
@ -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
|
||||
|
||||
|
|
|
@ -1284,3 +1284,5 @@ module API
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
API::Users.prepend_mod
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -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 ""
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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] }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|