Add latest changes from gitlab-org/gitlab@master

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1064,8 +1064,12 @@ module Ci
end
def has_reports?(reports_scope)
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?
pipeline_artifacts&.report_exists?(:code_coverage)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,7 +4,8 @@ require 'sidekiq/web'
require 'sidekiq/cron/web'
require 'product_analytics/collector_app'
Rails.application.routes.draw do
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
@ -334,6 +335,7 @@ Rails.application.routes.draw do
root to: "root#index"
get '*unmatched_route', to: 'application#route_not_found', format: false
end
end
Gitlab::Routing.add_helpers(TimeboxesRoutingHelper)
Gitlab::Routing.add_helpers(TimeboxesRoutingHelper)
end

View File

@ -22,14 +22,14 @@ 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`. |
| `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`. |
| `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:
@ -63,14 +63,14 @@ 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`. |
| `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`. |
| `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:
@ -100,8 +100,8 @@ API response has a different meaning depending on the provided `metric` query
parameter:
| `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. |
| `change_failure_rate` | The number of incidents divided by the number of deployments during the time period. Available only for production environment. |

View File

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

View File

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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