Commit 54e03a55 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 1bcf6be2 50a24009
......@@ -35,5 +35,4 @@
@import './pages/sherlock';
@import './pages/storage_quota';
@import './pages/tree';
@import './pages/trials';
@import './pages/users';
......@@ -339,3 +339,19 @@
display: inline;
}
}
.gl-select2-html5-required-fix {
.select2-container {
+ .select2 {
@include gl-opacity-0;
@include gl-border-0;
@include gl-bg-none;
@include gl-bg-transparent;
display: block !important;
width: 1px;
height: 1px;
z-index: -1;
margin: -3px auto 0;
}
}
}
/*
* A CSS cross-browser fix for Select2 failire to display HTML5 required warnings
* MR link https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22716
*/
.gl-select2-html5-required-fix div.select2-container+select.select2 {
@include gl-opacity-0;
@include gl-border-0;
@include gl-bg-none;
@include gl-bg-transparent;
display: block !important;
width: 1px;
height: 1px;
z-index: -1;
margin: -3px auto 0;
}
......@@ -5,8 +5,11 @@ module Mutations
module Issues
class IssueMoveList < Mutations::Issues::Base
graphql_name 'IssueMoveList'
BoardGID = ::Types::GlobalIDType[::Board]
ListID = ::GraphQL::ID_TYPE
IssueID = ::GraphQL::ID_TYPE
argument :board_id, GraphQL::ID_TYPE,
argument :board_id, BoardGID,
required: true,
loads: Types::BoardType,
description: 'Global ID of the board that the issue is in.'
......@@ -19,19 +22,19 @@ module Mutations
required: true,
description: 'IID of the issue to mutate.'
argument :from_list_id, GraphQL::ID_TYPE,
argument :from_list_id, ListID,
required: false,
description: 'ID of the board list that the issue will be moved from.'
argument :to_list_id, GraphQL::ID_TYPE,
argument :to_list_id, ListID,
required: false,
description: 'ID of the board list that the issue will be moved to.'
argument :move_before_id, GraphQL::ID_TYPE,
argument :move_before_id, IssueID,
required: false,
description: 'ID of issue that should be placed before the current issue.'
argument :move_after_id, GraphQL::ID_TYPE,
argument :move_after_id, IssueID,
required: false,
description: 'ID of issue that should be placed after the current issue.'
......
......@@ -53,8 +53,9 @@ class ApplicationSetting < ApplicationRecord
serialize :domain_allowlist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :domain_denylist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :repository_storages # rubocop:disable Cop/ActiveRecordSerialize
serialize :asset_proxy_allowlist, Array # rubocop:disable Cop/ActiveRecordSerialize
# See https://gitlab.com/gitlab-org/gitlab/-/issues/300916
serialize :asset_proxy_allowlist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :asset_proxy_whitelist, Array # rubocop:disable Cop/ActiveRecordSerialize
cache_markdown_field :sign_in_text
......
......@@ -280,13 +280,18 @@ module ApplicationSettingImplementation
self.notes_create_limit_allowlist = strings_to_array(values).map(&:downcase)
end
def asset_proxy_allowlist=(values)
def asset_proxy_whitelist=(values)
values = strings_to_array(values) if values.is_a?(String)
# make sure we always allow the running host
values << Gitlab.config.gitlab.host unless values.include?(Gitlab.config.gitlab.host)
self[:asset_proxy_allowlist] = values
self[:asset_proxy_whitelist] = values
end
alias_method :asset_proxy_allowlist=, :asset_proxy_whitelist=
def asset_proxy_allowlist
read_attribute(:asset_proxy_whitelist)
end
def repository_storages
......
......@@ -6,7 +6,7 @@ module ApplicationSettings
attr_reader :params, :application_setting
MARKDOWN_CACHE_INVALIDATING_PARAMS = %w(asset_proxy_enabled asset_proxy_url asset_proxy_secret_key asset_proxy_allowlist).freeze
MARKDOWN_CACHE_INVALIDATING_PARAMS = %w(asset_proxy_enabled asset_proxy_url asset_proxy_secret_key asset_proxy_whitelist).freeze
def execute
result = update_settings
......
......@@ -31,6 +31,7 @@ module MergeRequests
old_mentioned_users = old_associations.fetch(:mentioned_users, [])
old_assignees = old_associations.fetch(:assignees, [])
old_reviewers = old_associations.fetch(:reviewers, [])
old_timelogs = old_associations.fetch(:timelogs, [])
changed_fields = merge_request.previous_changes.keys
resolve_todos(merge_request, old_labels, old_assignees, old_reviewers)
......@@ -48,6 +49,7 @@ module MergeRequests
track_title_and_desc_edits(changed_fields)
track_discussion_lock_toggle(merge_request, changed_fields)
track_time_estimate_and_spend_edits(merge_request, old_timelogs, changed_fields)
notify_if_labels_added(merge_request, old_labels)
notify_if_mentions_added(merge_request, old_mentioned_users)
......@@ -106,6 +108,11 @@ module MergeRequests
end
end
def track_time_estimate_and_spend_edits(merge_request, old_timelogs, changed_fields)
merge_request_activity_counter.track_time_estimate_changed_action(user: current_user) if changed_fields.include?('time_estimate')
merge_request_activity_counter.track_time_spent_changed_action(user: current_user) if old_timelogs != merge_request.timelogs
end
def notify_if_labels_added(merge_request, old_labels)
added_labels = merge_request.labels - old_labels
......
---
title: Add tracking to merge request time estimate/spent changes
merge_request: 55046
author:
type: other
---
title: Rename asset_proxy_allowlist column
merge_request: 55419
author:
type: fixed
---
name: usage_data_i_code_review_user_time_estimate_changed
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046
rollout_issue_url:
milestone: '13.10'
type: development
group: group::code review
default_enabled: true
---
name: usage_data_i_code_review_user_time_spent_changed
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046
rollout_issue_url:
milestone: '13.10'
type: development
group: group::code review
default_enabled: true
---
key_path: redis_hll_counters.code_review.i_code_review_user_time_estimate_changed_monthly
description: Count of unique users per month who changed time estimate of a MR
product_section: dev
product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
status: implemented
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046
time_frame: 28d
data_source: redis_hll
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
---
key_path: redis_hll_counters.code_review.i_code_review_user_time_spent_changed_monthly
description: Count of unique users per month who changed time spent on a MR
product_section: dev
product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
status: implemented
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046
time_frame: 28d
data_source: redis_hll
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
---
key_path: redis_hll_counters.code_review.i_code_review_user_time_estimate_changed_weekly
description: Count of unique users per week who changed time estimate of a MR
product_section: dev
product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
status: implemented
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046
time_frame: 7d
data_source: redis_hll
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
---
key_path: redis_hll_counters.code_review.i_code_review_user_time_spent_changed_weekly
description: Count of unique users per week who changed time spent on a MR
product_section: dev
product_stage: create
product_group: group::code review
product_category: code_review
value_type: number
status: implemented
milestone: "13.10"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046
time_frame: 7d
data_source: redis_hll
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
# frozen_string_literal: true
class RenameAssetProxyAllowlistOnApplicationSettings < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers::V2
DOWNTIME = false
disable_ddl_transaction!
def up
rename_column_concurrently :application_settings,
:asset_proxy_allowlist,
:asset_proxy_whitelist
end
def down
undo_rename_column_concurrently :application_settings,
:asset_proxy_allowlist,
:asset_proxy_whitelist
end
end
# frozen_string_literal: true
class CleanUpAssetProxyAllowlistRenameOnApplicationSettings < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers::V2
DOWNTIME = false
disable_ddl_transaction!
def up
cleanup_concurrent_column_rename :application_settings,
:asset_proxy_allowlist,
:asset_proxy_whitelist
end
def down
undo_cleanup_concurrent_column_rename :application_settings,
:asset_proxy_allowlist,
:asset_proxy_whitelist
end
end
21ae7ea7cbf1d34c7b9dc300a641eaf975ed1e33f5bc519494cd37c4a661bec8
\ No newline at end of file
28b90c9b7c2e4f2e2b12088f5aee85c16dfb567f89ed6a8e771f2c5d91c818d9
\ No newline at end of file
......@@ -9394,12 +9394,12 @@ CREATE TABLE application_settings (
invisible_captcha_enabled boolean DEFAULT false NOT NULL,
enforce_ssh_key_expiration boolean DEFAULT false NOT NULL,
git_two_factor_session_expiry integer DEFAULT 15 NOT NULL,
asset_proxy_allowlist text,
keep_latest_artifact boolean DEFAULT true NOT NULL,
notes_create_limit integer DEFAULT 300 NOT NULL,
notes_create_limit_allowlist text[] DEFAULT '{}'::text[] NOT NULL,
kroki_formats jsonb DEFAULT '{}'::jsonb NOT NULL,
in_product_marketing_emails_enabled boolean DEFAULT true NOT NULL,
asset_proxy_whitelist text,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_registry_exp_policies_worker_capacity_positive CHECK ((container_registry_expiration_policies_worker_capacity >= 0)),
CONSTRAINT check_17d9558205 CHECK ((char_length(kroki_url) <= 1024)),
......@@ -13730,6 +13730,86 @@ Count of unique users per week|month with diffs viewed file by file
| `tier` | |
| `skip_validation` | true |
## `redis_hll_counters.code_review.i_code_review_user_time_estimate_changed_monthly`
Count of unique users per month who changed time estimate of a MR
| field | value |
| --- | --- |
| `key_path` | **`redis_hll_counters.code_review.i_code_review_user_time_estimate_changed_monthly`** |
| `product_section` | dev |
| `product_stage` | create |
| `product_group` | `group::code review` |
| `product_category` | `code_review` |
| `value_type` | number |
| `status` | implemented |
| `milestone` | 13.10 |
| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046) |
| `time_frame` | 28d |
| `data_source` | Redis_hll |
| `distribution` | ce, ee |
| `tier` | free, premium, ultimate |
## `redis_hll_counters.code_review.i_code_review_user_time_estimate_changed_weekly`
Count of unique users per week who changed time estimate of a MR
| field | value |
| --- | --- |
| `key_path` | **`redis_hll_counters.code_review.i_code_review_user_time_estimate_changed_weekly`** |
| `product_section` | dev |
| `product_stage` | create |
| `product_group` | `group::code review` |
| `product_category` | `code_review` |
| `value_type` | number |
| `status` | implemented |
| `milestone` | 13.10 |
| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046) |
| `time_frame` | 7d |
| `data_source` | Redis_hll |
| `distribution` | ce, ee |
| `tier` | free, premium, ultimate |
## `redis_hll_counters.code_review.i_code_review_user_time_spent_changed_monthly`
Count of unique users per month who changed time spent on a MR
| field | value |
| --- | --- |
| `key_path` | **`redis_hll_counters.code_review.i_code_review_user_time_spent_changed_monthly`** |
| `product_section` | dev |
| `product_stage` | create |
| `product_group` | `group::code review` |
| `product_category` | `code_review` |
| `value_type` | number |
| `status` | implemented |
| `milestone` | 13.10 |
| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046) |
| `time_frame` | 28d |
| `data_source` | Redis_hll |
| `distribution` | ce, ee |
| `tier` | free, premium, ultimate |
## `redis_hll_counters.code_review.i_code_review_user_time_spent_changed_weekly`
Count of unique users per week who changed time spent on a MR
| field | value |
| --- | --- |
| `key_path` | **`redis_hll_counters.code_review.i_code_review_user_time_spent_changed_weekly`** |
| `product_section` | dev |
| `product_stage` | create |
| `product_group` | `group::code review` |
| `product_category` | `code_review` |
| `value_type` | number |
| `status` | implemented |
| `milestone` | 13.10 |
| `introduced_by_url` | [Introduced by](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55046) |
| `time_frame` | 7d |
| `data_source` | Redis_hll |
| `distribution` | ce, ee |
| `tier` | free, premium, ultimate |
## `redis_hll_counters.code_review.i_code_review_user_toggled_task_item_status_monthly`
Missing description
......
<script>
import { GlToken, GlAvatar, GlPopover } from '@gitlab/ui';
import { GlAvatar, GlPopover } from '@gitlab/ui';
import { formatDate } from '~/lib/utils/datetime_utility';
import { truncate } from '~/lib/utils/text_utility';
import { __, sprintf } from '~/locale';
......@@ -10,11 +10,13 @@ export const SHIFT_WIDTHS = {
xs: 40,
};
const ROTATION_CENTER_CLASS = 'gl-display-flex gl-justify-content-center gl-align-items-center';
export default {
ROTATION_CENTER_CLASS,
components: {
GlAvatar,
GlPopover,
GlToken,
},
props: {
assignee: {
......@@ -72,19 +74,19 @@ export default {
<template>
<div class="gl-absolute gl-h-7 gl-mt-3" :style="rotationAssigneeStyle">
<gl-token
<div
:id="rotationAssigneeUniqueID"
class="gl-w-full gl-h-6 gl-align-items-center"
:class="chevronClass"
:view-only="true"
class="gl-h-6"
:class="[chevronClass, $options.ROTATION_CENTER_CLASS]"
data-testid="rotation-assignee"
>
<div class="gl-display-flex gl-text-white gl-font-weight-normal">
<div class="gl-text-white" :class="$options.ROTATION_CENTER_CLASS">
<gl-avatar :src="assignee.user.avatarUrl" :size="16" />
<span v-if="!rotationMobileView" class="gl-ml-2" data-testid="rotation-assignee-name">{{
assigneeName
}}</span>
</div>
</gl-token>
</div>
<gl-popover
:target="rotationAssigneeUniqueID"
:title="assignee.user.username"
......
import { GlToken, GlAvatar, GlPopover } from '@gitlab/ui';
import { GlAvatar, GlPopover } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import RotationAssignee, {
SHIFT_WIDTHS,
......@@ -13,7 +13,7 @@ describe('RotationAssignee', () => {
const shiftWidth = 100;
const assignee = mockRotations[0].shifts.nodes[0];
const findToken = () => wrapper.findComponent(GlToken);
const findToken = () => wrapper.findByTestId('rotation-assignee');
const findAvatar = () => wrapper.findComponent(GlAvatar);
const findPopOver = () => wrapper.findComponent(GlPopover);
const findStartsAt = () => wrapper.findByTestId('rotation-assignee-starts-at');
......
......@@ -80,15 +80,13 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
class="gl-absolute gl-h-7 gl-mt-3"
style="left: 0px; width: -2px;"
>
<span
class="gl-w-full gl-h-6 gl-align-items-center gl-token gl-token-default-variant gl-bg-data-viz-blue-500"
<div
class="gl-h-6 gl-bg-data-viz-blue-500 gl-display-flex gl-justify-content-center gl-align-items-center"
data-testid="rotation-assignee"
id="1-12"
>
<span
class="gl-token-content"
>
<div
class="gl-display-flex gl-text-white gl-font-weight-normal"
class="gl-text-white gl-display-flex gl-justify-content-center gl-align-items-center"
>
<img
alt="avatar"
......@@ -98,10 +96,7 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
<!---->
</div>
<!---->
</span>
</span>
</div>
<div
class="gl-popover"
......@@ -125,15 +120,13 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
class="gl-absolute gl-h-7 gl-mt-3"
style="left: 0px; width: -2px;"
>
<span
class="gl-w-full gl-h-6 gl-align-items-center gl-token gl-token-default-variant gl-bg-data-viz-orange-500"
id="2-17"
>
<span
class="gl-token-content"
<div
class="gl-h-6 gl-bg-data-viz-orange-500 gl-display-flex gl-justify-content-center gl-align-items-center"
data-testid="rotation-assignee"
id="2-16"
>
<div
class="gl-display-flex gl-text-white gl-font-weight-normal"
class="gl-text-white gl-display-flex gl-justify-content-center gl-align-items-center"
>
<img
alt="avatar"
......@@ -143,10 +136,7 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
<!---->
</div>
<!---->
</span>
</span>
</div>
<div
class="gl-popover"
......
......@@ -44,7 +44,9 @@
'i_code_review_user_toggled_task_item_status',
'i_code_review_user_create_mr_from_issue',
'i_code_review_user_mr_discussion_locked',
'i_code_review_user_mr_discussion_unlocked'
'i_code_review_user_mr_discussion_unlocked',
'i_code_review_user_time_estimate_changed',
'i_code_review_user_time_spent_changed'
]
- name: code_review_category_monthly_active_users
operator: OR
......@@ -82,7 +84,9 @@
'i_code_review_user_toggled_task_item_status',
'i_code_review_user_create_mr_from_issue',
'i_code_review_user_mr_discussion_locked',
'i_code_review_user_mr_discussion_unlocked'
'i_code_review_user_mr_discussion_unlocked',
'i_code_review_user_time_estimate_changed',
'i_code_review_user_time_spent_changed'
]
- name: code_review_extension_category_monthly_active_users
operator: OR
......
......@@ -174,3 +174,13 @@
category: code_review
aggregation: weekly
feature_flag: usage_data_i_code_review_user_mr_discussion_unlocked
- name: i_code_review_user_time_estimate_changed
redis_slot: code_review
category: code_review
aggregation: weekly
feature_flag: usage_data_i_code_review_user_time_estimate_changed
- name: i_code_review_user_time_spent_changed
redis_slot: code_review
category: code_review
aggregation: weekly
feature_flag: usage_data_i_code_review_user_time_spent_changed
......@@ -37,6 +37,8 @@ module Gitlab
MR_CREATE_FROM_ISSUE_ACTION = 'i_code_review_user_create_mr_from_issue'
MR_DISCUSSION_LOCKED_ACTION = 'i_code_review_user_mr_discussion_locked'
MR_DISCUSSION_UNLOCKED_ACTION = 'i_code_review_user_mr_discussion_unlocked'
MR_TIME_ESTIMATE_CHANGED_ACTION = 'i_code_review_user_time_estimate_changed'
MR_TIME_SPENT_CHANGED_ACTION = 'i_code_review_user_time_spent_changed'
class << self
def track_mr_diffs_action(merge_request:)
......@@ -163,6 +165,14 @@ module Gitlab
track_unique_action_by_user(MR_DISCUSSION_UNLOCKED_ACTION, user)
end
def track_time_estimate_changed_action(user:)
track_unique_action_by_user(MR_TIME_ESTIMATE_CHANGED_ACTION, user)
end
def track_time_spent_changed_action(user:)
track_unique_action_by_user(MR_TIME_SPENT_CHANGED_ACTION, user)
end
private
def track_unique_action_by_merge_request(action, merge_request)
......
......@@ -300,4 +300,20 @@ RSpec.describe Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter, :cl
let(:action) { described_class::MR_DISCUSSION_UNLOCKED_ACTION }
end
end
describe '.track_time_estimate_changed_action' do
subject { described_class.track_time_estimate_changed_action(user: user) }
it_behaves_like 'a tracked merge request unique event' do
let(:action) { described_class::MR_TIME_ESTIMATE_CHANGED_ACTION }
end
end
describe '.track_time_spent_changed_action' do
subject { described_class.track_time_spent_changed_action(user: user) }
it_behaves_like 'a tracked merge request unique event' do
let(:action) { described_class::MR_TIME_SPENT_CHANGED_ACTION }
end
end
end
......@@ -650,6 +650,32 @@ RSpec.describe ApplicationSetting do
end
end
describe '#asset_proxy_whitelist' do
context 'when given an Array' do
it 'sets the domains and adds current running host' do
setting.asset_proxy_whitelist = ['example.com', 'assets.example.com']
expect(setting.asset_proxy_whitelist).to eq(['example.com', 'assets.example.com', 'localhost'])
end
end
context 'when given a String' do
it 'sets multiple domains with spaces' do
setting.asset_proxy_whitelist = 'example.com *.example.com'
expect(setting.asset_proxy_whitelist).to eq(['example.com', '*.example.com', 'localhost'])
end
it 'sets multiple domains with newlines and a space' do
setting.asset_proxy_whitelist = "example.com\n *.example.com"
expect(setting.asset_proxy_whitelist).to eq(['example.com', '*.example.com', 'localhost'])
end
it 'sets multiple domains with commas' do
setting.asset_proxy_whitelist = "example.com, *.example.com"
expect(setting.asset_proxy_whitelist).to eq(['example.com', '*.example.com', 'localhost'])
end
end
end
describe '#asset_proxy_allowlist' do
context 'when given an Array' do
it 'sets the domains and adds current running host' do
......
......@@ -123,6 +123,7 @@ RSpec.describe ApplicationSettings::UpdateService do
it_behaves_like 'invalidates markdown cache', { asset_proxy_url: 'http://test.com' }
it_behaves_like 'invalidates markdown cache', { asset_proxy_secret_key: 'another secret' }
it_behaves_like 'invalidates markdown cache', { asset_proxy_allowlist: ['domain.com'] }
it_behaves_like 'invalidates markdown cache', { asset_proxy_whitelist: ['domain.com'] }
context 'when also setting the local_markdown_version' do
let(:params) { { asset_proxy_enabled: true, local_markdown_version: 12 } }
......
......@@ -169,6 +169,23 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
end
end
it 'tracks time estimate and spend time changes' do
expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
.to receive(:track_time_estimate_changed_action).once.with(user: user)
expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
.to receive(:track_time_spent_changed_action).once.with(user: user)
opts[:time_estimate] = 86400
opts[:spend_time] = {
duration: 3600,
user_id: user.id,
spent_at: Date.parse('2021-02-24')
}
MergeRequests::UpdateService.new(project, user, opts).execute(merge_request)
end
end
context 'updating milestone' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment