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>
<div class="gl-pl-2" data-testid="service">{{ alert.service }}</div> <div class="gl-pl-2" data-testid="service">{{ alert.service }}</div>
</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> <template>
<div v-if="alert.notes.nodes" class="issuable-discussion py-5"> <div v-if="alert.notes.nodes" class="issuable-discussion py-5">
<ul class="notes main-notes-list timeline"> <ul class="notes main-notes-list timeline">

View File

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

View File

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

View File

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

View File

@ -43,7 +43,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action do before_action do
push_frontend_feature_flag(:vue_issuable_sidebar, @project.group) push_frontend_feature_flag(:vue_issuable_sidebar, @project.group)
push_frontend_feature_flag(:junit_pipeline_view, @project.group)
end end
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions] 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_create_pipeline!, only: [:new, :create]
before_action :authorize_update_pipeline!, only: [:retry, :cancel] before_action :authorize_update_pipeline!, only: [:retry, :cancel]
before_action do 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(:filter_pipelines_search, project, default_enabled: true)
push_frontend_feature_flag(:dag_pipeline_tab, project, default_enabled: true) push_frontend_feature_flag(:dag_pipeline_tab, project, default_enabled: true)
push_frontend_feature_flag(:pipelines_security_report_summary, project) push_frontend_feature_flag(:pipelines_security_report_summary, project)
@ -177,8 +176,6 @@ class Projects::PipelinesController < Projects::ApplicationController
end end
def test_report def test_report
return unless Feature.enabled?(:junit_pipeline_view, project)
respond_to do |format| respond_to do |format|
format.html do format.html do
render 'show' render 'show'

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -109,7 +109,7 @@ class EventCreateService
def wiki_event(wiki_page_meta, author, action, fingerprint) def wiki_event(wiki_page_meta, author, action, fingerprint)
raise IllegalActionError, action unless Event::WIKI_ACTIONS.include?(action) 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 duplicate = Event.for_wiki_meta(wiki_page_meta).for_fingerprint(fingerprint).first
return duplicate if duplicate.present? return duplicate if duplicate.present?
@ -154,7 +154,7 @@ class EventCreateService
result = Event.insert_all(attribute_sets, returning: %w[id]) result = Event.insert_all(attribute_sets, returning: %w[id])
tuples.each do |record, status, _| 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 end
result result
@ -172,7 +172,7 @@ class EventCreateService
new_event new_event
end 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) Users::LastPushEventService.new(current_user)
.cache_last_push_event(event) .cache_last_push_event(event)

View File

@ -43,7 +43,7 @@ module Issues
if issue.assignees != old_assignees if issue.assignees != old_assignees
create_assignee_note(issue, old_assignees) create_assignee_note(issue, old_assignees)
notification_service.async.reassigned_issue(issue, current_user, 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 end
if issue.previous_changes.include?('confidential') if issue.previous_changes.include?('confidential')

View File

@ -105,7 +105,7 @@ module MergeRequests
def handle_assignees_change(merge_request, old_assignees) def handle_assignees_change(merge_request, old_assignees)
create_assignee_note(merge_request, old_assignees) create_assignee_note(merge_request, old_assignees)
notification_service.async.reassigned_merge_request(merge_request, current_user, 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 end
def create_branch_change_note(issuable, branch_type, old_branch, new_branch) 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 attr_reader :resource_type, :resource
def feature_enabled? def feature_enabled?
return false if ::Gitlab.com?
::Feature.enabled?(:resource_access_token, resource, default_enabled: true) ::Feature.enabled?(:resource_access_token, resource, default_enabled: true)
end end

View File

@ -49,11 +49,11 @@ class TodoService
todo_users.each(&:update_todos_count_cache) todo_users.each(&:update_todos_count_cache)
end 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) create_assignment_todo(issuable, current_user, old_assignees)
end end
@ -154,14 +154,6 @@ class TodoService
resolve_todos_for_target(awardable, current_user) resolve_todos_for_target(awardable, current_user)
end 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 # When user marks a target as todo
def mark_todo(target, current_user) def mark_todo(target, current_user)
attributes = attributes_for_todo(target.project, target, current_user, Todo::MARKED) attributes = attributes_for_todo(target.project, target, current_user, Todo::MARKED)

View File

@ -1,5 +1,4 @@
- return if pipeline_has_errors - 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) - dag_pipeline_tab_enabled = Feature.enabled?(:dag_pipeline_tab, @project, default_enabled: true)
.tabs-holder .tabs-holder
@ -20,7 +19,6 @@
= link_to failures_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-failures', action: 'failures', toggle: 'tab' }, class: 'failures-tab' do = link_to failures_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-failures', action: 'failures', toggle: 'tab' }, class: 'failures-tab' do
= _('Failed Jobs') = _('Failed Jobs')
%span.badge.badge-pill.js-failures-counter= @pipeline.failed_builds.count %span.badge.badge-pill.js-failures-counter= @pipeline.failed_builds.count
- if test_reports_enabled
%li.js-tests-tab-link %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 = 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') = s_('TestReports|Tests')

View File

@ -10,8 +10,9 @@
= page_title = page_title
%p %p
= _('You can generate an access token scoped to this project for each application to use the GitLab API.') = _('You can generate an access token scoped to this project for each application to use the GitLab API.')
%p -# Commented out until https://gitlab.com/gitlab-org/gitlab/-/issues/219551 is fixed
= _('You can also use project access tokens to authenticate against Git over HTTP.') -# %p
-# = _('You can also use project access tokens to authenticate against Git over HTTP.')
.col-lg-8 .col-lg-8
- if @new_project_access_token - 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'] ||= Settingslogic.new({})
Settings.cron_jobs['elastic_cluster_reindexing_cron_worker']['cron'] ||= '*/10 * * * *' 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_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'] ||= Settingslogic.new({})
Settings.cron_jobs['sync_seat_link_worker']['cron'] ||= "#{rand(60)} 0 * * *" Settings.cron_jobs['sync_seat_link_worker']['cron'] ||= "#{rand(60)} 0 * * *"
Settings.cron_jobs['sync_seat_link_worker']['job_class'] = 'SyncSeatLinkWorker' 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_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 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); 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>)) 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 ```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: `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 { input BoardEpicIssueInput {
""" """
Username of a user assigned to issues Filter by assignee username
""" """
assigneeUsername: [String] assigneeUsername: [String]
""" """
Username of the issues author Filter by author username
""" """
authorUsername: String authorUsername: String
""" """
Epic ID applied to issues Filter by epic ID
""" """
epicId: String epicId: String
""" """
Label applied to issues Filter by label name
""" """
labelName: [String] labelName: [String]
""" """
Milestone applied to issues Filter by milestone title
""" """
milestoneTitle: String milestoneTitle: String
""" """
Reaction emoji applied to issues Filter by reaction emoji
""" """
myReactionEmoji: String 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 releaseTag: String
""" """
Weight applied to issues Filter by weight
""" """
weight: String weight: String
} }
@ -9795,6 +9800,48 @@ type NamespaceIncreaseStorageTemporarilyPayload {
namespace: Namespace 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 { type Note implements ResolvableInterface {
""" """
User who wrote this note User who wrote this note

View File

@ -3049,7 +3049,7 @@
"inputFields": [ "inputFields": [
{ {
"name": "labelName", "name": "labelName",
"description": "Label applied to issues", "description": "Filter by label name",
"type": { "type": {
"kind": "LIST", "kind": "LIST",
"name": null, "name": null,
@ -3063,7 +3063,7 @@
}, },
{ {
"name": "milestoneTitle", "name": "milestoneTitle",
"description": "Milestone applied to issues", "description": "Filter by milestone title",
"type": { "type": {
"kind": "SCALAR", "kind": "SCALAR",
"name": "String", "name": "String",
@ -3073,7 +3073,7 @@
}, },
{ {
"name": "assigneeUsername", "name": "assigneeUsername",
"description": "Username of a user assigned to issues", "description": "Filter by assignee username",
"type": { "type": {
"kind": "LIST", "kind": "LIST",
"name": null, "name": null,
@ -3087,7 +3087,7 @@
}, },
{ {
"name": "authorUsername", "name": "authorUsername",
"description": "Username of the issues author", "description": "Filter by author username",
"type": { "type": {
"kind": "SCALAR", "kind": "SCALAR",
"name": "String", "name": "String",
@ -3097,7 +3097,7 @@
}, },
{ {
"name": "releaseTag", "name": "releaseTag",
"description": "Release applied to issues", "description": "Filter by release tag",
"type": { "type": {
"kind": "SCALAR", "kind": "SCALAR",
"name": "String", "name": "String",
@ -3107,7 +3107,7 @@
}, },
{ {
"name": "epicId", "name": "epicId",
"description": "Epic ID applied to issues", "description": "Filter by epic ID",
"type": { "type": {
"kind": "SCALAR", "kind": "SCALAR",
"name": "String", "name": "String",
@ -3117,7 +3117,7 @@
}, },
{ {
"name": "myReactionEmoji", "name": "myReactionEmoji",
"description": "Reaction emoji applied to issues", "description": "Filter by reaction emoji",
"type": { "type": {
"kind": "SCALAR", "kind": "SCALAR",
"name": "String", "name": "String",
@ -3127,13 +3127,23 @@
}, },
{ {
"name": "weight", "name": "weight",
"description": "Weight applied to issues", "description": "Filter by weight",
"type": { "type": {
"kind": "SCALAR", "kind": "SCALAR",
"name": "String", "name": "String",
"ofType": null "ofType": null
}, },
"defaultValue": 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, "interfaces": null,
@ -29245,6 +29255,105 @@
"enumValues": null, "enumValues": null,
"possibleTypes": 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", "kind": "OBJECT",
"name": "Note", "name": "Note",

View File

@ -239,9 +239,8 @@ Test:
## Viewing JUnit test reports on GitLab ## Viewing JUnit test reports on GitLab
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24792) in GitLab 12.5. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24792) in GitLab 12.5 behind a feature flag (`junit_pipeline_view`), disabled by default.
> - It's deployed behind a feature flag, 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.
> - 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)**
If JUnit XML files are generated and uploaded as part of a pipeline, these reports 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 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). 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 ## Viewing JUnit screenshots on GitLab
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202114) in GitLab 13.0. > - [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 type: reference, howto
--- ---
# Project access tokens (Alpha) **(CORE ONLY)** # Project access tokens **(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.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2587) in GitLab 13.0. > - [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. > - 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). 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. 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 ### 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. Project access tokens are deployed behind a feature flag that is **enabled by default**.
It is deployed behind a feature flag that is **disabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) [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 ```ruby
Feature.enable(:resource_access_token) Feature.enable(:resource_access_token)
``` ```
To disable it: To enable it for a specific project:
```ruby ```ruby
Feature.disable(:resource_access_token) Feature.enable(:resource_access_token, project)
``` ```

View File

@ -110,15 +110,13 @@ module API
end end
desc 'Gets the test report for a given pipeline' do 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 success TestReportEntity
end end
params do params do
requires :pipeline_id, type: Integer, desc: 'The pipeline ID' requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
end end
get ':id/pipelines/:pipeline_id/test_report' do get ':id/pipelines/:pipeline_id/test_report' do
not_found! unless Feature.enabled?(:junit_pipeline_view, user_project)
authorize! :read_build, pipeline authorize! :read_build, pipeline
present pipeline.test_reports, with: TestReportEntity, details: true present pipeline.test_reports, with: TestReportEntity, details: true

View File

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

View File

@ -27,7 +27,7 @@ module Gitlab
}).freeze }).freeze
class << self 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 Gitlab::CurrentSettings.usage_ping_enabled
return unless Feature.enabled?(FEATURE_FLAG) return unless Feature.enabled?(FEATURE_FLAG)
return unless valid_target?(event_target) 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) Gitlab::Redis::HLL.add(key: target_key, value: author_id, expiry: KEY_EXPIRY_LENGTH)
end 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) } keys = (date_from.to_date..date_to.to_date).map { |date| key(event_action, date) }
Gitlab::Redis::HLL.count(keys: keys) Gitlab::Redis::HLL.count(keys: keys)

View File

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

View File

@ -859,11 +859,6 @@ RSpec.describe Projects::PipelinesController do
end end
end end
context 'when feature is enabled' do
before do
stub_feature_flags(junit_pipeline_view: project)
end
context 'when pipeline does not have a test report' do context 'when pipeline does not have a test report' do
it 'renders an empty test report' do it 'renders an empty test report' do
get_test_report_json get_test_report_json
@ -875,9 +870,7 @@ RSpec.describe Projects::PipelinesController do
context 'when pipeline has a test report' do context 'when pipeline has a test report' do
before do before do
create(:ci_build, name: 'rspec', pipeline: pipeline).tap do |build| create(:ci_build, :test_reports, name: 'rspec', pipeline: pipeline)
create(:ci_job_artifact, :junit, job: build)
end
end end
it 'renders the test report' do it 'renders the test report' do
@ -890,9 +883,7 @@ RSpec.describe Projects::PipelinesController do
context 'when pipeline has a corrupt test report artifact' do context 'when pipeline has a corrupt test report artifact' do
before do before do
create(:ci_build, name: 'rspec', pipeline: pipeline).tap do |build| create(:ci_build, :broken_test_reports, name: 'rspec', pipeline: pipeline)
create(:ci_job_artifact, :junit_with_corrupted_data, job: build)
end
get_test_report_json get_test_report_json
end end
@ -952,22 +943,6 @@ RSpec.describe Projects::PipelinesController do
end end
end end
end end
end
context 'when feature is disabled' do
let(:pipeline) { create(:ci_empty_pipeline, project: project) }
before do
stub_feature_flags(junit_pipeline_view: false)
end
it 'renders empty response' do
get_test_report_json
expect(response).to have_gitlab_http_status(:no_content)
expect(response.body).to be_empty
end
end
def get_test_report_json(**args) def get_test_report_json(**args)
params = { params = {

View File

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

View File

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

View File

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

View File

@ -6,8 +6,7 @@ RSpec.describe Banzai::Filter::GollumTagsFilter do
include FilterSpecHelper include FilterSpecHelper
let(:project) { create(:project) } let(:project) { create(:project) }
let(:user) { double } let(:wiki) { ProjectWiki.new(project, nil) }
let(:wiki) { ProjectWiki.new(project, user) }
describe 'validation' do describe 'validation' do
it 'ensure that a :wiki key exists in context' 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(:namespace) { build_stubbed(:namespace, name: "wiki_link_ns") }
let(:project) { build_stubbed(:project, :public, name: "wiki_link_project", namespace: namespace) } let(:project) { build_stubbed(:project, :public, name: "wiki_link_project", namespace: namespace) }
let(:user) { double } let(:wiki) { ProjectWiki.new(project, nil) }
let(:wiki) { ProjectWiki.new(project, user) }
let(:repository_upload_folder) { Wikis::CreateAttachmentService::ATTACHMENT_PATH } let(:repository_upload_folder) { Wikis::CreateAttachmentService::ATTACHMENT_PATH }
it "doesn't rewrite absolute links" do it "doesn't rewrite absolute links" do

View File

@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Banzai::Pipeline::WikiPipeline do RSpec.describe Banzai::Pipeline::WikiPipeline do
let_it_be(:namespace) { create(:namespace, name: "wiki_link_ns") } 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(: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') } let_it_be(:page) { build(:wiki_page, wiki: wiki, title: 'nested/twice/start-page') }
describe 'TableOfContents' do describe 'TableOfContents' do

View File

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

View File

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

View File

@ -1090,6 +1090,30 @@ RSpec.describe Project do
end end
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 describe '#external_wiki' do
let(:project) { create(:project) } 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,11 +735,6 @@ RSpec.describe API::Ci::Pipelines do
let(:pipeline) { create(:ci_pipeline, project: project) } 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 context 'when pipeline does not have a test report' do
it 'returns an empty test report' do it 'returns an empty test report' do
subject subject
@ -762,8 +757,7 @@ RSpec.describe API::Ci::Pipelines do
context 'when pipeline has corrupt test reports' do context 'when pipeline has corrupt test reports' do
before do before do
job = create(:ci_build, pipeline: pipeline) create(:ci_build, :broken_test_reports, name: 'rspec', pipeline: pipeline)
create(:ci_job_artifact, :junit_with_corrupted_data, job: job, project: project)
end end
it 'returns a suite_error' do it 'returns a suite_error' do
@ -775,19 +769,6 @@ RSpec.describe API::Ci::Pipelines do
end end
end end
context 'when feature is disabled' do
before do
stub_feature_flags(junit_pipeline_view: false)
end
it 'renders empty response' do
subject
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
context 'unauthorized user' do context 'unauthorized user' do
it 'does not return project pipelines' do it 'does not return project pipelines' do
get api("/projects/#{project.id}/pipelines/#{pipeline.id}/test_report", non_member) get api("/projects/#{project.id}/pipelines/#{pipeline.id}/test_report", non_member)

View File

@ -147,8 +147,7 @@ RSpec.describe AlertManagement::Alerts::UpdateService do
end end
it_behaves_like 'does not add a system note' it_behaves_like 'does not add a system note'
# TODO: We should not add another todo in this scenario it_behaves_like 'does not add a todo'
it_behaves_like 'adds a todo'
end end
context 'with multiple users included' do 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 } tracking_params = { event_action: counter_class::WIKI_ACTION, date_from: Date.yesterday, date_to: Date.today }
expect { create_event } expect { create_event }
.to change { counter_class.count_unique_events(tracking_params) } .to change { counter_class.count_unique(tracking_params) }
.by(1) .by(1)
end end
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 } tracking_params = { event_action: counter_class::PUSH_ACTION, date_from: Date.yesterday, date_to: Date.today }
expect { subject } expect { subject }
.to change { counter_class.count_unique_events(tracking_params) } .to change { counter_class.count_unique(tracking_params) }
.from(0).to(1) .from(0).to(1)
end end
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 } tracking_params = { event_action: counter_class::PUSH_ACTION, date_from: Date.yesterday, date_to: Date.today }
expect { subject } expect { subject }
.to change { counter_class.count_unique_events(tracking_params) } .to change { counter_class.count_unique(tracking_params) }
.from(0).to(1) .from(0).to(1)
end end
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 } tracking_params = { event_action: counter_class::DESIGN_ACTION, date_from: Date.yesterday, date_to: Date.today }
expect { result } expect { result }
.to change { counter_class.count_unique_events(tracking_params) } .to change { counter_class.count_unique(tracking_params) }
.from(0).to(1) .from(0).to(1)
end end
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 } tracking_params = { event_action: counter_class::DESIGN_ACTION, date_from: Date.yesterday, date_to: Date.today }
expect { result } expect { result }
.to change { counter_class.count_unique_events(tracking_params) } .to change { counter_class.count_unique(tracking_params) }
.from(0).to(1) .from(0).to(1)
end end
end end

View File

@ -34,6 +34,16 @@ RSpec.describe ResourceAccessTokens::CreateService do
end end
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 shared_examples 'allows creation of bot with valid params' do
it { expect { subject }.to change { User.count }.by(1) } 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 user does not have the permission to create a Resource Bot'
it_behaves_like 'fails when flag is disabled' it_behaves_like 'fails when flag is disabled'
it_behaves_like 'fails on gitlab.com'
context 'user with valid permission' do context 'user with valid permission' do
before_all 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) should_not_create_todo(user: guest, target: addressed_target_assigned, action: Todo::DIRECTLY_ADDRESSED)
end 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 end
describe 'Issues' do describe 'Issues' do
@ -573,10 +577,10 @@ RSpec.describe TodoService do
end end
end end
describe '#reassigned_issuable' do describe '#reassigned_assignable' do
let(:described_method) { :reassigned_issuable } 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 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(: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") } 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
end end
context 'issuable is an issue' do context 'assignable is an issue' do
it_behaves_like 'reassigned target' 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(: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(: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: []) } let(:target_unassigned) { create(:issue, project: project, author: author, assignees: []) }
end end
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 end
describe 'Merge Requests' do describe 'Merge Requests' do
@ -778,16 +790,6 @@ RSpec.describe TodoService do
end end
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 describe '#merge_request_build_failed' do
let(:merge_participants) { [mr_unassigned.author, admin] } let(:merge_participants) { [mr_unassigned.author, admin] }