Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
e92c95bf45
commit
d7774ee304
|
@ -123,6 +123,7 @@
|
|||
- ".gitlab/route-map.yml"
|
||||
- "doc/**/*"
|
||||
- ".markdownlint.json"
|
||||
- "scripts/lint-doc.sh"
|
||||
|
||||
.frontend-dependency-patterns: &frontend-dependency-patterns
|
||||
- "{package.json,yarn.lock}"
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
<script>
|
||||
import { isEmpty } from 'lodash';
|
||||
import { GlLink } from '@gitlab/ui';
|
||||
import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TimeagoTooltip,
|
||||
GlAlert,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
TimeagoTooltip,
|
||||
},
|
||||
props: {
|
||||
user: {
|
||||
|
@ -27,17 +29,21 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="gl-mt-3 js-build-erased">
|
||||
<div class="erased alert alert-warning">
|
||||
<div class="gl-mt-3">
|
||||
<gl-alert variant="warning" :dismissible="false">
|
||||
<template v-if="isErasedByUser">
|
||||
{{ s__('Job|Job has been erased by') }}
|
||||
<gl-link :href="user.web_url"> {{ user.username }} </gl-link>
|
||||
<gl-sprintf :message="s__('Job|Job has been erased by %{userLink}')">
|
||||
<template #userLink>
|
||||
<gl-link :href="user.web_url" target="_blank">{{ user.username }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
{{ s__('Job|Job has been erased') }}
|
||||
</template>
|
||||
|
||||
<timeago-tooltip :time="erasedAt" />
|
||||
</div>
|
||||
</gl-alert>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -35,6 +35,16 @@ export default (resolvers = {}, config = {}) => {
|
|||
batchMax: config.batchMax || 10,
|
||||
};
|
||||
|
||||
const requestCounterLink = new ApolloLink((operation, forward) => {
|
||||
window.pendingApolloRequests = window.pendingApolloRequests || 0;
|
||||
window.pendingApolloRequests += 1;
|
||||
|
||||
return forward(operation).map((response) => {
|
||||
window.pendingApolloRequests -= 1;
|
||||
return response;
|
||||
});
|
||||
});
|
||||
|
||||
const uploadsLink = ApolloLink.split(
|
||||
(operation) => operation.getContext().hasUpload || operation.getContext().isSingleRequest,
|
||||
createUploadLink(httpOptions),
|
||||
|
@ -63,7 +73,12 @@ export default (resolvers = {}, config = {}) => {
|
|||
|
||||
return new ApolloClient({
|
||||
typeDefs: config.typeDefs,
|
||||
link: ApolloLink.from([performanceBarLink, new StartupJSLink(), uploadsLink]),
|
||||
link: ApolloLink.from([
|
||||
requestCounterLink,
|
||||
performanceBarLink,
|
||||
new StartupJSLink(),
|
||||
uploadsLink,
|
||||
]),
|
||||
cache: new InMemoryCache({
|
||||
...config.cacheConfig,
|
||||
freezeResults: config.assumeImmutableResults,
|
||||
|
|
|
@ -6,6 +6,7 @@ import { languageCode, s__, __, n__ } from '../../locale';
|
|||
|
||||
const MILLISECONDS_IN_HOUR = 60 * 60 * 1000;
|
||||
const MILLISECONDS_IN_DAY = 24 * MILLISECONDS_IN_HOUR;
|
||||
const DAYS_IN_WEEK = 7;
|
||||
|
||||
window.timeago = timeago;
|
||||
|
||||
|
@ -693,6 +694,25 @@ export const nDaysAfter = (date, numberOfDays) =>
|
|||
*/
|
||||
export const nDaysBefore = (date, numberOfDays) => nDaysAfter(date, -numberOfDays);
|
||||
|
||||
/**
|
||||
* Returns the date n weeks after the date provided
|
||||
*
|
||||
* @param {Date} date the initial date
|
||||
* @param {Number} numberOfWeeks number of weeks after
|
||||
* @return {Date} the date following the date provided
|
||||
*/
|
||||
export const nWeeksAfter = (date, numberOfWeeks) =>
|
||||
new Date(newDate(date)).setDate(date.getDate() + DAYS_IN_WEEK * numberOfWeeks);
|
||||
|
||||
/**
|
||||
* Returns the date n weeks before the date provided
|
||||
*
|
||||
* @param {Date} date the initial date
|
||||
* @param {Number} numberOfWeeks number of weeks before
|
||||
* @return {Date} the date following the date provided
|
||||
*/
|
||||
export const nWeeksBefore = (date, numberOfWeeks) => nWeeksAfter(date, -numberOfWeeks);
|
||||
|
||||
/**
|
||||
* Returns the date n months after the date provided
|
||||
*
|
||||
|
@ -897,3 +917,19 @@ export const getOverlapDateInPeriods = (givenPeriodLeft = {}, givenPeriodRight =
|
|||
overlapEndDate,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* A utility function that checks that the date is today
|
||||
*
|
||||
* @param {Date} date
|
||||
*
|
||||
* @return {Boolean} true if provided date is today
|
||||
*/
|
||||
export const isToday = (date) => {
|
||||
const today = new Date();
|
||||
return (
|
||||
date.getDate() === today.getDate() &&
|
||||
date.getMonth() === today.getMonth() &&
|
||||
date.getFullYear() === today.getFullYear()
|
||||
);
|
||||
};
|
||||
|
|
|
@ -31,10 +31,11 @@ module AvatarsHelper
|
|||
end
|
||||
|
||||
def avatar_icon_for_user(user = nil, size = nil, scale = 2, only_path: true)
|
||||
return gravatar_icon(nil, size, scale) unless user
|
||||
return default_avatar if user.blocked?
|
||||
|
||||
user.avatar_url(size: size, only_path: only_path) || default_avatar
|
||||
if user
|
||||
user.avatar_url(size: size, only_path: only_path) || default_avatar
|
||||
else
|
||||
gravatar_icon(nil, size, scale)
|
||||
end
|
||||
end
|
||||
|
||||
def gravatar_icon(user_email = '', size = nil, scale = 2)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Ci
|
||||
class CodequalityMrDiffEntity < Grape::Entity
|
||||
expose :files
|
||||
end
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Ci
|
||||
class CodequalityMrDiffReportSerializer < BaseSerializer
|
||||
entity CodequalityMrDiffEntity
|
||||
end
|
||||
end
|
|
@ -22,11 +22,17 @@ module Ci
|
|||
|
||||
def build_carrierwave_file(pipeline)
|
||||
CarrierWaveStringFile.new_file(
|
||||
file_content: pipeline.codequality_reports.to_json,
|
||||
file_content: build_quality_mr_diff_report(pipeline),
|
||||
filename: Ci::PipelineArtifact::DEFAULT_FILE_NAMES.fetch(:code_quality),
|
||||
content_type: 'application/json'
|
||||
)
|
||||
end
|
||||
|
||||
def build_quality_mr_diff_report(pipeline)
|
||||
mr_diff_report = Gitlab::Ci::Reports::CodequalityMrDiff.new(pipeline.codequality_reports)
|
||||
|
||||
Ci::CodequalityMrDiffReportSerializer.new.represent(mr_diff_report).to_json # rubocop: disable CodeReuse/Serializer
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,6 +22,6 @@
|
|||
- unless @hide_breadcrumbs
|
||||
= render "layouts/nav/breadcrumbs"
|
||||
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
|
||||
.content{ id: "content-body", **page_itemtype }
|
||||
%main.content{ id: "content-body", **page_itemtype }
|
||||
= render "layouts/flash", extra_flash_class: 'limit-container-width'
|
||||
= yield
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
- unless @skip_current_level_breadcrumb
|
||||
- push_to_schema_breadcrumb(@breadcrumb_title, breadcrumb_title_link)
|
||||
|
||||
%nav.breadcrumbs{ role: "navigation", class: [container, @content_class] }
|
||||
%nav.breadcrumbs{ class: [container, @content_class], 'aria-label': _('Breadcrumbs') }
|
||||
.breadcrumbs-container{ class: ("border-bottom-0" if @no_breadcrumb_border) }
|
||||
- if defined?(@left_sidebar)
|
||||
= button_tag class: 'toggle-mobile-nav', type: 'button' do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.nav-sidebar.qa-admin-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?) }
|
||||
%aside.nav-sidebar.qa-admin-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), 'aria-label': _('Admin navigation') }
|
||||
.nav-sidebar-inner-scroll
|
||||
.context-header
|
||||
= link_to admin_root_path, title: _('Admin Overview') do
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
- issues_count = group_open_issues_count(@group)
|
||||
- merge_requests_count = group_merge_requests_count(state: 'opened')
|
||||
- aside_title = @group.subgroup? ? _('Subgroup navigation') : _('Group navigation')
|
||||
- overview_title = @group.subgroup? ? _('Subgroup overview') : _('Group overview')
|
||||
|
||||
.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('groups_side_navigation', 'render', 'groups_side_navigation') }
|
||||
%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('groups_side_navigation', 'render', 'groups_side_navigation'), 'aria-label': aside_title }
|
||||
.nav-sidebar-inner-scroll
|
||||
.context-header
|
||||
= link_to group_path(@group), title: @group.name do
|
||||
|
@ -19,19 +21,13 @@
|
|||
.nav-icon-container
|
||||
= sprite_icon('home')
|
||||
%span.nav-item-name
|
||||
- if @group.subgroup?
|
||||
= _('Subgroup overview')
|
||||
- else
|
||||
= _('Group overview')
|
||||
= overview_title
|
||||
|
||||
%ul.sidebar-sub-level-items
|
||||
= nav_link(path: ['groups#show', 'groups#details', 'groups#activity', 'groups#subgroups'], html_options: { class: "fly-out-top-item" } ) do
|
||||
= link_to group_path(@group) do
|
||||
%strong.fly-out-top-item-name
|
||||
- if @group.subgroup?
|
||||
= _('Subgroup overview')
|
||||
- else
|
||||
= _('Group overview')
|
||||
= overview_title
|
||||
%li.divider.fly-out-top-item
|
||||
|
||||
= nav_link(path: ['groups#show', 'groups#details', 'groups#subgroups'], html_options: { class: 'home' }) do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('user_side_navigation', 'render', 'user_side_navigation') }
|
||||
%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('user_side_navigation', 'render', 'user_side_navigation'), 'aria-label': _('User settings') }
|
||||
.nav-sidebar-inner-scroll
|
||||
.context-header
|
||||
= link_to profile_path, title: _('Profile Settings') do
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('projects_side_navigation', 'render', 'projects_side_navigation') }
|
||||
%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **tracking_attrs('projects_side_navigation', 'render', 'projects_side_navigation'), 'aria-label': _('Project navigation') }
|
||||
.nav-sidebar-inner-scroll
|
||||
.context-header
|
||||
= link_to project_path(@project), title: @project.name do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
%board-sidebar{ "inline-template" => true, ":current-user" => (UserSerializer.new.represent(current_user) || {}).to_json }
|
||||
%transition{ name: "boards-sidebar-slide" }
|
||||
%aside.right-sidebar.right-sidebar-expanded.issue-boards-sidebar{ "v-show" => "showSidebar" }
|
||||
%aside.right-sidebar.right-sidebar-expanded.issue-boards-sidebar{ "v-show" => "showSidebar", 'aria-label': s_('Boards|Board') }
|
||||
.issuable-sidebar
|
||||
.block.issuable-sidebar-header.position-relative
|
||||
%span.issuable-header-text.hide-collapsed.float-left
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
- epic_bulk_edit_flag = @project&.group&.feature_available?(:epics) && type == :issues
|
||||
- bulk_iterations_flag = @project&.group&.feature_available?(:iterations) && type == :issues
|
||||
|
||||
%aside.issues-bulk-update.js-right-sidebar.right-sidebar{ "aria-live" => "polite", data: { 'signed-in': current_user.present? } }
|
||||
%aside.issues-bulk-update.js-right-sidebar.right-sidebar{ "aria-live" => "polite", data: { 'signed-in': current_user.present? }, 'aria-label': _('Bulk update') }
|
||||
.issuable-sidebar.hidden
|
||||
= form_tag [:bulk_update, @project, type], method: :post, class: "bulk-update" do
|
||||
.block.issuable-sidebar-header
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
- add_page_startup_api_call "#{issuable_sidebar[:issuable_json_path]}?serializer=sidebar_extras"
|
||||
- reviewers = local_assigns.fetch(:reviewers, nil)
|
||||
|
||||
%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in }, issuable_type: issuable_type }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' }
|
||||
%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in }, issuable_type: issuable_type }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite', 'aria-label': issuable_type }
|
||||
.issuable-sidebar
|
||||
.block.issuable-sidebar-header
|
||||
- if signed_in
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- affix_offset = local_assigns.fetch(:affix_offset, "50")
|
||||
- project = local_assigns[:project]
|
||||
|
||||
%aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => affix_offset, "spy" => "affix", "always-show-toggle" => true }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' }
|
||||
%aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => affix_offset, "spy" => "affix", "always-show-toggle" => true }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite', 'aria-label': _('Milestone') }
|
||||
.issuable-sidebar.milestone-sidebar
|
||||
.block.milestone-progress.issuable-sidebar-header
|
||||
%a.gutter-toggle.float-right.js-sidebar-toggle.has-tooltip{ role: "button", href: "#", "aria-label" => s_('MilestoneSidebar|Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
- editing ||= false
|
||||
|
||||
%aside.right-sidebar.right-sidebar-expanded.wiki-sidebar.js-wiki-sidebar.js-right-sidebar{ data: { "offset-top" => "50", "spy" => "affix" } }
|
||||
%aside.right-sidebar.right-sidebar-expanded.wiki-sidebar.js-wiki-sidebar.js-right-sidebar{ data: { "offset-top" => "50", "spy" => "affix" }, 'aria-label': _('Wiki') }
|
||||
.sidebar-container
|
||||
.block.wiki-sidebar-header.gl-mb-3.w-100
|
||||
%a.gutter-toggle.float-right.d-block.d-md-none.js-sidebar-wiki-toggle{ href: "#" }
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Remove avatar of the blocked user
|
||||
merge_request: 52051
|
||||
author: Yogi (@yo)
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add site landmarks for screen readers
|
||||
merge_request: 52514
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix empty pipeline analytics charts when time_zone is non-UTC
|
||||
merge_request: 52971
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Replace erase job alert background color with color consistent with UI
|
||||
merge_request: 52810
|
||||
author:
|
||||
type: changed
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: import_requirements_csv
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48060
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/284846
|
||||
milestone: '13.7'
|
||||
type: development
|
||||
group: group::product planning
|
||||
default_enabled: true
|
|
@ -68,6 +68,8 @@ To create a new Auditor user:
|
|||
To revoke Auditor permissions from a user, make them a regular user by
|
||||
following the previous steps.
|
||||
|
||||
Additionally users can be set as an Auditor using [SAML groups](../integration/saml.md#auditor-groups).
|
||||
|
||||
## Permissions and restrictions of an Auditor user
|
||||
|
||||
An Auditor user should be able to access all projects and groups of a GitLab
|
||||
|
|
|
@ -307,37 +307,37 @@ Example response:
|
|||
"health_status": "Healthy",
|
||||
"missing_oauth_application": false,
|
||||
"attachments_count": 1,
|
||||
"attachments_synced_count": nil,
|
||||
"attachments_failed_count": nil,
|
||||
"attachments_synced_count": null,
|
||||
"attachments_failed_count": null,
|
||||
"attachments_synced_missing_on_primary_count": 0,
|
||||
"attachments_synced_in_percentage": "0.00%",
|
||||
"db_replication_lag_seconds": nil,
|
||||
"db_replication_lag_seconds": null,
|
||||
"lfs_objects_count": 0,
|
||||
"lfs_objects_synced_count": nil,
|
||||
"lfs_objects_failed_count": nil,
|
||||
"lfs_objects_synced_count": null,
|
||||
"lfs_objects_failed_count": null,
|
||||
"lfs_objects_synced_missing_on_primary_count": 0,
|
||||
"lfs_objects_synced_in_percentage": "0.00%",
|
||||
"job_artifacts_count": 2,
|
||||
"job_artifacts_synced_count": nil,
|
||||
"job_artifacts_failed_count": nil,
|
||||
"job_artifacts_synced_count": null,
|
||||
"job_artifacts_failed_count": null,
|
||||
"job_artifacts_synced_missing_on_primary_count": 0,
|
||||
"job_artifacts_synced_in_percentage": "0.00%",
|
||||
"container_repositories_count": 3,
|
||||
"container_repositories_synced_count": nil,
|
||||
"container_repositories_failed_count": nil,
|
||||
"container_repositories_synced_count": null,
|
||||
"container_repositories_failed_count": null,
|
||||
"container_repositories_synced_in_percentage": "0.00%",
|
||||
"design_repositories_count": 3,
|
||||
"design_repositories_synced_count": nil,
|
||||
"design_repositories_failed_count": nil,
|
||||
"design_repositories_synced_count": null,
|
||||
"design_repositories_failed_count": null,
|
||||
"design_repositories_synced_in_percentage": "0.00%",
|
||||
"projects_count": 41,
|
||||
"repositories_count": 41,
|
||||
"repositories_failed_count": nil,
|
||||
"repositories_synced_count": nil,
|
||||
"repositories_failed_count": null,
|
||||
"repositories_synced_count": null,
|
||||
"repositories_synced_in_percentage": "0.00%",
|
||||
"wikis_count": 41,
|
||||
"wikis_failed_count": nil,
|
||||
"wikis_synced_count": nil,
|
||||
"wikis_failed_count": null,
|
||||
"wikis_synced_count": null,
|
||||
"wikis_synced_in_percentage": "0.00%",
|
||||
"replication_slots_count": 1,
|
||||
"replication_slots_used_count": 1,
|
||||
|
@ -367,7 +367,7 @@ Example response:
|
|||
"repositories_checked_in_percentage": "17.07%",
|
||||
"last_event_id": 23,
|
||||
"last_event_timestamp": 1509681166,
|
||||
"cursor_last_event_id": nil,
|
||||
"cursor_last_event_id": null,
|
||||
"cursor_last_event_timestamp": 0,
|
||||
"last_successful_status_check_timestamp": 1510125024,
|
||||
"version": "10.3.0",
|
||||
|
@ -408,12 +408,12 @@ Example response:
|
|||
"job_artifacts_synced_missing_on_primary_count": 0,
|
||||
"job_artifacts_synced_in_percentage": "50.00%",
|
||||
"container_repositories_count": 3,
|
||||
"container_repositories_synced_count": nil,
|
||||
"container_repositories_failed_count": nil,
|
||||
"container_repositories_synced_count": null,
|
||||
"container_repositories_failed_count": null,
|
||||
"container_repositories_synced_in_percentage": "0.00%",
|
||||
"design_repositories_count": 3,
|
||||
"design_repositories_synced_count": nil,
|
||||
"design_repositories_failed_count": nil,
|
||||
"design_repositories_synced_count": null,
|
||||
"design_repositories_failed_count": null,
|
||||
"design_repositories_synced_in_percentage": "0.00%",
|
||||
"projects_count": 41,
|
||||
"repositories_count": 41,
|
||||
|
@ -424,10 +424,10 @@ Example response:
|
|||
"wikis_failed_count": 0,
|
||||
"wikis_synced_count": 41,
|
||||
"wikis_synced_in_percentage": "100.00%",
|
||||
"replication_slots_count": nil,
|
||||
"replication_slots_used_count": nil,
|
||||
"replication_slots_count": null,
|
||||
"replication_slots_used_count": null,
|
||||
"replication_slots_used_in_percentage": "0.00%",
|
||||
"replication_slots_max_retained_wal_bytes": nil,
|
||||
"replication_slots_max_retained_wal_bytes": null,
|
||||
"repositories_checksummed_count": 20,
|
||||
"repositories_checksum_failed_count": 5,
|
||||
"repositories_checksummed_in_percentage": "48.78%",
|
||||
|
@ -518,12 +518,12 @@ Example response:
|
|||
"job_artifacts_synced_missing_on_primary_count": 0,
|
||||
"job_artifacts_synced_in_percentage": "50.00%",
|
||||
"container_repositories_count": 3,
|
||||
"container_repositories_synced_count": nil,
|
||||
"container_repositories_failed_count": nil,
|
||||
"container_repositories_synced_count": null,
|
||||
"container_repositories_failed_count": null,
|
||||
"container_repositories_synced_in_percentage": "0.00%",
|
||||
"design_repositories_count": 3,
|
||||
"design_repositories_synced_count": nil,
|
||||
"design_repositories_failed_count": nil,
|
||||
"design_repositories_synced_count": null,
|
||||
"design_repositories_failed_count": null,
|
||||
"design_repositories_synced_in_percentage": "0.00%",
|
||||
"projects_count": 41,
|
||||
"repositories_count": 41,
|
||||
|
@ -534,10 +534,10 @@ Example response:
|
|||
"wikis_failed_count": 0,
|
||||
"wikis_synced_count": 41,
|
||||
"wikis_synced_in_percentage": "100.00%",
|
||||
"replication_slots_count": nil,
|
||||
"replication_slots_used_count": nil,
|
||||
"replication_slots_count": null,
|
||||
"replication_slots_used_count": null,
|
||||
"replication_slots_used_in_percentage": "0.00%",
|
||||
"replication_slots_max_retained_wal_bytes": nil,
|
||||
"replication_slots_max_retained_wal_bytes": null,
|
||||
"last_event_id": 23,
|
||||
"last_event_timestamp": 1509681166,
|
||||
"cursor_last_event_id": 23,
|
||||
|
|
|
@ -1779,7 +1779,7 @@ To add a tier badge to a heading, add the relevant [tier badge](#available-produ
|
|||
after the heading text. For example:
|
||||
|
||||
```markdown
|
||||
# Heading title `**(FREE)**`
|
||||
# Heading title **(FREE)**
|
||||
```
|
||||
|
||||
#### Product tier badges on other content
|
||||
|
|
|
@ -93,8 +93,8 @@ To execute documentation link tests locally:
|
|||
|
||||
### UI link tests
|
||||
|
||||
The `ui-docs-links lint` job uses `haml-lint` to test that all links to docs from
|
||||
UI elements (`app/views` files, for example) are linking to valid docs and anchors.
|
||||
The `ui-docs-links lint` job uses `haml-lint` to test that all documentation links from
|
||||
UI elements (`app/views` files, for example) are linking to valid pages and anchors.
|
||||
|
||||
To run the `ui-docs-links` test locally:
|
||||
|
||||
|
@ -156,12 +156,12 @@ markdownlint configuration is found in the following projects:
|
|||
- [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/.markdownlint.json)
|
||||
- [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/.markdownlint.json)
|
||||
|
||||
This configuration is also used within build pipelines.
|
||||
This configuration is also used in build pipelines.
|
||||
|
||||
You can use markdownlint:
|
||||
|
||||
- [On the command line](https://github.com/igorshubovych/markdownlint-cli#markdownlint-cli--).
|
||||
- [Within a code editor](#configure-editors).
|
||||
- [In a code editor](#configure-editors).
|
||||
- [In a `pre-push` hook](#configure-pre-push-hooks).
|
||||
|
||||
### Vale
|
||||
|
@ -172,10 +172,10 @@ English language. Vale's configuration is stored in the
|
|||
directory of projects.
|
||||
|
||||
Vale supports creating [custom tests](https://errata-ai.github.io/vale/styles/) that extend any of
|
||||
several types of checks, which we store in the `.linting/vale/styles/gitlab` directory within the
|
||||
several types of checks, which we store in the `.linting/vale/styles/gitlab` directory in the
|
||||
documentation directory of projects.
|
||||
|
||||
Vale configuration is found in the following projects:
|
||||
You can find Vale configuration in the following projects:
|
||||
|
||||
- [`gitlab`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/.vale/gitlab)
|
||||
- [`gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/master/docs/.vale/gitlab)
|
||||
|
@ -183,13 +183,13 @@ Vale configuration is found in the following projects:
|
|||
- [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/tree/master/doc/.vale/gitlab)
|
||||
- [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/master/doc/.vale/gitlab)
|
||||
|
||||
This configuration is also used within build pipelines, where
|
||||
This configuration is also used in build pipelines, where
|
||||
[error-level rules](#vale-result-types) are enforced.
|
||||
|
||||
You can use Vale:
|
||||
|
||||
- [On the command line](https://errata-ai.gitbook.io/vale/getting-started/usage).
|
||||
- [Within a code editor](#configure-editors).
|
||||
- [In a code editor](#configure-editors).
|
||||
- [In a Git hook](#configure-pre-push-hooks). Vale only reports errors in the Git hook (the same
|
||||
configuration as the CI/CD pipelines), and does not report suggestions or warnings.
|
||||
|
||||
|
@ -243,32 +243,40 @@ To match the versions of `markdownlint-cli` and `vale` used in the GitLab projec
|
|||
[versions used](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/.gitlab-ci.yml#L447)
|
||||
when building the `image:docs-lint-markdown` Docker image containing these tools for CI/CD.
|
||||
|
||||
| Tool | Version | Command | Additional information |
|
||||
|--------------------|----------|-------------------------------------------|------------------------|
|
||||
| `markdownlint-cli` | Latest | `yarn global add markdownlint-cli` | n/a |
|
||||
| Tool | Version | Command | Additional information |
|
||||
|--------------------|-----------|-------------------------------------------|------------------------|
|
||||
| `markdownlint-cli` | Latest | `yarn global add markdownlint-cli` | n/a |
|
||||
| `markdownlint-cli` | Specific | `yarn global add markdownlint-cli@0.23.2` | The `@` indicates a specific version, and this example updates the tool to version `0.23.2`. |
|
||||
| Vale | Latest | `brew update && brew upgrade vale` | This command is for macOS only. |
|
||||
| Vale | Specific | n/a | Not possible using `brew`, but can be [directly downloaded](https://github.com/errata-ai/vale/releases). |
|
||||
| Vale | Latest | `brew update && brew upgrade vale` | This command is for macOS only. |
|
||||
| Vale | Specific | n/a | Not possible using `brew`, but can be [directly downloaded](https://github.com/errata-ai/vale/releases). |
|
||||
|
||||
### Configure editors
|
||||
|
||||
Using linters in your editor is more convenient than having to run the commands from the
|
||||
command line.
|
||||
|
||||
To configure markdownlint within your editor, install one of the following as appropriate:
|
||||
To configure markdownlint in your editor, install one of the following as appropriate:
|
||||
|
||||
- [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint)
|
||||
- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint)
|
||||
- [Atom](https://atom.io/packages/linter-node-markdownlint)
|
||||
- [Vim](https://github.com/dense-analysis/ale)
|
||||
- Sublime Text [`SublimeLinter-contrib-markdownlint` package](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint).
|
||||
- Visual Studio Code [`DavidAnson.vscode-markdownlint` extension](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint).
|
||||
- Atom [`linter-node-markdownlint` package](https://atom.io/packages/linter-node-markdownlint).
|
||||
- Vim [ALE plugin](https://github.com/dense-analysis/ale).
|
||||
|
||||
To configure Vale within your editor, install one of the following as appropriate:
|
||||
To configure Vale in your editor, install one of the following as appropriate:
|
||||
|
||||
- The Sublime Text [`SublimeLinter-contrib-vale` plugin](https://packagecontrol.io/packages/SublimeLinter-contrib-vale).
|
||||
- The Visual Studio Code [`errata-ai.vale-server` extension](https://marketplace.visualstudio.com/items?itemName=errata-ai.vale-server).
|
||||
You don't need Vale Server to use the plugin. You can configure the plugin to
|
||||
- Sublime Text [`SublimeLinter-contrib-vale` package](https://packagecontrol.io/packages/SublimeLinter-contrib-vale).
|
||||
- Visual Studio Code [`errata-ai.vale-server` extension](https://marketplace.visualstudio.com/items?itemName=errata-ai.vale-server).
|
||||
You can configure the plugin to
|
||||
[display only a subset of alerts](#show-subset-of-vale-alerts).
|
||||
- [Vim](https://github.com/dense-analysis/ale).
|
||||
|
||||
In the extension's settings:
|
||||
|
||||
- Select the **Use CLI** checkbox.
|
||||
- In the **Config** setting, enter an absolute path to [`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/blob/master/.vale.ini) in one of the cloned GitLab repositories on your computer.
|
||||
- In the **Path** setting, enter the absolute path to the Vale binary. In most
|
||||
cases, `vale` should work. To find the location, run `which vale` in a terminal.
|
||||
|
||||
- Vim [ALE plugin](https://github.com/dense-analysis/ale).
|
||||
|
||||
We don't use [Vale Server](https://errata-ai.github.io/vale/#using-vale-with-a-text-editor-or-another-third-party-application).
|
||||
|
||||
|
|
|
@ -163,7 +163,9 @@ will be returned to GitLab and will be signed in.
|
|||
|
||||
## SAML Groups
|
||||
|
||||
You can require users to be members of a certain group, or assign users `external`, `admin` or `auditor` roles based on group membership. This feature **does not** allow you to
|
||||
You can require users to be members of a certain group, or assign users [external](../user/permissions.md#external-users), admin or [auditor](../user/permissions.md#auditor-users) roles based on group membership.
|
||||
These groups are checked on each SAML login and user attributes updated as necessary.
|
||||
This feature **does not** allow you to
|
||||
automatically add users to GitLab [Groups](../user/group/index.md).
|
||||
|
||||
### Requirements
|
||||
|
@ -215,7 +217,7 @@ Example:
|
|||
|
||||
### External groups **(PREMIUM SELF)**
|
||||
|
||||
SAML login supports automatic identification on whether a user should be considered an [external](../user/permissions.md) user. This is based on the user's group membership in the SAML identity provider.
|
||||
SAML login supports automatic identification on whether a user should be considered an [external user](../user/permissions.md#external-users). This is based on the user's group membership in the SAML identity provider.
|
||||
|
||||
```yaml
|
||||
{ name: 'saml',
|
||||
|
@ -257,7 +259,7 @@ considered admin users.
|
|||
|
||||
The requirements are the same as the previous settings, your IdP needs to pass Group information to GitLab, you need to tell
|
||||
GitLab where to look for the groups in the SAML response, and which group(s) should be
|
||||
considered auditor users.
|
||||
considered [auditor users](../user/permissions.md#auditor-users).
|
||||
|
||||
```yaml
|
||||
{ name: 'saml',
|
||||
|
@ -385,7 +387,7 @@ This setting should be used only to map attributes that are part of the OmniAuth
|
|||
`attribute_statements` is used to map Attribute Names in a SAMLResponse to entries
|
||||
in the OmniAuth [`info` hash](https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema#schema-10-and-later).
|
||||
|
||||
For example, if your SAMLResponse contains an Attribute called 'EmailAddress',
|
||||
For example, if your SAMLResponse contains an Attribute called `EmailAddress`,
|
||||
specify `{ email: ['EmailAddress'] }` to map the Attribute to the
|
||||
corresponding key in the `info` hash. URI-named Attributes are also supported, e.g.
|
||||
`{ email: ['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'] }`.
|
||||
|
@ -582,8 +584,8 @@ GitLab will sign the request with the provided private key. GitLab will include
|
|||
|
||||
Avoid user control of the following attributes:
|
||||
|
||||
- [`*NameID*`](../user/group/saml_sso/index.md#nameid)
|
||||
- *Email* when used with `omniauth_auto_link_saml_user`
|
||||
- [`NameID`](../user/group/saml_sso/index.md#nameid)
|
||||
- `Email` when used with `omniauth_auto_link_saml_user`
|
||||
|
||||
These attributes define the SAML user. If users can change these attributes, they can impersonate others.
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ variables:
|
|||
# If not using GitLab's HTTP backend, remove this line and specify TF_HTTP_* variables
|
||||
TF_STATE_NAME: default
|
||||
TF_CACHE_KEY: default
|
||||
# If your terraform files are in a subdirectory, set TF_ROOT accordingly
|
||||
# TF_ROOT: terraform/production
|
||||
```
|
||||
|
||||
This template uses `.latest.`, instead of stable, and may include breaking changes.
|
||||
|
@ -39,6 +41,15 @@ This template also includes some opinionated decisions, which you can override:
|
|||
[run the Terraform commands](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml)
|
||||
`init`, `validate`, `plan`, `plan-json`, and `apply`. The `apply` command only runs on `master`.
|
||||
|
||||
This video from January 2021 walks you through all the GitLab Terraform integration features:
|
||||
|
||||
<div class="video-fallback">
|
||||
See the video: <a href="https://www.youtube.com/watch?v=iGXjUrkkzDI">Terraform with GitLab</a>.
|
||||
</div>
|
||||
<figure class="video-container">
|
||||
<iframe src="https://www.youtube.com/embed/iGXjUrkkzDI" frameborder="0" allowfullscreen="true"> </iframe>
|
||||
</figure>
|
||||
|
||||
## GitLab Managed Terraform state
|
||||
|
||||
[Terraform remote backends](https://www.terraform.io/docs/backends/index.html)
|
||||
|
|
|
@ -352,6 +352,9 @@ An administrator can flag a user as external by either of the following methods:
|
|||
or edit an existing one. There, you can find the option to flag the user as
|
||||
external.
|
||||
|
||||
Additionally users can be set as external users using [SAML groups](../integration/saml.md#external-groups)
|
||||
and [LDAP groups](../administration/auth/ldap/index.md#external-groups).
|
||||
|
||||
### Setting new users to external
|
||||
|
||||
By default, new users are not set as external users. This behavior can be changed
|
||||
|
|
|
@ -145,7 +145,7 @@ whitespace changes.
|
|||
|
||||
## Mark files as viewed
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51513) in GitLab 13.8.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51513) in GitLab 13.9.
|
||||
> - It's deployed behind a feature flag, enabled by default.
|
||||
> - It's enabled on GitLab.com.
|
||||
> - It's recommended for production use.
|
||||
|
|
|
@ -21,13 +21,17 @@ By default, a protected branch does these things:
|
|||
- It prevents **anyone** from force pushing to the branch.
|
||||
- It prevents **anyone** from deleting the branch.
|
||||
|
||||
NOTE:
|
||||
A GitLab administrator is allowed to push to the protected branches.
|
||||
**Permissions:**
|
||||
|
||||
See the [Changelog](#changelog) section for changes over time.
|
||||
- GitLab administrators are allowed to push to the protected branches.
|
||||
- Users with [Developer permissions](../permissions.md) are allowed to
|
||||
create a project in a group, but might not be allowed to initially
|
||||
push to the [default branch](repository/branches/index.md#default-branch).
|
||||
|
||||
The default branch protection level is set in the [Admin Area](../admin_area/settings/visibility_and_access_controls.md#default-branch-protection).
|
||||
|
||||
See the [Changelog](#changelog) section for changes over time.
|
||||
|
||||
## Configuring protected branches
|
||||
|
||||
To protect a branch, you need to have at least Maintainer permission level.
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# See Usage Ping metrics dictionary docs https://docs.gitlab.com/ee/development/usage_ping/metrics_dictionary.html
|
||||
key_path: <%= key_path %>
|
||||
value_type:
|
||||
product_category:
|
||||
stage:
|
||||
status:
|
||||
milestone:
|
||||
introduced_by_url:
|
||||
group:
|
||||
time_frame: <%= time_frame %>
|
||||
data_source:
|
||||
distribution: <%= distribution %>
|
||||
# tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold']
|
||||
tier:
|
|
@ -0,0 +1,78 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails/generators'
|
||||
|
||||
module Gitlab
|
||||
class UsageMetricDefinitionGenerator < Rails::Generators::Base
|
||||
Directory = Struct.new(:name, :time_frame) do
|
||||
def match?(str)
|
||||
(name == str || time_frame == str) && str != 'none'
|
||||
end
|
||||
end
|
||||
|
||||
TIME_FRAME_DIRS = [
|
||||
Directory.new('counts_7d', '7d'),
|
||||
Directory.new('counts_28d', '28d'),
|
||||
Directory.new('counts_all', 'all'),
|
||||
Directory.new('settings', 'none'),
|
||||
Directory.new('license', 'none')
|
||||
].freeze
|
||||
|
||||
VALID_INPUT_DIRS = (TIME_FRAME_DIRS.flat_map { |d| [d.name, d.time_frame] } - %w(none)).freeze
|
||||
|
||||
source_root File.expand_path('../../../generator_templates/usage_metric_definition', __dir__)
|
||||
|
||||
desc 'Generates a metric definition yml file'
|
||||
|
||||
class_option :ee, type: :boolean, optional: true, default: false, desc: 'Indicates if metric is for ee'
|
||||
class_option :dir,
|
||||
type: :string, desc: "Indicates the metric location. It must be one of: #{VALID_INPUT_DIRS.join(', ')}"
|
||||
|
||||
argument :key_path, type: :string, desc: 'Unique JSON key path for the metric'
|
||||
|
||||
def create_metric_file
|
||||
validate!
|
||||
|
||||
template "metric_definition.yml", file_path
|
||||
end
|
||||
|
||||
def time_frame
|
||||
directory&.time_frame
|
||||
end
|
||||
|
||||
def distribution
|
||||
value = ['ce']
|
||||
value << 'ee' if ee?
|
||||
value
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def file_path
|
||||
path = File.join('config', 'metrics', directory&.name, "#{file_name}.yml")
|
||||
path = File.join('ee', path) if ee?
|
||||
path
|
||||
end
|
||||
|
||||
def validate!
|
||||
raise "--dir option is required" unless input_dir.present?
|
||||
raise "Invalid dir #{input_dir}, allowed options are #{VALID_INPUT_DIRS.join(', ')}" unless directory.present?
|
||||
end
|
||||
|
||||
def ee?
|
||||
options[:ee]
|
||||
end
|
||||
|
||||
def input_dir
|
||||
options[:dir]
|
||||
end
|
||||
|
||||
def file_name
|
||||
key_path.split('.').last
|
||||
end
|
||||
|
||||
def directory
|
||||
@directory ||= TIME_FRAME_DIRS.find { |d| d.match?(input_dir) }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,6 +6,7 @@ module Gitlab
|
|||
module Models
|
||||
# isolated Namespace model
|
||||
class Namespace < ApplicationRecord
|
||||
include FeatureGate
|
||||
include ::Gitlab::VisibilityLevel
|
||||
include ::Gitlab::Utils::StrongMemoize
|
||||
include Gitlab::BackgroundMigration::UserMentions::Models::Concerns::Namespace::RecursiveTraversal
|
||||
|
|
|
@ -31,9 +31,10 @@ module Gitlab
|
|||
|
||||
current = @from
|
||||
while current <= @to
|
||||
@labels << current.strftime(@format)
|
||||
@total << (totals_count[current] || 0)
|
||||
@success << (success_count[current] || 0)
|
||||
label = current.strftime(@format)
|
||||
@labels << label
|
||||
@total << (totals_count[label] || 0)
|
||||
@success << (success_count[label] || 0)
|
||||
|
||||
current += interval_step
|
||||
end
|
||||
|
@ -45,6 +46,7 @@ module Gitlab
|
|||
query
|
||||
.group("date_trunc('#{interval}', #{::Ci::Pipeline.table_name}.created_at)")
|
||||
.count(:created_at)
|
||||
.transform_keys { |date| date.strftime(@format) }
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Ci
|
||||
module Reports
|
||||
class CodequalityMrDiff
|
||||
attr_reader :files
|
||||
|
||||
def initialize(raw_report)
|
||||
@raw_report = raw_report
|
||||
@files = {}
|
||||
build_report!
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_report!
|
||||
codequality_files = @raw_report.all_degradations.each_with_object({}) do |degradation, codequality_files|
|
||||
unless codequality_files[degradation.dig(:location, :path)].present?
|
||||
codequality_files[degradation.dig(:location, :path)] = []
|
||||
end
|
||||
|
||||
build_mr_diff_payload(codequality_files, degradation)
|
||||
end
|
||||
|
||||
@files = codequality_files
|
||||
end
|
||||
|
||||
def build_mr_diff_payload(codequality_files, degradation)
|
||||
codequality_files[degradation.dig(:location, :path)] << {
|
||||
line: degradation.dig(:location, :lines, :begin) || degradation.dig(:location, :positions, :begin, :line),
|
||||
description: degradation[:description],
|
||||
severity: degradation[:severity]
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -8,9 +8,9 @@ module Rouge
|
|||
# Creates a new <tt>Rouge::Formatter::HTMLGitlab</tt> instance.
|
||||
#
|
||||
# [+tag+] The tag (language) of the lexer used to generate the formatted tokens
|
||||
def initialize(tag: nil)
|
||||
def initialize(options = {})
|
||||
@line_number = 1
|
||||
@tag = tag
|
||||
@tag = options[:tag]
|
||||
end
|
||||
|
||||
def stream(tokens)
|
||||
|
|
|
@ -1905,6 +1905,9 @@ msgstr ""
|
|||
msgid "Admin mode enabled"
|
||||
msgstr ""
|
||||
|
||||
msgid "Admin navigation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Admin notes"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4656,6 +4659,9 @@ msgstr ""
|
|||
msgid "Boards|An error occurred while updating the list. Please try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "Boards|Board"
|
||||
msgstr ""
|
||||
|
||||
msgid "Boards|Collapse"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4851,6 +4857,9 @@ msgstr ""
|
|||
msgid "Branches|protected"
|
||||
msgstr ""
|
||||
|
||||
msgid "Breadcrumbs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Brief title about the change"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4890,6 +4899,9 @@ msgstr ""
|
|||
msgid "Bulk request concurrency"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bulk update"
|
||||
msgstr ""
|
||||
|
||||
msgid "BulkImport|From source group"
|
||||
msgstr ""
|
||||
|
||||
|
@ -8904,7 +8916,7 @@ msgstr ""
|
|||
msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
|
||||
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
|
||||
msgstr ""
|
||||
|
||||
msgid "DastProfiles|A passive scan monitors all HTTP messages (requests and responses) sent to the target. An active scan attacks the target to find potential vulnerabilities."
|
||||
|
@ -13876,6 +13888,9 @@ msgstr ""
|
|||
msgid "Group name (your organization)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Group navigation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Group overview"
|
||||
msgstr ""
|
||||
|
||||
|
@ -16723,7 +16738,7 @@ msgstr ""
|
|||
msgid "Job|Job has been erased"
|
||||
msgstr ""
|
||||
|
||||
msgid "Job|Job has been erased by"
|
||||
msgid "Job|Job has been erased by %{userLink}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Job|Keep"
|
||||
|
@ -20507,7 +20522,7 @@ msgstr ""
|
|||
msgid "One or more of your personal access tokens will expire in %{days_to_expire} days or less."
|
||||
msgstr ""
|
||||
|
||||
msgid "Only 'Reporter' roles and above on tiers Premium / Silver and above can see Value Stream Analytics."
|
||||
msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
|
||||
msgstr ""
|
||||
|
||||
msgid "Only 1 appearances row can exist"
|
||||
|
@ -20543,7 +20558,7 @@ msgstr ""
|
|||
msgid "Only verified users with an email address in any of these domains can be added to the group."
|
||||
msgstr ""
|
||||
|
||||
msgid "Only ‘Reporter’ roles and above on tiers Premium / Silver and above can see Productivity Analytics."
|
||||
msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
|
||||
msgstr ""
|
||||
|
||||
msgid "Oops, are you sure?"
|
||||
|
@ -22613,6 +22628,9 @@ msgstr ""
|
|||
msgid "Project name suffix"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project navigation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project order will not be saved as local storage is not available."
|
||||
msgstr ""
|
||||
|
||||
|
@ -25595,6 +25613,9 @@ msgstr ""
|
|||
msgid "Security dashboard"
|
||||
msgstr ""
|
||||
|
||||
msgid "Security navigation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Security report is out of date. Please update your branch with the latest changes from the target branch (%{targetBranchName})"
|
||||
msgstr ""
|
||||
|
||||
|
@ -27710,6 +27731,9 @@ msgstr ""
|
|||
msgid "Subgroup milestone"
|
||||
msgstr ""
|
||||
|
||||
msgid "Subgroup navigation"
|
||||
msgstr ""
|
||||
|
||||
msgid "Subgroup overview"
|
||||
msgstr ""
|
||||
|
||||
|
@ -30322,7 +30346,7 @@ msgstr ""
|
|||
msgid "To see all the user's personal access tokens you must impersonate them first."
|
||||
msgstr ""
|
||||
|
||||
msgid "To see this project's operational details, %{linkStart}upgrade its group plan to Silver%{linkEnd}. You can also remove the project from the dashboard."
|
||||
msgid "To see this project's operational details, %{linkStart}upgrade its group plan to Premium%{linkEnd}. You can also remove the project from the dashboard."
|
||||
msgstr ""
|
||||
|
||||
msgid "To see this project's operational details, contact an owner of group %{groupName} to upgrade the plan. You can also remove the project from the dashboard."
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :codequality_degradation_1, class: Hash do
|
||||
skip_create
|
||||
|
||||
initialize_with do
|
||||
{
|
||||
"categories": [
|
||||
"Complexity"
|
||||
],
|
||||
"check_name": "argument_count",
|
||||
"content": {
|
||||
"body": ""
|
||||
},
|
||||
"description": "Avoid parameter lists longer than 5 parameters. [12/5]",
|
||||
"fingerprint": "15cdb5c53afd42bc22f8ca366a08d547",
|
||||
"location": {
|
||||
"path": "file_a.rb",
|
||||
"lines": {
|
||||
"begin": 10,
|
||||
"end": 10
|
||||
}
|
||||
},
|
||||
"other_locations": [],
|
||||
"remediation_points": 900000,
|
||||
"severity": "major",
|
||||
"type": "issue",
|
||||
"engine_name": "structure"
|
||||
}.with_indifferent_access
|
||||
end
|
||||
end
|
||||
|
||||
factory :codequality_degradation_2, class: Hash do
|
||||
skip_create
|
||||
|
||||
initialize_with do
|
||||
{
|
||||
"categories": [
|
||||
"Complexity"
|
||||
],
|
||||
"check_name": "argument_count",
|
||||
"content": {
|
||||
"body": ""
|
||||
},
|
||||
"description": "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.",
|
||||
"fingerprint": "f3bdc1e8c102ba5fbd9e7f6cda51c95e",
|
||||
"location": {
|
||||
"path": "file_a.rb",
|
||||
"lines": {
|
||||
"begin": 10,
|
||||
"end": 10
|
||||
}
|
||||
},
|
||||
"other_locations": [],
|
||||
"remediation_points": 900000,
|
||||
"severity": "major",
|
||||
"type": "issue",
|
||||
"engine_name": "structure"
|
||||
}.with_indifferent_access
|
||||
end
|
||||
end
|
||||
|
||||
factory :codequality_degradation_3, class: Hash do
|
||||
skip_create
|
||||
|
||||
initialize_with do
|
||||
{
|
||||
"type": "Issue",
|
||||
"check_name": "Rubocop/Metrics/ParameterLists",
|
||||
"description": "Avoid parameter lists longer than 5 parameters. [12/5]",
|
||||
"categories": [
|
||||
"Complexity"
|
||||
],
|
||||
"remediation_points": 550000,
|
||||
"location": {
|
||||
"path": "file_b.rb",
|
||||
"positions": {
|
||||
"begin": {
|
||||
"column": 14,
|
||||
"line": 10
|
||||
},
|
||||
"end": {
|
||||
"column": 39,
|
||||
"line": 10
|
||||
}
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"body": "This cop checks for methods with too many parameters.\nThe maximum number of parameters is configurable.\nKeyword arguments can optionally be excluded from the total count."
|
||||
},
|
||||
"engine_name": "rubocop",
|
||||
"fingerprint": "ab5f8b935886b942d621399f5a2ca16e",
|
||||
"severity": "minor"
|
||||
}.with_indifferent_access
|
||||
end
|
||||
end
|
||||
end
|
|
@ -54,7 +54,7 @@ RSpec.describe 'Admin Groups' do
|
|||
click_button "Create group"
|
||||
|
||||
expect(current_path).to eq admin_group_path(Group.find_by(path: path_component))
|
||||
content = page.find('div#content-body')
|
||||
content = page.find('#content-body')
|
||||
h3_texts = content.all('h3').collect(&:text).join("\n")
|
||||
expect(h3_texts).to match group_name
|
||||
li_texts = content.all('li').collect(&:text).join("\n")
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"type": "object",
|
||||
"description": "The schema used to display codequality report in mr diff",
|
||||
"required": ["files"],
|
||||
"properties": {
|
||||
"patternProperties": {
|
||||
".*.": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"required": ["line", "description", "severity"],
|
||||
"properties": {
|
||||
"line": { "type": "integer" },
|
||||
"description": { "type": "string" },
|
||||
"severity": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,8 @@ describe('Erased block', () => {
|
|||
const timeago = getTimeago();
|
||||
const formattedDate = timeago.format(erasedAt);
|
||||
|
||||
const findLink = () => wrapper.find(GlLink);
|
||||
|
||||
const createComponent = (props) => {
|
||||
wrapper = mount(ErasedBlock, {
|
||||
propsData: props,
|
||||
|
@ -32,7 +34,7 @@ describe('Erased block', () => {
|
|||
});
|
||||
|
||||
it('renders username and link', () => {
|
||||
expect(wrapper.find(GlLink).attributes('href')).toEqual('gitlab.com/root');
|
||||
expect(findLink().attributes('href')).toEqual('gitlab.com/root');
|
||||
|
||||
expect(wrapper.text().trim()).toContain('Job has been erased by');
|
||||
expect(wrapper.text().trim()).toContain('root');
|
||||
|
|
|
@ -618,9 +618,12 @@ describe('nDaysAfter', () => {
|
|||
${-1} | ${new Date('2019-07-15T00:00:00.000Z').valueOf()}
|
||||
${0} | ${date.valueOf()}
|
||||
${0.9} | ${date.valueOf()}
|
||||
`('returns $numberOfDays day(s) after the provided date', ({ numberOfDays, expectedResult }) => {
|
||||
expect(datetimeUtility.nDaysAfter(date, numberOfDays)).toBe(expectedResult);
|
||||
});
|
||||
`(
|
||||
'returns the date $numberOfDays day(s) after the provided date',
|
||||
({ numberOfDays, expectedResult }) => {
|
||||
expect(datetimeUtility.nDaysAfter(date, numberOfDays)).toBe(expectedResult);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('nDaysBefore', () => {
|
||||
|
@ -633,9 +636,48 @@ describe('nDaysBefore', () => {
|
|||
${-1} | ${new Date('2019-07-17T00:00:00.000Z').valueOf()}
|
||||
${0} | ${date.valueOf()}
|
||||
${0.9} | ${new Date('2019-07-15T00:00:00.000Z').valueOf()}
|
||||
`('returns $numberOfDays day(s) before the provided date', ({ numberOfDays, expectedResult }) => {
|
||||
expect(datetimeUtility.nDaysBefore(date, numberOfDays)).toBe(expectedResult);
|
||||
});
|
||||
`(
|
||||
'returns the date $numberOfDays day(s) before the provided date',
|
||||
({ numberOfDays, expectedResult }) => {
|
||||
expect(datetimeUtility.nDaysBefore(date, numberOfDays)).toBe(expectedResult);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('nWeeksAfter', () => {
|
||||
const date = new Date('2021-07-16T00:00:00.000Z');
|
||||
|
||||
it.each`
|
||||
numberOfWeeks | expectedResult
|
||||
${1} | ${new Date('2021-07-23T00:00:00.000Z').valueOf()}
|
||||
${3} | ${new Date('2021-08-06T00:00:00.000Z').valueOf()}
|
||||
${-1} | ${new Date('2021-07-09T00:00:00.000Z').valueOf()}
|
||||
${0} | ${date.valueOf()}
|
||||
${0.6} | ${new Date('2021-07-20T00:00:00.000Z').valueOf()}
|
||||
`(
|
||||
'returns the date $numberOfWeeks week(s) after the provided date',
|
||||
({ numberOfWeeks, expectedResult }) => {
|
||||
expect(datetimeUtility.nWeeksAfter(date, numberOfWeeks)).toBe(expectedResult);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('nWeeksBefore', () => {
|
||||
const date = new Date('2021-07-16T00:00:00.000Z');
|
||||
|
||||
it.each`
|
||||
numberOfWeeks | expectedResult
|
||||
${1} | ${new Date('2021-07-09T00:00:00.000Z').valueOf()}
|
||||
${3} | ${new Date('2021-06-25T00:00:00.000Z').valueOf()}
|
||||
${-1} | ${new Date('2021-07-23T00:00:00.000Z').valueOf()}
|
||||
${0} | ${date.valueOf()}
|
||||
${0.6} | ${new Date('2021-07-11T00:00:00.000Z').valueOf()}
|
||||
`(
|
||||
'returns the date $numberOfWeeks week(s) before the provided date',
|
||||
({ numberOfWeeks, expectedResult }) => {
|
||||
expect(datetimeUtility.nWeeksBefore(date, numberOfWeeks)).toBe(expectedResult);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('nMonthsAfter', () => {
|
||||
|
@ -659,7 +701,7 @@ describe('nMonthsAfter', () => {
|
|||
${may2020} | ${0} | ${may2020.valueOf()}
|
||||
${may2020} | ${0.9} | ${may2020.valueOf()}
|
||||
`(
|
||||
'returns $numberOfMonths month(s) after the provided date',
|
||||
'returns the date $numberOfMonths month(s) after the provided date',
|
||||
({ date, numberOfMonths, expectedResult }) => {
|
||||
expect(datetimeUtility.nMonthsAfter(date, numberOfMonths)).toBe(expectedResult);
|
||||
},
|
||||
|
@ -687,7 +729,7 @@ describe('nMonthsBefore', () => {
|
|||
${june2020} | ${0} | ${june2020.valueOf()}
|
||||
${june2020} | ${0.9} | ${new Date('2020-05-15T00:00:00.000Z').valueOf()}
|
||||
`(
|
||||
'returns $numberOfMonths month(s) before the provided date',
|
||||
'returns the date $numberOfMonths month(s) before the provided date',
|
||||
({ date, numberOfMonths, expectedResult }) => {
|
||||
expect(datetimeUtility.nMonthsBefore(date, numberOfMonths)).toBe(expectedResult);
|
||||
},
|
||||
|
@ -898,3 +940,14 @@ describe('getOverlapDateInPeriods', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isToday', () => {
|
||||
const today = new Date();
|
||||
it.each`
|
||||
date | expected | negation
|
||||
${today} | ${true} | ${'is'}
|
||||
${new Date('2021-01-21T12:00:00.000Z')} | ${false} | ${'is NOT'}
|
||||
`('returns $expected as $date $negation today', ({ date, expected }) => {
|
||||
expect(datetimeUtility.isToday(date)).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -135,15 +135,6 @@ RSpec.describe AvatarsHelper do
|
|||
helper.avatar_icon_for_user(nil, 20, 2)
|
||||
end
|
||||
end
|
||||
|
||||
context 'for a blocked user' do
|
||||
let(:user) { create(:user, :blocked) }
|
||||
|
||||
it 'returns the default avatar' do
|
||||
expect(helper.avatar_icon_for_user(user).to_s)
|
||||
.to eq(helper.default_avatar)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#gravatar_icon' do
|
||||
|
|
|
@ -9,6 +9,10 @@ RSpec.describe Gitlab::Ci::Charts do
|
|||
|
||||
subject { chart.to }
|
||||
|
||||
before do
|
||||
create(:ci_empty_pipeline, project: project, duration: 120)
|
||||
end
|
||||
|
||||
it 'goes until the end of the current month (including the whole last day of the month)' do
|
||||
is_expected.to eq(Date.today.end_of_month.end_of_day)
|
||||
end
|
||||
|
@ -20,6 +24,10 @@ RSpec.describe Gitlab::Ci::Charts do
|
|||
it 'uses %B %Y as labels format' do
|
||||
expect(chart.labels).to include(chart.from.strftime('%B %Y'))
|
||||
end
|
||||
|
||||
it 'returns count of pipelines run each day in the current year' do
|
||||
expect(chart.total.sum).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'monthchart' do
|
||||
|
@ -28,6 +36,10 @@ RSpec.describe Gitlab::Ci::Charts do
|
|||
|
||||
subject { chart.to }
|
||||
|
||||
before do
|
||||
create(:ci_empty_pipeline, project: project, duration: 120)
|
||||
end
|
||||
|
||||
it 'includes the whole current day' do
|
||||
is_expected.to eq(Date.today.end_of_day)
|
||||
end
|
||||
|
@ -39,6 +51,10 @@ RSpec.describe Gitlab::Ci::Charts do
|
|||
it 'uses %d %B as labels format' do
|
||||
expect(chart.labels).to include(chart.from.strftime('%d %B'))
|
||||
end
|
||||
|
||||
it 'returns count of pipelines run each day in the current month' do
|
||||
expect(chart.total.sum).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'weekchart' do
|
||||
|
@ -47,6 +63,10 @@ RSpec.describe Gitlab::Ci::Charts do
|
|||
|
||||
subject { chart.to }
|
||||
|
||||
before do
|
||||
create(:ci_empty_pipeline, project: project, duration: 120)
|
||||
end
|
||||
|
||||
it 'includes the whole current day' do
|
||||
is_expected.to eq(Date.today.end_of_day)
|
||||
end
|
||||
|
@ -58,6 +78,68 @@ RSpec.describe Gitlab::Ci::Charts do
|
|||
it 'uses %d %B as labels format' do
|
||||
expect(chart.labels).to include(chart.from.strftime('%d %B'))
|
||||
end
|
||||
|
||||
it 'returns count of pipelines run each day in the current week' do
|
||||
expect(chart.total.sum).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'weekchart_utc' do
|
||||
today = Date.today
|
||||
end_of_today = Time.use_zone(Time.find_zone('UTC')) { today.end_of_day }
|
||||
|
||||
let(:project) { create(:project) }
|
||||
let(:chart) do
|
||||
allow(Date).to receive(:today).and_return(today)
|
||||
allow(today).to receive(:end_of_day).and_return(end_of_today)
|
||||
Gitlab::Ci::Charts::WeekChart.new(project)
|
||||
end
|
||||
|
||||
subject { chart.total }
|
||||
|
||||
before do
|
||||
create(:ci_empty_pipeline, project: project, duration: 120)
|
||||
end
|
||||
|
||||
it 'uses a utc time zone for range times' do
|
||||
expect(chart.to.zone).to eq(end_of_today.zone)
|
||||
expect(chart.from.zone).to eq(end_of_today.zone)
|
||||
end
|
||||
|
||||
it 'returns count of pipelines run each day in the current week' do
|
||||
expect(chart.total.sum).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'weekchart_non_utc' do
|
||||
today = Date.today
|
||||
end_of_today = Time.use_zone(Time.find_zone('Asia/Dubai')) { today.end_of_day }
|
||||
|
||||
let(:project) { create(:project) }
|
||||
let(:chart) do
|
||||
allow(Date).to receive(:today).and_return(today)
|
||||
allow(today).to receive(:end_of_day).and_return(end_of_today)
|
||||
Gitlab::Ci::Charts::WeekChart.new(project)
|
||||
end
|
||||
|
||||
subject { chart.total }
|
||||
|
||||
before do
|
||||
# The DB uses UTC always, so our use of a Time Zone in the application
|
||||
# can cause the creation date of the pipeline to go unmatched depending
|
||||
# on the offset. We can work around this by requesting the pipeline be
|
||||
# created a with the `created_at` field set to a day ago in the same week.
|
||||
create(:ci_empty_pipeline, project: project, duration: 120, created_at: today - 1.day)
|
||||
end
|
||||
|
||||
it 'uses a non-utc time zone for range times' do
|
||||
expect(chart.to.zone).to eq(end_of_today.zone)
|
||||
expect(chart.from.zone).to eq(end_of_today.zone)
|
||||
end
|
||||
|
||||
it 'returns count of pipelines run each day in the current week' do
|
||||
expect(chart.total.sum).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'pipeline_times' do
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Ci::Reports::CodequalityMrDiff do
|
||||
let(:codequality_report) { Gitlab::Ci::Reports::CodequalityReports.new }
|
||||
let(:degradation_1) { build(:codequality_degradation_1) }
|
||||
let(:degradation_2) { build(:codequality_degradation_2) }
|
||||
let(:degradation_3) { build(:codequality_degradation_3) }
|
||||
|
||||
describe '#initialize!' do
|
||||
subject(:report) { described_class.new(codequality_report) }
|
||||
|
||||
context 'when quality has degradations' do
|
||||
context 'with several degradations on the same line' do
|
||||
before do
|
||||
codequality_report.add_degradation(degradation_1)
|
||||
codequality_report.add_degradation(degradation_2)
|
||||
end
|
||||
|
||||
it 'generates quality report for mr diff' do
|
||||
expect(report.files).to match(
|
||||
"file_a.rb" => [
|
||||
{ line: 10, description: "Avoid parameter lists longer than 5 parameters. [12/5]", severity: "major" },
|
||||
{ line: 10, description: "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.", severity: "major" }
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with several degradations on several files' do
|
||||
before do
|
||||
codequality_report.add_degradation(degradation_1)
|
||||
codequality_report.add_degradation(degradation_2)
|
||||
codequality_report.add_degradation(degradation_3)
|
||||
end
|
||||
|
||||
it 'returns quality report for mr diff' do
|
||||
expect(report.files).to match(
|
||||
"file_a.rb" => [
|
||||
{ line: 10, description: "Avoid parameter lists longer than 5 parameters. [12/5]", severity: "major" },
|
||||
{ line: 10, description: "Method `new_array` has 12 arguments (exceeds 4 allowed). Consider refactoring.", severity: "major" }
|
||||
],
|
||||
"file_b.rb" => [
|
||||
{ line: 10, description: "Avoid parameter lists longer than 5 parameters. [12/5]", severity: "minor" }
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when quality has no degradation' do
|
||||
it 'returns an empty hash' do
|
||||
expect(report.files).to match({})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -545,7 +545,7 @@ project:
|
|||
- daily_build_group_report_results
|
||||
- jira_imports
|
||||
- compliance_framework_setting
|
||||
- compliance_management_frameworks
|
||||
- compliance_management_framework
|
||||
- metrics_users_starred_dashboards
|
||||
- alert_management_alerts
|
||||
- repository_storage_moves
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Ci::CodequalityMrDiffEntity do
|
||||
let(:entity) { described_class.new(mr_diff_report) }
|
||||
let(:mr_diff_report) { Gitlab::Ci::Reports::CodequalityMrDiff.new(codequality_report) }
|
||||
let(:codequality_report) { Gitlab::Ci::Reports::CodequalityReports.new }
|
||||
let(:degradation_1) { build(:codequality_degradation_1) }
|
||||
let(:degradation_2) { build(:codequality_degradation_2) }
|
||||
|
||||
describe '#as_json' do
|
||||
subject(:report) { entity.as_json }
|
||||
|
||||
context 'when quality report has degradations' do
|
||||
before do
|
||||
codequality_report.add_degradation(degradation_1)
|
||||
codequality_report.add_degradation(degradation_2)
|
||||
end
|
||||
|
||||
it 'contains correct codequality mr diff report', :aggregate_failures do
|
||||
expect(report[:files].keys).to eq(["file_a.rb"])
|
||||
expect(report[:files]["file_a.rb"].first).to include(:line, :description, :severity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Ci::CodequalityMrDiffReportSerializer do
|
||||
let(:serializer) { described_class.new.represent(mr_diff_report) }
|
||||
let(:mr_diff_report) { Gitlab::Ci::Reports::CodequalityMrDiff.new(codequality_report) }
|
||||
let(:codequality_report) { Gitlab::Ci::Reports::CodequalityReports.new }
|
||||
let(:degradation_1) { build(:codequality_degradation_1) }
|
||||
let(:degradation_2) { build(:codequality_degradation_2) }
|
||||
|
||||
describe '#to_json' do
|
||||
subject { serializer.as_json }
|
||||
|
||||
context 'when quality report has degradations' do
|
||||
before do
|
||||
codequality_report.add_degradation(degradation_1)
|
||||
codequality_report.add_degradation(degradation_2)
|
||||
end
|
||||
|
||||
it 'matches the schema' do
|
||||
expect(subject).to match_schema('entities/codequality_mr_diff_report')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when quality report has no degradations' do
|
||||
it 'matches the schema' do
|
||||
expect(subject).to match_schema('entities/codequality_mr_diff_report')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -52,6 +52,6 @@ module WaitForRequests
|
|||
end
|
||||
|
||||
def finished_all_ajax_requests?
|
||||
Capybara.page.evaluate_script('window.pendingRequests || window.pendingRailsUJSRequests || 0').zero? # rubocop:disable Style/NumericPredicate
|
||||
Capybara.page.evaluate_script('window.pendingRequests || window.pendingApolloRequests || window.pendingRailsUJSRequests || 0').zero? # rubocop:disable Style/NumericPredicate
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue