Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-08-17 09:10:08 +00:00
parent c64b892786
commit 325318e2dd
51 changed files with 538 additions and 312 deletions

View File

@ -324,6 +324,12 @@ export default {
</div>
<div class="gl-pl-2" data-testid="service">{{ alert.service }}</div>
</div>
<div v-if="alert.runbook" class="gl-my-5 gl-display-flex">
<div class="bold gl-w-13 gl-text-right gl-pr-3">
{{ s__('AlertManagement|Runbook') }}:
</div>
<div class="gl-pl-2" data-testid="runbook">{{ alert.runbook }}</div>
</div>
<template>
<div v-if="alert.notes.nodes" class="issuable-discussion py-5">
<ul class="notes main-notes-list timeline">

View File

@ -11,6 +11,7 @@ fragment AlertDetailItem on AlertManagementAlert {
updatedAt
endedAt
details
runbook
todos {
nodes {
id

View File

@ -93,10 +93,6 @@ const createPipelineHeaderApp = mediator => {
};
const createTestDetails = () => {
if (!window.gon?.features?.junitPipelineView) {
return;
}
const el = document.querySelector('#js-pipeline-tests-detail');
const { summaryEndpoint, suiteEndpoint } = el?.dataset || {};

View File

@ -56,7 +56,7 @@ export default {
return `${this.pipelinePath}/test_report`;
},
showViewFullReport() {
return Boolean(this.glFeatures.junitPipelineView) && this.pipelinePath.length;
return this.pipelinePath.length;
},
},
created() {
@ -116,6 +116,7 @@ export default {
<template v-if="showViewFullReport" #actionButtons>
<gl-button
:href="testTabURL"
target="_blank"
icon="external-link"
data-testid="group-test-reports-full-link"
class="gl-mr-3"

View File

@ -43,7 +43,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action do
push_frontend_feature_flag(:vue_issuable_sidebar, @project.group)
push_frontend_feature_flag(:junit_pipeline_view, @project.group)
end
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions]

View File

@ -12,7 +12,6 @@ class Projects::PipelinesController < Projects::ApplicationController
before_action :authorize_create_pipeline!, only: [:new, :create]
before_action :authorize_update_pipeline!, only: [:retry, :cancel]
before_action do
push_frontend_feature_flag(:junit_pipeline_view, project)
push_frontend_feature_flag(:filter_pipelines_search, project, default_enabled: true)
push_frontend_feature_flag(:dag_pipeline_tab, project, default_enabled: true)
push_frontend_feature_flag(:pipelines_security_report_summary, project)
@ -177,8 +176,6 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def test_report
return unless Feature.enabled?(:junit_pipeline_view, project)
respond_to do |format|
format.html do
render 'show'

View File

@ -17,7 +17,7 @@ module HasWiki
def wiki
strong_memoize(:wiki) do
Wiki.for_container(self, self.owner)
Wiki.for_container(self, self.default_owner)
end
end

View File

@ -563,6 +563,10 @@ class Group < Namespace
all_projects.update_all(shared_runners_enabled: false)
end
def default_owner
owners.first || parent&.default_owner || owner
end
private
def update_two_factor_requirement

View File

@ -1395,6 +1395,16 @@ class Project < ApplicationRecord
group || namespace.try(:owner)
end
def default_owner
obj = owner
if obj.respond_to?(:default_owner)
obj.default_owner
else
obj
end
end
def to_ability_name
model_name.singular
end

View File

@ -35,6 +35,7 @@ class Wiki
def initialize(container, user = nil)
@container = container
@user = user
raise ArgumentError, "user must be a User, got #{user.class}" if user && !user.is_a?(User)
end
def path

View File

@ -96,12 +96,12 @@ module AlertManagement
end
def handle_assignement(old_assignees)
assign_todo
assign_todo(old_assignees)
add_assignee_system_note(old_assignees)
end
def assign_todo
todo_service.assign_alert(alert, current_user)
def assign_todo(old_assignees)
todo_service.reassigned_assignable(alert, current_user, old_assignees)
end
def add_assignee_system_note(old_assignees)

View File

@ -109,7 +109,7 @@ class EventCreateService
def wiki_event(wiki_page_meta, author, action, fingerprint)
raise IllegalActionError, action unless Event::WIKI_ACTIONS.include?(action)
Gitlab::UsageDataCounters::TrackUniqueActions.track_action(event_action: action, event_target: wiki_page_meta.class, author_id: author.id)
Gitlab::UsageDataCounters::TrackUniqueActions.track_event(event_action: action, event_target: wiki_page_meta.class, author_id: author.id)
duplicate = Event.for_wiki_meta(wiki_page_meta).for_fingerprint(fingerprint).first
return duplicate if duplicate.present?
@ -154,7 +154,7 @@ class EventCreateService
result = Event.insert_all(attribute_sets, returning: %w[id])
tuples.each do |record, status, _|
Gitlab::UsageDataCounters::TrackUniqueActions.track_action(event_action: status, event_target: record.class, author_id: current_user.id)
Gitlab::UsageDataCounters::TrackUniqueActions.track_event(event_action: status, event_target: record.class, author_id: current_user.id)
end
result
@ -172,7 +172,7 @@ class EventCreateService
new_event
end
Gitlab::UsageDataCounters::TrackUniqueActions.track_action(event_action: :pushed, event_target: Project, author_id: current_user.id)
Gitlab::UsageDataCounters::TrackUniqueActions.track_event(event_action: :pushed, event_target: Project, author_id: current_user.id)
Users::LastPushEventService.new(current_user)
.cache_last_push_event(event)

View File

@ -43,7 +43,7 @@ module Issues
if issue.assignees != old_assignees
create_assignee_note(issue, old_assignees)
notification_service.async.reassigned_issue(issue, current_user, old_assignees)
todo_service.reassigned_issuable(issue, current_user, old_assignees)
todo_service.reassigned_assignable(issue, current_user, old_assignees)
end
if issue.previous_changes.include?('confidential')

View File

@ -105,7 +105,7 @@ module MergeRequests
def handle_assignees_change(merge_request, old_assignees)
create_assignee_note(merge_request, old_assignees)
notification_service.async.reassigned_merge_request(merge_request, current_user, old_assignees)
todo_service.reassigned_issuable(merge_request, current_user, old_assignees)
todo_service.reassigned_assignable(merge_request, current_user, old_assignees)
end
def create_branch_change_note(issuable, branch_type, old_branch, new_branch)

View File

@ -32,6 +32,8 @@ module ResourceAccessTokens
attr_reader :resource_type, :resource
def feature_enabled?
return false if ::Gitlab.com?
::Feature.enabled?(:resource_access_token, resource, default_enabled: true)
end

View File

@ -49,11 +49,11 @@ class TodoService
todo_users.each(&:update_todos_count_cache)
end
# When we reassign an issuable we should:
# When we reassign an assignable object (issuable, alert) we should:
#
# * create a pending todo for new assignee if issuable is assigned
# * create a pending todo for new assignee if object is assigned
#
def reassigned_issuable(issuable, current_user, old_assignees = [])
def reassigned_assignable(issuable, current_user, old_assignees = [])
create_assignment_todo(issuable, current_user, old_assignees)
end
@ -154,14 +154,6 @@ class TodoService
resolve_todos_for_target(awardable, current_user)
end
# When assigning an alert we should:
#
# * create a pending todo for new assignee if alert is assigned
#
def assign_alert(alert, current_user)
create_assignment_todo(alert, current_user, [])
end
# When user marks a target as todo
def mark_todo(target, current_user)
attributes = attributes_for_todo(target.project, target, current_user, Todo::MARKED)

View File

@ -1,5 +1,4 @@
- return if pipeline_has_errors
- test_reports_enabled = Feature.enabled?(:junit_pipeline_view, @project)
- dag_pipeline_tab_enabled = Feature.enabled?(:dag_pipeline_tab, @project, default_enabled: true)
.tabs-holder
@ -20,11 +19,10 @@
= link_to failures_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-failures', action: 'failures', toggle: 'tab' }, class: 'failures-tab' do
= _('Failed Jobs')
%span.badge.badge-pill.js-failures-counter= @pipeline.failed_builds.count
- if test_reports_enabled
%li.js-tests-tab-link
= link_to test_report_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-tests', action: 'test_report', toggle: 'tab' }, class: 'test-tab' do
= s_('TestReports|Tests')
%span.badge.badge-pill.js-test-report-badge-counter= @pipeline.test_report_summary.total[:count]
%li.js-tests-tab-link
= link_to test_report_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-tests', action: 'test_report', toggle: 'tab' }, class: 'test-tab' do
= s_('TestReports|Tests')
%span.badge.badge-pill.js-test-report-badge-counter= @pipeline.test_report_summary.total[:count]
= render_if_exists "projects/pipelines/tabs_holder", pipeline: @pipeline, project: @project
.tab-content

View File

@ -10,8 +10,9 @@
= page_title
%p
= _('You can generate an access token scoped to this project for each application to use the GitLab API.')
%p
= _('You can also use project access tokens to authenticate against Git over HTTP.')
-# Commented out until https://gitlab.com/gitlab-org/gitlab/-/issues/219551 is fixed
-# %p
-# = _('You can also use project access tokens to authenticate against Git over HTTP.')
.col-lg-8
- if @new_project_access_token

View File

@ -0,0 +1,5 @@
---
title: JUnit test report on pipeline detail page
merge_request: 39260
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Make View full report button open link in new tab
merge_request: 39501
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Show runbook for alert in detail view
merge_request: 39477
author:
type: added

View File

@ -575,6 +575,9 @@ Gitlab.ee do
Settings.cron_jobs['elastic_cluster_reindexing_cron_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['elastic_cluster_reindexing_cron_worker']['cron'] ||= '*/10 * * * *'
Settings.cron_jobs['elastic_cluster_reindexing_cron_worker']['job_class'] ||= 'ElasticClusterReindexingCronWorker'
Settings.cron_jobs['elastic_remove_expired_namespace_subscriptions_from_index_cron_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['elastic_remove_expired_namespace_subscriptions_from_index_cron_worker']['cron'] ||= '10 3 * * *'
Settings.cron_jobs['elastic_remove_expired_namespace_subscriptions_from_index_cron_worker']['job_class'] ||= 'ElasticRemoveExpiredNamespaceSubscriptionsFromIndexCronWorker'
Settings.cron_jobs['sync_seat_link_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['sync_seat_link_worker']['cron'] ||= "#{rand(60)} 0 * * *"
Settings.cron_jobs['sync_seat_link_worker']['job_class'] = 'SyncSeatLinkWorker'

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class AddIndexOnEndDateAndNamespaceIdToGitlabSubscriptions < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :gitlab_subscriptions, [:end_date, :namespace_id]
end
def down
remove_concurrent_index :gitlab_subscriptions, [:end_date, :namespace_id]
end
end

View File

@ -0,0 +1 @@
432ef9d45c8242ab8db954ceeb6a68a75ef46181dd868a30d68fef0ed6058caf

View File

@ -19710,6 +19710,8 @@ CREATE INDEX index_geo_upload_deleted_events_on_upload_id ON public.geo_upload_d
CREATE INDEX index_gitlab_subscription_histories_on_gitlab_subscription_id ON public.gitlab_subscription_histories USING btree (gitlab_subscription_id);
CREATE INDEX index_gitlab_subscriptions_on_end_date_and_namespace_id ON public.gitlab_subscriptions USING btree (end_date, namespace_id);
CREATE INDEX index_gitlab_subscriptions_on_hosted_plan_id ON public.gitlab_subscriptions USING btree (hosted_plan_id);
CREATE UNIQUE INDEX index_gitlab_subscriptions_on_namespace_id ON public.gitlab_subscriptions USING btree (namespace_id);

View File

@ -103,10 +103,10 @@ Some feature flags can be enabled or disabled on a per project basis:
Feature.enable(:<feature flag>, Project.find(<project id>))
```
For example, to enable the [`:junit_pipeline_view`](../ci/junit_test_reports.md#enabling-the-junit-test-reports-feature-core-only) feature flag for project `1234`:
For example, to enable the [`:product_analytics`](../operations/product_analytics.md#enable-or-disable-product-analytics) feature flag for project `1234`:
```ruby
Feature.enable(:junit_pipeline_view, Project.find(1234))
Feature.enable(:product_analytics, Project.find(1234))
```
`Feature.enable` and `Feature.disable` always return `nil`, this is not an indication that the command failed:

View File

@ -1135,42 +1135,47 @@ type BoardEdge {
input BoardEpicIssueInput {
"""
Username of a user assigned to issues
Filter by assignee username
"""
assigneeUsername: [String]
"""
Username of the issues author
Filter by author username
"""
authorUsername: String
"""
Epic ID applied to issues
Filter by epic ID
"""
epicId: String
"""
Label applied to issues
Filter by label name
"""
labelName: [String]
"""
Milestone applied to issues
Filter by milestone title
"""
milestoneTitle: String
"""
Reaction emoji applied to issues
Filter by reaction emoji
"""
myReactionEmoji: String
"""
Release applied to issues
List of negated params. Warning: this argument is experimental and a subject to change in future
"""
not: NegatedBoardEpicIssueInput
"""
Filter by release tag
"""
releaseTag: String
"""
Weight applied to issues
Filter by weight
"""
weight: String
}
@ -9795,6 +9800,48 @@ type NamespaceIncreaseStorageTemporarilyPayload {
namespace: Namespace
}
input NegatedBoardEpicIssueInput {
"""
Filter by assignee username
"""
assigneeUsername: [String]
"""
Filter by author username
"""
authorUsername: String
"""
Filter by epic ID
"""
epicId: String
"""
Filter by label name
"""
labelName: [String]
"""
Filter by milestone title
"""
milestoneTitle: String
"""
Filter by reaction emoji
"""
myReactionEmoji: String
"""
Filter by release tag
"""
releaseTag: String
"""
Filter by weight
"""
weight: String
}
type Note implements ResolvableInterface {
"""
User who wrote this note

View File

@ -3049,7 +3049,7 @@
"inputFields": [
{
"name": "labelName",
"description": "Label applied to issues",
"description": "Filter by label name",
"type": {
"kind": "LIST",
"name": null,
@ -3063,7 +3063,7 @@
},
{
"name": "milestoneTitle",
"description": "Milestone applied to issues",
"description": "Filter by milestone title",
"type": {
"kind": "SCALAR",
"name": "String",
@ -3073,7 +3073,7 @@
},
{
"name": "assigneeUsername",
"description": "Username of a user assigned to issues",
"description": "Filter by assignee username",
"type": {
"kind": "LIST",
"name": null,
@ -3087,7 +3087,7 @@
},
{
"name": "authorUsername",
"description": "Username of the issues author",
"description": "Filter by author username",
"type": {
"kind": "SCALAR",
"name": "String",
@ -3097,7 +3097,7 @@
},
{
"name": "releaseTag",
"description": "Release applied to issues",
"description": "Filter by release tag",
"type": {
"kind": "SCALAR",
"name": "String",
@ -3107,7 +3107,7 @@
},
{
"name": "epicId",
"description": "Epic ID applied to issues",
"description": "Filter by epic ID",
"type": {
"kind": "SCALAR",
"name": "String",
@ -3117,7 +3117,7 @@
},
{
"name": "myReactionEmoji",
"description": "Reaction emoji applied to issues",
"description": "Filter by reaction emoji",
"type": {
"kind": "SCALAR",
"name": "String",
@ -3127,13 +3127,23 @@
},
{
"name": "weight",
"description": "Weight applied to issues",
"description": "Filter by weight",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "not",
"description": "List of negated params. Warning: this argument is experimental and a subject to change in future",
"type": {
"kind": "INPUT_OBJECT",
"name": "NegatedBoardEpicIssueInput",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
@ -29245,6 +29255,105 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "NegatedBoardEpicIssueInput",
"description": null,
"fields": null,
"inputFields": [
{
"name": "labelName",
"description": "Filter by label name",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "milestoneTitle",
"description": "Filter by milestone title",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "assigneeUsername",
"description": "Filter by assignee username",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "authorUsername",
"description": "Filter by author username",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "releaseTag",
"description": "Filter by release tag",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "epicId",
"description": "Filter by epic ID",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "myReactionEmoji",
"description": "Filter by reaction emoji",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "weight",
"description": "Filter by weight",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Note",

View File

@ -239,9 +239,8 @@ Test:
## Viewing JUnit test reports on GitLab
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24792) in GitLab 12.5.
> - It's deployed behind a feature flag, disabled by default.
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enabling-the-junit-test-reports-feature-core-only). **(CORE ONLY)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24792) in GitLab 12.5 behind a feature flag (`junit_pipeline_view`), disabled by default.
> - The feature flag was removed and the feature was [made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/216478) in GitLab 13.3.
If JUnit XML files are generated and uploaded as part of a pipeline, these reports
can be viewed inside the pipelines details page. The **Tests** tab on this page will
@ -254,22 +253,6 @@ details, including the cases that make up the suite.
You can also retrieve the reports via the [GitLab API](../api/pipelines.md#get-a-pipelines-test-report).
### Enabling the JUnit test reports feature **(CORE ONLY)**
This feature comes with the `:junit_pipeline_view` feature flag disabled by default. This
feature is disabled due to some performance issues with very large data sets.
When [the performance is improved](https://gitlab.com/groups/gitlab-org/-/epics/2854), the feature will be enabled by default.
To enable this feature, ask a GitLab administrator with [Rails console access](../administration/feature_flags.md#how-to-enable-and-disable-features-behind-flags) to run the
following command:
```ruby
Feature.enable(:junit_pipeline_view)
# Enable the feature for a specific project, GitLab 13.0 and above only.
Feature.enable(:junit_pipeline_view, Project.find(<your-project-id-here>))
```
## Viewing JUnit screenshots on GitLab
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202114) in GitLab 13.0.

View File

@ -5,20 +5,20 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
# Project access tokens (Alpha) **(CORE ONLY)**
CAUTION: **Warning:**
This is an [Alpha](https://about.gitlab.com/handbook/product/#alpha) feature, and it is subject to change at any time without
prior notice.
# Project access tokens **(CORE ONLY)**
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2587) in GitLab 13.0.
> - It's deployed behind a feature flag, disabled by default.
> - It was [deployed](https://gitlab.com/groups/gitlab-org/-/epics/2587) behind a feature flag, disabled by default.
> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/218722) in GitLab 13.3.
> - It's disabled on GitLab.com.
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-project-access-tokens).
> - It can be enabled or disabled by project.
> - It's recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can [disable it](#enable-or-disable-project-access-tokens).
Project access tokens are scoped to a project and can be used to authenticate with the [GitLab API](../../../api/README.md#personalproject-access-tokens).
You can also use project access tokens with Git to authenticate over HTTP or SSH.
<!-- Commented out until https://gitlab.com/gitlab-org/gitlab/-/issues/219551 is fixed -->
<!-- You can also use project access tokens with Git to authenticate over HTTP or SSH. -->
Project access tokens expire on the date you define, at midnight UTC.
@ -78,19 +78,30 @@ the following table.
### Enable or disable project access tokens
Project access tokens is an [Alpha](https://about.gitlab.com/handbook/product/#alpha) feature and is not recommended for production use.
It is deployed behind a feature flag that is **disabled by default**.
Project access tokens are deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
can enable it for your instance.
can disable it for your instance, globally or by project.
To enable it:
To disable it globally:
```ruby
Feature.disable(:resource_access_token)
```
To disable it for a specific project:
```ruby
Feature.disable(:resource_access_token, project)
```
To enable it globally:
```ruby
Feature.enable(:resource_access_token)
```
To disable it:
To enable it for a specific project:
```ruby
Feature.disable(:resource_access_token)
Feature.enable(:resource_access_token, project)
```

View File

@ -110,15 +110,13 @@ module API
end
desc 'Gets the test report for a given pipeline' do
detail 'This feature was introduced in GitLab 13.0. Disabled by default behind feature flag `junit_pipeline_view`'
detail 'This feature was introduced in GitLab 13.0.'
success TestReportEntity
end
params do
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
end
get ':id/pipelines/:pipeline_id/test_report' do
not_found! unless Feature.enabled?(:junit_pipeline_view, user_project)
authorize! :read_build, pipeline
present pipeline.test_reports, with: TestReportEntity, details: true

View File

@ -607,7 +607,7 @@ module Gitlab
counter = Gitlab::UsageDataCounters::TrackUniqueActions
project_count = redis_usage_data do
counter.count_unique_events(
counter.count_unique(
event_action: Gitlab::UsageDataCounters::TrackUniqueActions::PUSH_ACTION,
date_from: time_period[:created_at].first,
date_to: time_period[:created_at].last
@ -615,7 +615,7 @@ module Gitlab
end
design_count = redis_usage_data do
counter.count_unique_events(
counter.count_unique(
event_action: Gitlab::UsageDataCounters::TrackUniqueActions::DESIGN_ACTION,
date_from: time_period[:created_at].first,
date_to: time_period[:created_at].last
@ -623,7 +623,7 @@ module Gitlab
end
wiki_count = redis_usage_data do
counter.count_unique_events(
counter.count_unique(
event_action: Gitlab::UsageDataCounters::TrackUniqueActions::WIKI_ACTION,
date_from: time_period[:created_at].first,
date_to: time_period[:created_at].last

View File

@ -27,7 +27,7 @@ module Gitlab
}).freeze
class << self
def track_action(event_action:, event_target:, author_id:, time: Time.zone.now)
def track_event(event_action:, event_target:, author_id:, time: Time.zone.now)
return unless Gitlab::CurrentSettings.usage_ping_enabled
return unless Feature.enabled?(FEATURE_FLAG)
return unless valid_target?(event_target)
@ -40,7 +40,7 @@ module Gitlab
Gitlab::Redis::HLL.add(key: target_key, value: author_id, expiry: KEY_EXPIRY_LENGTH)
end
def count_unique_events(event_action:, date_from:, date_to:)
def count_unique(event_action:, date_from:, date_to:)
keys = (date_from.to_date..date_to.to_date).map { |date| key(event_action, date) }
Gitlab::Redis::HLL.count(keys: keys)

View File

@ -2180,6 +2180,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
msgid "AlertManagement|Runbook"
msgstr ""
msgid "AlertManagement|Service"
msgstr ""
@ -27831,9 +27834,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
msgid "You can also use project access tokens to authenticate against Git over HTTP."
msgstr ""
msgid "You can always edit this later"
msgstr ""

View File

@ -859,113 +859,88 @@ RSpec.describe Projects::PipelinesController do
end
end
context 'when feature is enabled' do
context 'when pipeline does not have a test report' do
it 'renders an empty test report' do
get_test_report_json
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['total_count']).to eq(0)
end
end
context 'when pipeline has a test report' do
before do
stub_feature_flags(junit_pipeline_view: project)
create(:ci_build, :test_reports, name: 'rspec', pipeline: pipeline)
end
context 'when pipeline does not have a test report' do
it 'renders an empty test report' do
get_test_report_json
it 'renders the test report' do
get_test_report_json
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['total_count']).to eq(4)
end
end
context 'when pipeline has a corrupt test report artifact' do
before do
create(:ci_build, :broken_test_reports, name: 'rspec', pipeline: pipeline)
get_test_report_json
end
it 'renders the test reports' do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['test_suites'].count).to eq(1)
end
it 'returns a suite_error on the suite with corrupted XML' do
expect(json_response['test_suites'].first['suite_error']).to eq('JUnit XML parsing failed: 1:1: FATAL: Document is empty')
end
end
context 'when junit_pipeline_screenshots_view is enabled' do
before do
stub_feature_flags(junit_pipeline_screenshots_view: project)
end
context 'when test_report contains attachment and scope is with_attachment as a URL param' do
let(:pipeline) { create(:ci_pipeline, :with_test_reports_attachment, project: project) }
it 'returns a test reports with attachment' do
get_test_report_json(scope: 'with_attachment')
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['total_count']).to eq(0)
expect(json_response["test_suites"]).to be_present
expect(json_response["test_suites"].first["test_cases"].first).to include("attachment_url")
end
end
context 'when pipeline has a test report' do
before do
create(:ci_build, name: 'rspec', pipeline: pipeline).tap do |build|
create(:ci_job_artifact, :junit, job: build)
end
end
context 'when test_report does not contain attachment and scope is with_attachment as a URL param' do
let(:pipeline) { create(:ci_pipeline, :with_test_reports, project: project) }
it 'renders the test report' do
get_test_report_json
it 'returns a test reports with empty values' do
get_test_report_json(scope: 'with_attachment')
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['total_count']).to eq(4)
end
end
context 'when pipeline has a corrupt test report artifact' do
before do
create(:ci_build, name: 'rspec', pipeline: pipeline).tap do |build|
create(:ci_job_artifact, :junit_with_corrupted_data, job: build)
end
get_test_report_json
end
it 'renders the test reports' do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['test_suites'].count).to eq(1)
end
it 'returns a suite_error on the suite with corrupted XML' do
expect(json_response['test_suites'].first['suite_error']).to eq('JUnit XML parsing failed: 1:1: FATAL: Document is empty')
end
end
context 'when junit_pipeline_screenshots_view is enabled' do
before do
stub_feature_flags(junit_pipeline_screenshots_view: project)
end
context 'when test_report contains attachment and scope is with_attachment as a URL param' do
let(:pipeline) { create(:ci_pipeline, :with_test_reports_attachment, project: project) }
it 'returns a test reports with attachment' do
get_test_report_json(scope: 'with_attachment')
expect(response).to have_gitlab_http_status(:ok)
expect(json_response["test_suites"]).to be_present
expect(json_response["test_suites"].first["test_cases"].first).to include("attachment_url")
end
end
context 'when test_report does not contain attachment and scope is with_attachment as a URL param' do
let(:pipeline) { create(:ci_pipeline, :with_test_reports, project: project) }
it 'returns a test reports with empty values' do
get_test_report_json(scope: 'with_attachment')
expect(response).to have_gitlab_http_status(:ok)
expect(json_response["test_suites"]).to be_empty
end
end
end
context 'when junit_pipeline_screenshots_view is disabled' do
before do
stub_feature_flags(junit_pipeline_screenshots_view: false)
end
context 'when test_report contains attachment and scope is with_attachment as a URL param' do
let(:pipeline) { create(:ci_pipeline, :with_test_reports_attachment, project: project) }
it 'returns a test reports without attachment_url' do
get_test_report_json(scope: 'with_attachment')
expect(response).to have_gitlab_http_status(:ok)
expect(json_response["test_suites"].first["test_cases"].first).not_to include("attachment_url")
end
expect(json_response["test_suites"]).to be_empty
end
end
end
context 'when feature is disabled' do
let(:pipeline) { create(:ci_empty_pipeline, project: project) }
context 'when junit_pipeline_screenshots_view is disabled' do
before do
stub_feature_flags(junit_pipeline_view: false)
stub_feature_flags(junit_pipeline_screenshots_view: false)
end
it 'renders empty response' do
get_test_report_json
context 'when test_report contains attachment and scope is with_attachment as a URL param' do
let(:pipeline) { create(:ci_pipeline, :with_test_reports_attachment, project: project) }
expect(response).to have_gitlab_http_status(:no_content)
expect(response.body).to be_empty
it 'returns a test reports without attachment_url' do
get_test_report_json(scope: 'with_attachment')
expect(response).to have_gitlab_http_status(:ok)
expect(json_response["test_suites"].first["test_cases"].first).not_to include("attachment_url")
end
end
end

View File

@ -118,6 +118,8 @@ describe('AlertDetails', () => {
${'monitoringTool'} | ${undefined} | ${false}
${'service'} | ${'Prometheus'} | ${true}
${'service'} | ${undefined} | ${false}
${'runbook'} | ${undefined} | ${false}
${'runbook'} | ${'run.com'} | ${true}
`(`$desc`, ({ field, data, isShown }) => {
beforeEach(() => {
mountComponent({ data: { alert: { ...mockAlert, [field]: data } } });

View File

@ -15,7 +15,6 @@ RSpec.describe Projects::PipelinesController, "(JavaScript fixtures)", type: :co
before do
sign_in(user)
stub_feature_flags(junit_pipeline_view: project)
end
it "pipelines/test_report.json" do

View File

@ -20,10 +20,7 @@ describe('Grouped test reports app', () => {
let wrapper;
let mockStore;
const mountComponent = ({
glFeatures = { junitPipelineView: false },
props = { pipelinePath },
} = {}) => {
const mountComponent = ({ props = { pipelinePath } } = {}) => {
wrapper = mount(Component, {
store: mockStore,
localVue,
@ -35,9 +32,6 @@ describe('Grouped test reports app', () => {
methods: {
fetchReports: () => {},
},
provide: {
glFeatures,
},
});
};
@ -78,28 +72,17 @@ describe('Grouped test reports app', () => {
});
describe('`View full report` button', () => {
it('should not render the full test report link', () => {
expect(findFullTestReportLink().exists()).toBe(false);
});
it('should render the full test report link', () => {
const fullTestReportLink = findFullTestReportLink();
describe('With junitPipelineView feature flag enabled', () => {
beforeEach(() => {
mountComponent({ glFeatures: { junitPipelineView: true } });
});
it('should render the full test report link', () => {
const fullTestReportLink = findFullTestReportLink();
expect(fullTestReportLink.exists()).toBe(true);
expect(pipelinePath).not.toBe('');
expect(fullTestReportLink.attributes('href')).toBe(`${pipelinePath}/test_report`);
});
expect(fullTestReportLink.exists()).toBe(true);
expect(pipelinePath).not.toBe('');
expect(fullTestReportLink.attributes('href')).toBe(`${pipelinePath}/test_report`);
});
describe('Without a pipelinePath', () => {
beforeEach(() => {
mountComponent({
glFeatures: { junitPipelineView: true },
props: { pipelinePath: '' },
});
});

View File

@ -6,8 +6,7 @@ RSpec.describe Banzai::Filter::GollumTagsFilter do
include FilterSpecHelper
let(:project) { create(:project) }
let(:user) { double }
let(:wiki) { ProjectWiki.new(project, user) }
let(:wiki) { ProjectWiki.new(project, nil) }
describe 'validation' do
it 'ensure that a :wiki key exists in context' do

View File

@ -7,8 +7,7 @@ RSpec.describe Banzai::Filter::WikiLinkFilter do
let(:namespace) { build_stubbed(:namespace, name: "wiki_link_ns") }
let(:project) { build_stubbed(:project, :public, name: "wiki_link_project", namespace: namespace) }
let(:user) { double }
let(:wiki) { ProjectWiki.new(project, user) }
let(:wiki) { ProjectWiki.new(project, nil) }
let(:repository_upload_folder) { Wikis::CreateAttachmentService::ATTACHMENT_PATH }
it "doesn't rewrite absolute links" do

View File

@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Banzai::Pipeline::WikiPipeline do
let_it_be(:namespace) { create(:namespace, name: "wiki_link_ns") }
let_it_be(:project) { create(:project, :public, name: "wiki_link_project", namespace: namespace) }
let_it_be(:wiki) { ProjectWiki.new(project, double(:user)) }
let_it_be(:wiki) { ProjectWiki.new(project, nil) }
let_it_be(:page) { build(:wiki_page, wiki: wiki, title: 'nested/twice/start-page') }
describe 'TableOfContents' do

View File

@ -7,12 +7,12 @@ RSpec.describe Gitlab::UsageDataCounters::TrackUniqueActions, :clean_gitlab_redi
let(:time) { Time.zone.now }
def track_action(params)
track_unique_events.track_action(params)
def track_event(params)
track_unique_events.track_event(params)
end
def count_unique_events(params)
track_unique_events.count_unique_events(params)
def count_unique(params)
track_unique_events.count_unique(params)
end
context 'tracking an event' do
@ -29,28 +29,28 @@ RSpec.describe Gitlab::UsageDataCounters::TrackUniqueActions, :clean_gitlab_redi
design = Event::TARGET_TYPES[:design]
wiki = Event::TARGET_TYPES[:wiki]
expect(track_action(event_action: :pushed, event_target: project, author_id: 1)).to be_truthy
expect(track_action(event_action: :pushed, event_target: project, author_id: 1)).to be_truthy
expect(track_action(event_action: :pushed, event_target: project, author_id: 2)).to be_truthy
expect(track_action(event_action: :pushed, event_target: project, author_id: 3)).to be_truthy
expect(track_action(event_action: :pushed, event_target: project, author_id: 4, time: time - 3.days)).to be_truthy
expect(track_action(event_action: :created, event_target: project, author_id: 5, time: time - 3.days)).to be_truthy
expect(track_event(event_action: :pushed, event_target: project, author_id: 1)).to be_truthy
expect(track_event(event_action: :pushed, event_target: project, author_id: 1)).to be_truthy
expect(track_event(event_action: :pushed, event_target: project, author_id: 2)).to be_truthy
expect(track_event(event_action: :pushed, event_target: project, author_id: 3)).to be_truthy
expect(track_event(event_action: :pushed, event_target: project, author_id: 4, time: time - 3.days)).to be_truthy
expect(track_event(event_action: :created, event_target: project, author_id: 5, time: time - 3.days)).to be_truthy
expect(track_action(event_action: :destroyed, event_target: design, author_id: 3)).to be_truthy
expect(track_action(event_action: :created, event_target: design, author_id: 4)).to be_truthy
expect(track_action(event_action: :updated, event_target: design, author_id: 5)).to be_truthy
expect(track_action(event_action: :pushed, event_target: design, author_id: 6)).to be_truthy
expect(track_event(event_action: :destroyed, event_target: design, author_id: 3)).to be_truthy
expect(track_event(event_action: :created, event_target: design, author_id: 4)).to be_truthy
expect(track_event(event_action: :updated, event_target: design, author_id: 5)).to be_truthy
expect(track_event(event_action: :pushed, event_target: design, author_id: 6)).to be_truthy
expect(track_action(event_action: :destroyed, event_target: wiki, author_id: 5)).to be_truthy
expect(track_action(event_action: :created, event_target: wiki, author_id: 3)).to be_truthy
expect(track_action(event_action: :updated, event_target: wiki, author_id: 4)).to be_truthy
expect(track_action(event_action: :pushed, event_target: wiki, author_id: 6)).to be_truthy
expect(track_event(event_action: :destroyed, event_target: wiki, author_id: 5)).to be_truthy
expect(track_event(event_action: :created, event_target: wiki, author_id: 3)).to be_truthy
expect(track_event(event_action: :updated, event_target: wiki, author_id: 4)).to be_truthy
expect(track_event(event_action: :pushed, event_target: wiki, author_id: 6)).to be_truthy
expect(count_unique_events(event_action: described_class::PUSH_ACTION, date_from: time, date_to: Date.today)).to eq(3)
expect(count_unique_events(event_action: described_class::PUSH_ACTION, date_from: time - 5.days, date_to: Date.tomorrow)).to eq(4)
expect(count_unique_events(event_action: described_class::DESIGN_ACTION, date_from: time - 5.days, date_to: Date.today)).to eq(3)
expect(count_unique_events(event_action: described_class::WIKI_ACTION, date_from: time - 5.days, date_to: Date.today)).to eq(3)
expect(count_unique_events(event_action: described_class::PUSH_ACTION, date_from: time - 5.days, date_to: time - 2.days)).to eq(1)
expect(count_unique(event_action: described_class::PUSH_ACTION, date_from: time, date_to: Date.today)).to eq(3)
expect(count_unique(event_action: described_class::PUSH_ACTION, date_from: time - 5.days, date_to: Date.tomorrow)).to eq(4)
expect(count_unique(event_action: described_class::DESIGN_ACTION, date_from: time - 5.days, date_to: Date.today)).to eq(3)
expect(count_unique(event_action: described_class::WIKI_ACTION, date_from: time - 5.days, date_to: Date.today)).to eq(3)
expect(count_unique(event_action: described_class::PUSH_ACTION, date_from: time - 5.days, date_to: time - 2.days)).to eq(1)
end
end
end
@ -73,8 +73,8 @@ RSpec.describe Gitlab::UsageDataCounters::TrackUniqueActions, :clean_gitlab_redi
end
it 'returns the expected values' do
expect(track_action(event_action: action, event_target: target, author_id: 2)).to be_nil
expect(count_unique_events(event_action: described_class::PUSH_ACTION, date_from: time, date_to: Date.today)).to eq(0)
expect(track_event(event_action: action, event_target: target, author_id: 2)).to be_nil
expect(count_unique(event_action: described_class::PUSH_ACTION, date_from: time, date_to: Date.today)).to eq(0)
end
end
end

View File

@ -924,14 +924,14 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
wiki = Event::TARGET_TYPES[:wiki]
design = Event::TARGET_TYPES[:design]
counter.track_action(event_action: :pushed, event_target: project, author_id: 1)
counter.track_action(event_action: :pushed, event_target: project, author_id: 1)
counter.track_action(event_action: :pushed, event_target: project, author_id: 2)
counter.track_action(event_action: :pushed, event_target: project, author_id: 3)
counter.track_action(event_action: :pushed, event_target: project, author_id: 4, time: time - 3.days)
counter.track_action(event_action: :created, event_target: project, author_id: 5, time: time - 3.days)
counter.track_action(event_action: :created, event_target: wiki, author_id: 3)
counter.track_action(event_action: :created, event_target: design, author_id: 3)
counter.track_event(event_action: :pushed, event_target: project, author_id: 1)
counter.track_event(event_action: :pushed, event_target: project, author_id: 1)
counter.track_event(event_action: :pushed, event_target: project, author_id: 2)
counter.track_event(event_action: :pushed, event_target: project, author_id: 3)
counter.track_event(event_action: :pushed, event_target: project, author_id: 4, time: time - 3.days)
counter.track_event(event_action: :created, event_target: project, author_id: 5, time: time - 3.days)
counter.track_event(event_action: :created, event_target: wiki, author_id: 3)
counter.track_event(event_action: :created, event_target: design, author_id: 3)
end
it 'returns the distinct count of user actions within the specified time period' do

View File

@ -1541,4 +1541,48 @@ RSpec.describe Group do
end
end
end
describe '#default_owner' do
let(:group) { build(:group) }
context 'the group has owners' do
before do
group.add_owner(create(:user))
group.add_owner(create(:user))
end
it 'is the first owner' do
expect(group.default_owner)
.to eq(group.owners.first)
.and be_a(User)
end
end
context 'the group has a parent' do
let(:parent) { build(:group) }
before do
group.parent = parent
parent.add_owner(create(:user))
end
it 'is the first owner of the parent' do
expect(group.default_owner)
.to eq(parent.default_owner)
.and be_a(User)
end
end
context 'we fallback to group.owner' do
before do
group.owner = build(:user)
end
it 'is the group.owner' do
expect(group.default_owner)
.to eq(group.owner)
.and be_a(User)
end
end
end
end

View File

@ -1090,6 +1090,30 @@ RSpec.describe Project do
end
end
describe '#default_owner' do
let_it_be(:owner) { create(:user) }
let_it_be(:namespace) { create(:namespace, owner: owner) }
context 'the project does not have a group' do
let(:project) { build(:project, namespace: namespace) }
it 'is the namespace owner' do
expect(project.default_owner).to eq(owner)
end
end
context 'the project is in a group' do
let(:group) { build(:group) }
let(:project) { build(:project, group: group, namespace: namespace) }
it 'is the group owner' do
allow(group).to receive(:default_owner).and_return(Object.new)
expect(project.default_owner).to eq(group.default_owner)
end
end
end
describe '#external_wiki' do
let(:project) { create(:project) }

14
spec/models/wiki_spec.rb Normal file
View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
require "spec_helper"
RSpec.describe Wiki do
describe '.new' do
it 'verifies that the user is a User' do
expect { described_class.new(double, 1) }.to raise_error(ArgumentError)
expect { described_class.new(double, build(:group)) }.to raise_error(ArgumentError)
expect { described_class.new(double, build(:user)) }.not_to raise_error
expect { described_class.new(double, nil) }.not_to raise_error
end
end
end

View File

@ -735,55 +735,36 @@ RSpec.describe API::Ci::Pipelines do
let(:pipeline) { create(:ci_pipeline, project: project) }
context 'when feature is enabled' do
before do
stub_feature_flags(junit_pipeline_view: true)
end
context 'when pipeline does not have a test report' do
it 'returns an empty test report' do
subject
context 'when pipeline does not have a test report' do
it 'returns an empty test report' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['total_count']).to eq(0)
end
end
context 'when pipeline has a test report' do
let(:pipeline) { create(:ci_pipeline, :with_test_reports, project: project) }
it 'returns the test report' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['total_count']).to eq(4)
end
end
context 'when pipeline has corrupt test reports' do
before do
job = create(:ci_build, pipeline: pipeline)
create(:ci_job_artifact, :junit_with_corrupted_data, job: job, project: project)
end
it 'returns a suite_error' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['test_suites'].first['suite_error']).to eq('JUnit XML parsing failed: 1:1: FATAL: Document is empty')
end
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['total_count']).to eq(0)
end
end
context 'when feature is disabled' do
before do
stub_feature_flags(junit_pipeline_view: false)
end
context 'when pipeline has a test report' do
let(:pipeline) { create(:ci_pipeline, :with_test_reports, project: project) }
it 'renders empty response' do
it 'returns the test report' do
subject
expect(response).to have_gitlab_http_status(:not_found)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['total_count']).to eq(4)
end
end
context 'when pipeline has corrupt test reports' do
before do
create(:ci_build, :broken_test_reports, name: 'rspec', pipeline: pipeline)
end
it 'returns a suite_error' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['test_suites'].first['suite_error']).to eq('JUnit XML parsing failed: 1:1: FATAL: Document is empty')
end
end
end

View File

@ -147,8 +147,7 @@ RSpec.describe AlertManagement::Alerts::UpdateService do
end
it_behaves_like 'does not add a system note'
# TODO: We should not add another todo in this scenario
it_behaves_like 'adds a todo'
it_behaves_like 'does not add a todo'
end
context 'with multiple users included' do

View File

@ -207,7 +207,7 @@ RSpec.describe EventCreateService do
tracking_params = { event_action: counter_class::WIKI_ACTION, date_from: Date.yesterday, date_to: Date.today }
expect { create_event }
.to change { counter_class.count_unique_events(tracking_params) }
.to change { counter_class.count_unique(tracking_params) }
.by(1)
end
end
@ -249,7 +249,7 @@ RSpec.describe EventCreateService do
tracking_params = { event_action: counter_class::PUSH_ACTION, date_from: Date.yesterday, date_to: Date.today }
expect { subject }
.to change { counter_class.count_unique_events(tracking_params) }
.to change { counter_class.count_unique(tracking_params) }
.from(0).to(1)
end
end
@ -273,7 +273,7 @@ RSpec.describe EventCreateService do
tracking_params = { event_action: counter_class::PUSH_ACTION, date_from: Date.yesterday, date_to: Date.today }
expect { subject }
.to change { counter_class.count_unique_events(tracking_params) }
.to change { counter_class.count_unique(tracking_params) }
.from(0).to(1)
end
end
@ -328,7 +328,7 @@ RSpec.describe EventCreateService do
tracking_params = { event_action: counter_class::DESIGN_ACTION, date_from: Date.yesterday, date_to: Date.today }
expect { result }
.to change { counter_class.count_unique_events(tracking_params) }
.to change { counter_class.count_unique(tracking_params) }
.from(0).to(1)
end
end
@ -356,7 +356,7 @@ RSpec.describe EventCreateService do
tracking_params = { event_action: counter_class::DESIGN_ACTION, date_from: Date.yesterday, date_to: Date.today }
expect { result }
.to change { counter_class.count_unique_events(tracking_params) }
.to change { counter_class.count_unique(tracking_params) }
.from(0).to(1)
end
end

View File

@ -34,6 +34,16 @@ RSpec.describe ResourceAccessTokens::CreateService do
end
end
shared_examples 'fails on gitlab.com' do
before do
allow(Gitlab).to receive(:com?) { true }
end
it 'returns nil' do
expect(subject).to be nil
end
end
shared_examples 'allows creation of bot with valid params' do
it { expect { subject }.to change { User.count }.by(1) }
@ -171,6 +181,7 @@ RSpec.describe ResourceAccessTokens::CreateService do
it_behaves_like 'fails when user does not have the permission to create a Resource Bot'
it_behaves_like 'fails when flag is disabled'
it_behaves_like 'fails on gitlab.com'
context 'user with valid permission' do
before_all do

View File

@ -59,6 +59,10 @@ RSpec.describe TodoService do
should_not_create_todo(user: guest, target: addressed_target_assigned, action: Todo::DIRECTLY_ADDRESSED)
end
it 'does not create a todo if already assigned' do
should_not_create_any_todo { service.send(described_method, target_assigned, author, [john_doe]) }
end
end
describe 'Issues' do
@ -573,10 +577,10 @@ RSpec.describe TodoService do
end
end
describe '#reassigned_issuable' do
let(:described_method) { :reassigned_issuable }
describe '#reassigned_assignable' do
let(:described_method) { :reassigned_assignable }
context 'issuable is a merge request' do
context 'assignable is a merge request' do
it_behaves_like 'reassigned target' do
let(:target_assigned) { create(:merge_request, source_project: project, author: author, assignees: [john_doe], description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") }
let(:addressed_target_assigned) { create(:merge_request, source_project: project, author: author, assignees: [john_doe], description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") }
@ -584,13 +588,21 @@ RSpec.describe TodoService do
end
end
context 'issuable is an issue' do
context 'assignable is an issue' do
it_behaves_like 'reassigned target' do
let(:target_assigned) { create(:issue, project: project, author: author, assignees: [john_doe], description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") }
let(:addressed_target_assigned) { create(:issue, project: project, author: author, assignees: [john_doe], description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") }
let(:target_unassigned) { create(:issue, project: project, author: author, assignees: []) }
end
end
context 'assignable is an alert' do
it_behaves_like 'reassigned target' do
let(:target_assigned) { create(:alert_management_alert, project: project, assignees: [john_doe]) }
let(:addressed_target_assigned) { create(:alert_management_alert, project: project, assignees: [john_doe]) }
let(:target_unassigned) { create(:alert_management_alert, project: project, assignees: []) }
end
end
end
describe 'Merge Requests' do
@ -778,16 +790,6 @@ RSpec.describe TodoService do
end
end
describe '#assign_alert' do
let(:described_method) { :assign_alert }
it_behaves_like 'reassigned target' do
let(:target_assigned) { create(:alert_management_alert, project: project, assignees: [john_doe]) }
let(:addressed_target_assigned) { create(:alert_management_alert, project: project, assignees: [john_doe]) }
let(:target_unassigned) { create(:alert_management_alert, project: project, assignees: []) }
end
end
describe '#merge_request_build_failed' do
let(:merge_participants) { [mr_unassigned.author, admin] }