Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-07-29 15:12:25 +00:00
parent 7fd99ae2a4
commit 8c2d06cba7
77 changed files with 2434 additions and 456 deletions

View File

@ -6,7 +6,7 @@
### Checklist
- [ ] If your proposal includes changes to the top-level menu items within the left sidebar, engage the [Foundations Product Design Manager](https://about.gitlab.com/handbook/product/categories/#foundations-group) for approval. The Foundations DRI will work with UX partners in product design, research, and technical writing, as applicable.
- [ ] If your proposal includes changes to the menu items within the left sidebar, engage the [Foundations Product Manager](https://about.gitlab.com/handbook/product/categories/#foundations-group) for approval. The Foundations DRI will work with UX partners in product design, research, and technical writing, as applicable.
- [ ] Follow the [product development workflow](https://about.gitlab.com/handbook/product-development-flow/#validation-phase-2-problem-validation) validation process to ensure you are solving a well understood problem and that the proposed change is understandable and non-disruptive to users. Navigation-specific research is strongly encouraged.
- [ ] Engage the [Foundations](https://about.gitlab.com/handbook/product/categories/#foundations-group) team to ensure your proposal is in alignment with holistic changes happening to the left side bar.
- [ ] Consider whether you need to communicate the change somehow, or if you will have an interim period in the UI where your nav item will live in more than one place.

View File

@ -1 +1 @@
1.61.1
1.62.0

View File

@ -10,6 +10,7 @@ import Code from '../../extensions/code';
import CodeBlockHighlight from '../../extensions/code_block_highlight';
import Diagram from '../../extensions/diagram';
import Frontmatter from '../../extensions/frontmatter';
import ReferenceDefinition from '../../extensions/reference_definition';
import ToolbarButton from '../toolbar_button.vue';
export default {
@ -35,6 +36,7 @@ export default {
Image.name,
Audio.name,
Video.name,
ReferenceDefinition.name,
];
return !exclude.some((type) => editor.isActive(type));

View File

@ -0,0 +1,29 @@
import { Node } from '@tiptap/core';
export default Node.create({
name: 'referenceDefinition',
group: 'block',
content: 'text*',
marks: '',
addAttributes() {
return {
identifier: {
default: null,
},
url: {
default: null,
},
title: {
default: null,
},
};
},
renderHTML() {
return ['pre', {}, 0];
},
});

View File

@ -16,6 +16,7 @@ import Link from './link';
import ListItem from './list_item';
import OrderedList from './ordered_list';
import Paragraph from './paragraph';
import ReferenceDefinition from './reference_definition';
import Strike from './strike';
import TaskList from './task_list';
import TaskItem from './task_item';
@ -45,6 +46,7 @@ export default Extension.create({
ListItem.name,
OrderedList.name,
Paragraph.name,
ReferenceDefinition.name,
Strike.name,
TaskList.name,
TaskItem.name,

View File

@ -42,6 +42,7 @@ import OrderedList from '../extensions/ordered_list';
import Paragraph from '../extensions/paragraph';
import PasteMarkdown from '../extensions/paste_markdown';
import Reference from '../extensions/reference';
import ReferenceDefinition from '../extensions/reference_definition';
import Sourcemap from '../extensions/sourcemap';
import Strike from '../extensions/strike';
import Subscript from '../extensions/subscript';
@ -128,6 +129,7 @@ export const createContentEditor = ({
Paragraph,
PasteMarkdown,
Reference,
ReferenceDefinition,
Sourcemap,
Strike,
Subscript,

View File

@ -33,6 +33,7 @@ import MathInline from '../extensions/math_inline';
import OrderedList from '../extensions/ordered_list';
import Paragraph from '../extensions/paragraph';
import Reference from '../extensions/reference';
import ReferenceDefinition from '../extensions/reference_definition';
import Strike from '../extensions/strike';
import Subscript from '../extensions/subscript';
import Superscript from '../extensions/superscript';
@ -177,6 +178,25 @@ const defaultSerializerConfig = {
[Reference.name]: (state, node) => {
state.write(node.attrs.originalText || node.attrs.text);
},
[ReferenceDefinition.name]: preserveUnchanged({
render: (state, node, parent, index, same, sourceMarkdown) => {
const nextSibling = parent.maybeChild(index + 1);
state.text(same ? sourceMarkdown : node.textContent, false);
/**
* Do not insert a blank line between reference definitions
* because it isnt necessary and a more compact text format
* is preferred.
*/
if (!nextSibling || nextSibling.type.name !== ReferenceDefinition.name) {
state.closeBlock(node);
} else {
state.ensureNewLine();
}
},
overwriteSourcePreservationStrategy: true,
}),
[TableOfContents.name]: (state, node) => {
state.write('[[_TOC_]]');
state.closeBlock(node);

View File

@ -170,6 +170,16 @@ const factorySpecs = {
type: 'ignore',
selector: (hastNode) => hastNode.type === 'comment',
},
referenceDefinition: {
type: 'block',
selector: 'referencedefinition',
getAttrs: (hastNode) => ({
title: hastNode.properties.title,
url: hastNode.properties.url,
identifier: hastNode.properties.identifier,
}),
},
};
export default () => {
@ -185,7 +195,7 @@ export default () => {
wrappableTags,
markdown,
}),
skipRendering: ['footnoteReference', 'footnoteDefinition', 'code'],
skipRendering: ['footnoteReference', 'footnoteDefinition', 'code', 'definition'],
});
return { document };

View File

@ -1,4 +1,4 @@
import { uniq, isString, omit } from 'lodash';
import { uniq, isString, omit, isFunction } from 'lodash';
const defaultAttrs = {
td: { colspan: 1, rowspan: 1, colwidth: null },
@ -327,16 +327,25 @@ export function renderCodeBlock(state, node) {
state.closeBlock(node);
}
export function preserveUnchanged(render) {
const expandPreserveUnchangedConfig = (configOrRender) =>
isFunction(configOrRender)
? { render: configOrRender, overwriteSourcePreservationStrategy: false }
: configOrRender;
export function preserveUnchanged(configOrRender) {
return (state, node, parent, index) => {
const { render, overwriteSourcePreservationStrategy } = expandPreserveUnchangedConfig(
configOrRender,
);
const { sourceMarkdown } = node.attrs;
const same = state.options.changeTracker.get(node);
if (same) {
if (same && !overwriteSourcePreservationStrategy) {
state.write(sourceMarkdown);
state.closeBlock(node);
} else {
render(state, node, parent, index);
render(state, node, parent, index, same, sourceMarkdown);
}
};
}

View File

@ -19,6 +19,16 @@ const skipRenderingHandlers = {
h(node.position, 'codeBlock', { language: node.lang, meta: node.meta }, [
{ type: 'text', value: node.value },
]),
definition: (h, node) => {
const title = node.title ? ` "${node.title}"` : '';
return h(
node.position,
'referenceDefinition',
{ identifier: node.identifier, url: node.url, title: node.title },
[{ type: 'text', value: `[${node.identifier}]: ${node.url}${title}` }],
);
},
};
const createParser = ({ skipRendering = [] }) => {

View File

@ -1,4 +1,6 @@
import Vue from 'vue';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import PipelineSchedulesTakeOwnershipModal from '~/pipeline_schedules/components/take_ownership_modal.vue';
import PipelineSchedulesCallout from '../shared/components/pipeline_schedules_callout.vue';
function initPipelineSchedules() {
@ -23,4 +25,43 @@ function initPipelineSchedules() {
});
}
function initTakeownershipModal() {
const modalId = 'pipeline-take-ownership-modal';
const buttonSelector = 'js-take-ownership-button';
const el = document.getElementById(modalId);
const takeOwnershipButtons = document.querySelectorAll(`.${buttonSelector}`);
if (!el) {
return;
}
// eslint-disable-next-line no-new
new Vue({
el,
data() {
return {
url: '',
};
},
mounted() {
takeOwnershipButtons.forEach((button) => {
button.addEventListener('click', () => {
const { url } = button.dataset;
this.url = url;
this.$root.$emit(BV_SHOW_MODAL, modalId, `.${buttonSelector}`);
});
});
},
render(createElement) {
return createElement(PipelineSchedulesTakeOwnershipModal, {
props: {
ownershipUrl: this.url,
},
});
},
});
}
initPipelineSchedules();
initTakeownershipModal();

View File

@ -0,0 +1,52 @@
<script>
import { GlModal } from '@gitlab/ui';
import { __, s__ } from '~/locale';
export default {
components: {
GlModal,
},
props: {
ownershipUrl: {
type: String,
required: true,
},
},
modalId: 'pipeline-take-ownership-modal',
i18n: {
takeOwnership: s__('PipelineSchedules|Take ownership'),
ownershipMessage: s__(
'PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?',
),
cancelLabel: __('Cancel'),
},
computed: {
actionCancel() {
return { text: this.$options.i18n.cancelLabel };
},
actionPrimary() {
return {
text: this.$options.i18n.takeOwnership,
attributes: [
{
variant: 'confirm',
category: 'primary',
href: this.ownershipUrl,
'data-method': 'post',
},
],
};
},
},
};
</script>
<template>
<gl-modal
:modal-id="$options.modalId"
:action-primary="actionPrimary"
:action-cancel="actionCancel"
:title="$options.i18n.takeOwnership"
>
<p>{{ $options.i18n.ownershipMessage }}</p>
</gl-modal>
</template>

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
module Projects
class ProjectTransferedEvent < ::Gitlab::EventStore::Event
def schema
{
'type' => 'object',
'properties' => {
'project_id' => { 'type' => 'integer' },
'old_namespace_id' => { 'type' => 'integer' },
'old_root_namespace_id' => { 'type' => 'integer' },
'new_namespace_id' => { 'type' => 'integer' },
'new_root_namespace_id' => { 'type' => 'integer' }
},
'required' => %w[
project_id
old_namespace_id
old_root_namespace_id
new_namespace_id
new_root_namespace_id
]
}
end
end
end

View File

@ -137,7 +137,12 @@ module CommitsHelper
def conditionally_paginate_diff_files(diffs, paginate:, page:, per:)
if paginate
Kaminari.paginate_array(diffs.diff_files.to_a).page(page).per(per)
diff_files = diffs.diff_files.to_a
Gitlab::Utils::BatchLoader.clear_key([:repository_blobs, diffs.project.repository])
Kaminari.paginate_array(diff_files).page(page).per(per).tap do |diff_files|
diff_files.each(&:add_blobs_to_batch_loader)
end
else
diffs.diff_files
end

View File

@ -93,8 +93,8 @@ class Blob < SimpleDelegator
end
def self.lazy(repository, commit_id, path, blob_size_limit: Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE)
BatchLoader.for([commit_id, path]).batch(key: repository) do |items, loader, args|
args[:key].blobs_at(items, blob_size_limit: blob_size_limit).each do |blob|
BatchLoader.for([commit_id, path]).batch(key: [:repository_blobs, repository]) do |items, loader, args|
args[:key].last.blobs_at(items, blob_size_limit: blob_size_limit).each do |blob|
loader.call([blob.commit_id, blob.path], blob) if blob
end
end

View File

@ -121,6 +121,8 @@ module Projects
# Overridden in EE
def post_update_hooks(project)
ensure_personal_project_owner_membership(project)
publish_event
end
# Overridden in EE
@ -268,6 +270,18 @@ module Projects
CustomerRelations::IssueContact.delete_for_project(project.id)
end
def publish_event
event = ::Projects::ProjectTransferedEvent.new(data: {
project_id: project.id,
old_namespace_id: old_namespace.id,
old_root_namespace_id: old_namespace.root_ancestor.id,
new_namespace_id: new_namespace.id,
new_root_namespace_id: new_namespace.root_ancestor.id
})
Gitlab::EventStore.publish(event)
end
end
end

View File

@ -13,5 +13,9 @@ module ProtectedBranches
def after_execute(*)
# overridden in EE::ProtectedBranches module
end
def refresh_cache
CacheService.new(@project, @current_user, @params).refresh
end
end
end

View File

@ -0,0 +1,47 @@
# frozen_string_literal: true
module ProtectedBranches
class CacheService < ProtectedBranches::BaseService
CACHE_ROOT_KEY = 'cache:gitlab:protected_branch'
TTL_UNSET = -1
CACHE_EXPIRE_IN = 1.day
CACHE_LIMIT = 1000
def fetch(ref_name)
record = OpenSSL::Digest::SHA256.hexdigest(ref_name)
Gitlab::Redis::Cache.with do |redis|
cached_result = redis.hget(redis_key, record)
break Gitlab::Redis::Boolean.decode(cached_result) unless cached_result.nil?
value = yield
redis.hset(redis_key, record, Gitlab::Redis::Boolean.encode(value))
# We don't want to extend cache expiration time
if redis.ttl(redis_key) == TTL_UNSET
redis.expire(redis_key, CACHE_EXPIRE_IN)
end
# If the cache record has too many elements, then something went wrong and
# it's better to drop the cache key.
if redis.hlen(redis_key) > CACHE_LIMIT
redis.unlink(redis_key)
end
value
end
end
def refresh
Gitlab::Redis::Cache.with { |redis| redis.unlink(redis_key) }
end
private
def redis_key
@redis_key ||= [CACHE_ROOT_KEY, @project.id].join(':')
end
end
end

View File

@ -7,6 +7,8 @@ module ProtectedBranches
save_protected_branch
refresh_cache
protected_branch
end

View File

@ -5,7 +5,7 @@ module ProtectedBranches
def execute(protected_branch)
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :destroy_protected_branch, protected_branch)
protected_branch.destroy
protected_branch.destroy.tap { refresh_cache }
end
end
end

View File

@ -10,6 +10,8 @@ module ProtectedBranches
if protected_branch.update(params)
after_execute(protected_branch: protected_branch, old_merge_access_levels: old_merge_access_levels, old_push_access_levels: old_push_access_levels)
refresh_cache
end
protected_branch

View File

@ -1,5 +1,5 @@
= gitlab_ui_form_for @application_setting, url: ci_cd_admin_application_settings_path(anchor: 'js-runner-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
= form_errors(@application_setting, pajamas_alert: true)
%fieldset
.gl-form-group

View File

@ -3,7 +3,7 @@
- link_end = '</a>'.html_safe
= gitlab_ui_form_for @application_setting, url: metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
= form_errors(@application_setting, pajamas_alert: true)
%fieldset
.form-group
@ -38,7 +38,7 @@
%p.gl-mb-3= s_('AdminSettings|Registration Features include:')
- email_from_gitlab_path = help_page_path('user/admin_area/email_from_gitlab')
- repo_size_limit_path = help_page_path('user/admin_area/settings/account_and_limit_settings', anchor: 'repository-size-limit')
- restrict_ip_path = help_page_path('user/group/index', anchor: 'restrict-group-access-by-ip-address')
- restrict_ip_path = help_page_path('user/group/access_and_permissions', anchor: 'restrict-group-access-by-ip-address')
- email_from_gitlab_link = link_start % { url: email_from_gitlab_path }
- repo_size_limit_link = link_start % { url: repo_size_limit_path }
- restrict_ip_link = link_start % { url: restrict_ip_path }

View File

@ -7,7 +7,7 @@
- content_for :flash_message do
= render "layouts/header/storage_enforcement_banner", context: @group
= dispensable_render_if_exists "shared/namespace_storage_limit_alert"
= dispensable_render_if_exists "shared/namespace_storage_limit_alert", context: @group
- content_for :page_specific_javascripts do
- if current_user

View File

@ -8,5 +8,6 @@
- content_for :flash_message do
= render "layouts/header/storage_enforcement_banner", context: current_user.namespace
= dispensable_render_if_exists "shared/namespace_storage_limit_alert", context: current_user.namespace
= render template: "layouts/application"

View File

@ -9,7 +9,7 @@
- content_for :flash_message do
= render "layouts/header/storage_enforcement_banner", context: @project
= dispensable_render_if_exists "shared/namespace_storage_limit_alert"
= dispensable_render_if_exists "shared/namespace_storage_limit_alert", context: @project
- content_for :project_javascripts do
- project = @target_project || @project

View File

@ -33,7 +33,7 @@
= link_to play_pipeline_schedule_path(pipeline_schedule), method: :post, title: _('Play'), class: 'btn gl-button btn-default btn-icon' do
= sprite_icon('play')
- if can?(current_user, :take_ownership_pipeline_schedule, pipeline_schedule)
= link_to take_ownership_pipeline_schedule_path(pipeline_schedule), method: :post, title: s_('PipelineSchedules|Take ownership'), class: 'btn gl-button btn-default' do
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-take-ownership-button has-tooltip', title: s_('PipelineSchedule|Take ownership to edit'), data: { url: take_ownership_pipeline_schedule_path(pipeline_schedule) } }) do
= s_('PipelineSchedules|Take ownership')
- if can?(current_user, :update_pipeline_schedule, pipeline_schedule)
= link_to edit_pipeline_schedule_path(pipeline_schedule), title: _('Edit'), class: 'btn gl-button btn-default btn-icon' do

View File

@ -18,3 +18,5 @@
- else
.card.bg-light.gl-mt-3
.nothing-here-block= _("No schedules")
#pipeline-take-ownership-modal

View File

@ -17,16 +17,6 @@
# Corresponding feature flag should have `default_enabled` attribute set to `false`.
# This attribute is OPTIONAL and can be omitted, when `feature_flag` is missing no feature flag will be checked.
---
- name: compliance_features_track_unique_visits_union
operator: OR
source: redis
time_frame: [7d, 28d]
events:
- 'g_compliance_audit_events'
- 'g_compliance_dashboard'
- 'i_compliance_audit_events'
- 'a_compliance_audit_events_api'
- 'i_compliance_credential_inventory'
- name: incident_management_alerts_total_unique_counts
operator: OR
source: redis

View File

@ -41,7 +41,6 @@ module.exports = {
'three',
'select2',
'moment-mini',
'aws-sdk',
'dompurify',
'bootstrap/dist/js/bootstrap.js',
'sortablejs/modular/sortable.esm.js',

View File

@ -115,7 +115,7 @@ From there, you can see the following actions:
- Instance administrator started or stopped impersonation of a group member. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300961) in GitLab 14.8.
- Group deploy token was successfully created, revoked, or deleted. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/353452) in GitLab 14.9.
- Failed attempt to create a group deploy token. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/353452) in GitLab 14.9.
- [IP restrictions](../user/group/index.md#group-access-restriction-by-ip-address) changed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/358986) in GitLab 15.0.
- [IP restrictions](../user/group/access_and_permissions.md#restrict-group-access-by-ip-address) changed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/358986) in GitLab 15.0.
- Changes to push rules. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227629) in GitLab 15.0.
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/356152) in GitLab 15.1, changes to the following merge request approvals settings:
- Prevent approval by author.

View File

@ -128,7 +128,7 @@ To take advantage of group sync, group Owners or users with the [Maintainer role
### Add group links
For information on adding group links by using CNs and filters, refer to the
[GitLab groups documentation](../../../user/group/index.md#manage-group-memberships-via-ldap).
[GitLab groups documentation](../../../user/group/access_and_permissions.md#manage-group-memberships-via-ldap).
### Administrator sync

View File

@ -97,7 +97,7 @@ These features can also help with compliance requirements:
projects): Search dependencies for their licenses. This lets you determine if
the licenses of your project's dependencies are compatible with your project's
license.
- [**Lock project membership to group**](../user/group/index.md#prevent-members-from-being-added-to-projects-in-a-group)
- [**Lock project membership to group**](../user/group/access_and_permissions.md#prevent-members-from-being-added-to-projects-in-a-group)
(for groups): Group owners can prevent new members from being added to projects
within a group.
- [**LDAP group sync**](auth/ldap/ldap_synchronization.md#group-sync) (for

View File

@ -926,7 +926,7 @@ PUT /groups/:id
| `emails_disabled` | boolean | no | Disable email notifications. |
| `lfs_enabled` | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
| `mentions_disabled` | boolean | no | Disable the capability of a group from getting mentioned. |
| `prevent_sharing_groups_outside_hierarchy` | boolean | no | See [Prevent group sharing outside the group hierarchy](../user/group/index.md#prevent-group-sharing-outside-the-group-hierarchy). This attribute is only available on top-level groups. [Introduced in GitLab 14.1](https://gitlab.com/gitlab-org/gitlab/-/issues/333721) |
| `prevent_sharing_groups_outside_hierarchy` | boolean | no | See [Prevent group sharing outside the group hierarchy](../user/group/access_and_permissions.md#prevent-group-sharing-outside-the-group-hierarchy). This attribute is only available on top-level groups. [Introduced in GitLab 14.1](https://gitlab.com/gitlab-org/gitlab/-/issues/333721) |
| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (users with the Maintainer role), or `developer` (users with the Developer or Maintainer role). |
| `request_access_enabled` | boolean | no | Allow users to request member access. |
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
@ -1481,7 +1481,7 @@ DELETE /groups/:id/share/:group_id
### Get group push rules **(PREMIUM)**
Get the [push rules](../user/group/index.md#group-push-rules) of a group.
Get the [push rules](../user/group/access_and_permissions.md#group-push-rules) of a group.
Only available to group owners and administrators.
@ -1524,7 +1524,7 @@ the `commit_committer_check` and `reject_unsigned_commits` parameters:
### Add group push rule **(PREMIUM)**
Adds [push rules](../user/group/index.md#group-push-rules) to the specified group.
Adds [push rules](../user/group/access_and_permissions.md#group-push-rules) to the specified group.
Only available to group owners and administrators.
@ -1618,7 +1618,7 @@ Response:
### Delete group push rule **(PREMIUM)**
Deletes the [push rules](../user/group/index.md#group-push-rules) of a group.
Deletes the [push rules](../user/group/access_and_permissions.md#group-push-rules) of a group.
Only available to group owners and administrators.

View File

@ -756,7 +756,7 @@ Group SAML on a self-managed instance is limited when compared to the recommende
[instance-wide SAML](../user/group/saml_sso/index.md). The recommended solution allows you to take advantage of:
- [LDAP compatibility](../administration/auth/ldap/index.md).
- [LDAP Group Sync](../user/group/index.md#manage-group-memberships-via-ldap).
- [LDAP Group Sync](../user/group/access_and_permissions.md#manage-group-memberships-via-ldap).
- [Required groups](#required-groups).
- [Administrator groups](#administrator-groups).
- [Auditor groups](#auditor-groups).

View File

@ -71,7 +71,7 @@ The following are important notes about 2FA:
2FA for the project. For example, if project *P* belongs to 2FA-enabled group *A* and
is shared with 2FA-disabled group *B*, members of group *B* can access project *P*
without 2FA. To ensure this scenario doesn't occur,
[prevent sharing of projects](../user/group/index.md#prevent-a-project-from-being-shared-with-groups)
[prevent sharing of projects](../user/group/access_and_permissions.md#prevent-a-project-from-being-shared-with-groups)
for the 2FA-enabled group.
- If you add additional members to a project within a group or subgroup that has
2FA enabled, 2FA is **not** required for those individually added members.

View File

@ -23,11 +23,11 @@ the tiers are no longer mentioned in GitLab documentation:
- [Setting a default template for merge requests and issues](../user/project/description_templates.md#set-a-default-template-for-merge-requests-and-issues)
- [Email from GitLab](../user/admin_area/email_from_gitlab.md)
- Groups:
- [Creating group memberships via CN](../user/group/index.md#create-group-links-via-cn)
- [Group push rules](../user/group/index.md#group-push-rules)
- [Managing group memberships via LDAP](../user/group/index.md#manage-group-memberships-via-ldap)
- [Member locking](../user/group/index.md#prevent-members-from-being-added-to-projects-in-a-group)
- [Overriding user permissions](../user/group/index.md#override-user-permissions)
- [Creating group memberships via CN](../user/group/access_and_permissions.md#create-group-links-via-cn)
- [Group push rules](../user/group/access_and_permissions.md#group-push-rules)
- [Managing group memberships via LDAP](../user/group/access_and_permissions.md#manage-group-memberships-via-ldap)
- [Member locking](../user/group/access_and_permissions.md#prevent-members-from-being-added-to-projects-in-a-group)
- [Overriding user permissions](../user/group/access_and_permissions.md#override-user-permissions)
- [User contribution analytics](../user/group/contribution_analytics/index.md)
- [Kerberos integration](../integration/kerberos.md)
- Issue boards:

View File

@ -48,7 +48,7 @@ tier. Users can continue to access the features in a paid tier without sharing u
### Features available in 14.4 and later
- [Repository size limit](../settings/account_and_limit_settings.md#repository-size-limit).
- [Group access restriction by IP address](../../group/index.md#group-access-restriction-by-ip-address).
- [Group access restriction by IP address](../../group/access_and_permissions.md#restrict-group-access-by-ip-address).
NOTE:
Registration is not yet required for participation, but may be added in a future milestone.

View File

@ -6,6 +6,246 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Group access and permissions
Use Groups to manage one or more related projects at the same time.
Configure your groups to control group permissions and access.
For instructions on how to configure access and permissions for groups, see [Groups](index.md).
## Group push rules **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34370) in GitLab 12.8.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/224129) in GitLab 13.4.
Group push rules allow group maintainers to set
[push rules](../project/repository/push_rules.md) for newly created projects in the specific group.
To configure push rules for a group:
1. Go to the groups's **Push Rules** page.
1. Select the settings you want.
1. Select **Save Push Rules**.
The group's new subgroups have push rules set for them based on either:
- The closest parent group with push rules defined.
- Push rules set at the instance level, if no parent groups have push rules defined.
## Restrict group access by IP address **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1985) in GitLab 12.0.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215410) from GitLab Ultimate to GitLab Premium in 13.1.
To ensure only people from your organization can access particular
resources, you can restrict access to groups by IP address. This group-level setting
applies to:
- The GitLab UI, including subgroups, projects, and issues.
- [In GitLab 12.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/12874), the API.
### Security implications
You should consider some security implications before configuring IP address restrictions.
- Restricting HTTP traffic on GitLab.com with IP address restrictions causes SSH requests (including Git operations over
SSH) to fail. For more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/271673).
- Administrators and group owners can access group settings from any IP address, regardless of IP restriction. However:
- Groups owners cannot access projects belonging to the group when accessing from a disallowed IP address.
- Administrators can access projects belonging to the group when accessing from a disallowed IP address.
Access to projects includes cloning code from them.
- Users can still see group and project names and hierarchies. Only the following are restricted:
- [Groups](../../api/groups.md), including all [group resources](../../api/api_resources.md#group-resources).
- [Project](../../api/projects.md), including all [project resources](../../api/api_resources.md#project-resources).
- When you register a runner, it is not bound by the IP restrictions. When the runner requests a new job or an update to
a job's state, it is also not bound by the IP restrictions. But when the running CI/CD job sends Git requests from a
restricted IP address, the IP restriction prevents code from being cloned.
- Users may still see some events from the IP restricted groups and projects on their dashboard. Activity may include
push, merge, issue, or comment events.
### Restrict group access by IP address
To restrict group access by IP address:
1. Go to the group's **Settings > General** page.
1. Expand the **Permissions and group features** section.
1. In the **Allow access to the following IP addresses** field, enter IPv4 or IPv6 address ranges in CIDR notation.
1. Select **Save changes**.
In self-managed installations of GitLab 15.1 and later, you can also configure
[globally-allowed IP address ranges](../admin_area/settings/visibility_and_access_controls.md#configure-globally-allowed-ip-address-ranges)
at the group level.
## Restrict group access by domain **(PREMIUM)**
> - Support for specifying multiple email domains [added](https://gitlab.com/gitlab-org/gitlab/-/issues/33143) in GitLab 13.1.
> - Support for restricting access to projects in the group [added](https://gitlab.com/gitlab-org/gitlab/-/issues/14004) in GitLab 14.1.2.
You can prevent users with email addresses in specific domains from being added to a group and its projects.
To restrict group access by domain:
1. Go to the group's **Settings > General** page.
1. Expand the **Permissions and group features** section.
1. In the **Restrict membership by email** field, enter the domain names.
1. Select **Save changes**.
Any time you attempt to add a new user, the user's [primary email](../profile/index.md#change-your-primary-email) is compared against this list.
Only users with a [primary email](../profile/index.md#change-your-primary-email) that matches any of the configured email domain restrictions
can be added to the group.
The most popular public email domains cannot be restricted, such as:
- `gmail.com`, `yahoo.com`, `aol.com`, `icloud.com`
- `hotmail.com`, `hotmail.co.uk`, `hotmail.fr`
- `msn.com`, `live.com`, `outlook.com`
## Prevent group sharing outside the group hierarchy
You can configure a top-level group so its subgroups and projects
cannot invite other groups outside of the top-level group's hierarchy.
This option is only available for top-level groups.
For example, in the following group and project hierarchy:
- **Animals > Dogs > Dog Project**
- **Animals > Cats**
- **Plants > Trees**
If you prevent group sharing outside the hierarchy for the **Animals** group:
- **Dogs** can invite the group **Cats**.
- **Dogs** cannot invite the group **Trees**.
- **Dog Project** can invite the group **Cats**.
- **Dog Project** cannot invite the group **Trees**.
To prevent sharing outside of the group's hierarchy:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Settings > General**.
1. Expand **Permissions and group features**.
1. Select **Prevent members from sending invitations to groups outside of `<group_name>` and its subgroups**.
1. Select **Save changes**.
## Prevent a project from being shared with groups
Prevent projects in a group from [sharing
a project with another group](../project/members/share_project_with_groups.md) to enable tighter control over project access.
To prevent a project from being shared with other groups:
1. Go to the group's **Settings > General** page.
1. Expand the **Permissions and group features** section.
1. Select **Prevent sharing a project in `<group_name>` with other groups**.
1. Select **Save changes**.
This setting applies to all subgroups unless overridden by a group owner. Groups already
added to a project lose access when the setting is enabled.
## Prevent users from requesting access to a group
As a group owner, you can prevent non-members from requesting access to
your group.
1. On the top bar, select **Menu > Groups**.
1. Select **Your Groups**.
1. Find the group and select it.
1. From the left menu, select **Settings > General**.
1. Expand the **Permissions and group features** section.
1. Clear the **Allow users to request access** checkbox.
1. Select **Save changes**.
## Prevent project forking outside group **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216987) in GitLab 13.3.
By default, projects in a group can be forked.
Optionally, on [GitLab Premium](https://about.gitlab.com/pricing/) or higher tiers,
you can prevent the projects in a group from being forked outside of the current top-level group.
This setting will be removed from the SAML setting page, and migrated to the
group settings page. In the interim period, both of these settings are taken into consideration.
If even one is set to `true`, then the group does not allow outside forks.
To prevent projects from being forked outside the group:
1. Go to the top-level group's **Settings > General** page.
1. Expand the **Permissions and group features** section.
1. Check **Prevent project forking outside current group**.
1. Select **Save changes**.
Existing forks are not removed.
## Prevent members from being added to projects in a group **(PREMIUM)**
As a group owner, you can prevent any new project membership for all
projects in a group, allowing tighter control over project membership.
For example, if you want to lock the group for an [Audit Event](../../administration/audit_events.md),
you can guarantee that project membership cannot be modified during the audit.
You can still invite groups or to add members to groups, implicitly giving members access to projects in the **locked** group.
The setting does not cascade. Projects in subgroups observe the subgroup configuration, ignoring the parent group.
To prevent members from being added to projects in a group:
1. Go to the group's **Settings > General** page.
1. Expand the **Permissions and group features** section.
1. Under **Membership**, select **Prevent adding new members to projects within this group**.
1. Select **Save changes**.
All users who previously had permissions can no longer add members to a group.
API requests to add a new user to a project are not possible.
## Manage group memberships via LDAP **(PREMIUM SELF)**
Group syncing allows LDAP groups to be mapped to GitLab groups. This provides more control over per-group user management. To configure group syncing, edit the `group_base` **DN** (`'OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=org'`). This **OU** contains all groups that are associated with GitLab groups.
Group links can be created by using either a CN or a filter. To create these group links, go to the group's **Settings > LDAP Synchronization** page. After configuring the link, it may take more than an hour for the users to sync with the GitLab group.
For more information on the administration of LDAP and group sync, refer to the [main LDAP documentation](../../administration/auth/ldap/ldap_synchronization.md#group-sync).
NOTE:
When you add LDAP synchronization, if an LDAP user is a group member and they are not part of the LDAP group, they are removed from the group.
### Create group links via CN **(PREMIUM SELF)**
To create group links via CN:
<!-- vale gitlab.Spelling = NO -->
1. Select the **LDAP Server** for the link.
1. As the **Sync method**, select `LDAP Group cn`.
1. In the **LDAP Group cn** field, begin typing the CN of the group. There is a dropdown list with matching CNs in the configured `group_base`. Select your CN from this list.
1. In the **LDAP Access** section, select the [permission level](../permissions.md) for users synced in this group.
1. Select **Add Synchronization**.
<!-- vale gitlab.Spelling = YES -->
### Create group links via filter **(PREMIUM SELF)**
To create group links via filter:
1. Select the **LDAP Server** for the link.
1. As the **Sync method**, select `LDAP user filter`.
1. Input your filter in the **LDAP User filter** box. Follow the [documentation on user filters](../../administration/auth/ldap/index.md#set-up-ldap-user-filter).
1. In the **LDAP Access** section, select the [permission level](../permissions.md) for users synced in this group.
1. Select **Add Synchronization**.
### Override user permissions **(PREMIUM SELF)**
LDAP user permissions can be manually overridden by an administrator. To override a user's permissions:
1. Go to your group's **Group information > Members** page.
1. In the row for the user you are editing, select the pencil (**{pencil}**) icon.
1. Select **Edit permissions** in the modal.
Now you can edit the user's permissions from the **Members** page.
## Troubleshooting
### Verify if access is blocked by IP restriction
If a user sees a 404 when they would normally expect access, and the problem is limited to a specific group, search the `auth.log` rails log for one or more of the following:
- `json.message`: `'Attempting to access IP restricted group'`
- `json.allowed`: `false`
In viewing the log entries, compare the `remote.ip` with the list of
[allowed IPs](#restrict-group-access-by-ip-address) for the group.

View File

@ -48,19 +48,6 @@ For example, consider a user named Alex:
| Alex creates a group for their team with the group name `alex-team`. The group and its projects are available at: `https://gitlab.example.com/alex-team`. | The namespace in this case is `alex-team`. |
| Alex creates a subgroup of `alex-team` with the subgroup name `marketing`. The subgroup and its projects are available at: `https://gitlab.example.com/alex-team/marketing`. | The namespace in this case is `alex-team/marketing`. |
## Prevent users from requesting access to a group
As a group owner, you can prevent non-members from requesting access to
your group.
1. On the top bar, select **Menu > Groups**.
1. Select **Your Groups**.
1. Find the group and select it.
1. From the left menu, select **Settings > General**.
1. Expand the **Permissions and group features** section.
1. Clear the **Allow users to request access** checkbox.
1. Select **Save changes**.
## Mention a group in an issue or merge request
When you mention a group in a comment, every member of the group gets a to-do item
@ -73,115 +60,6 @@ added to their To-do list.
A to-do item is created for all the group and subgroup members.
## Manage group memberships via LDAP **(PREMIUM SELF)**
Group syncing allows LDAP groups to be mapped to GitLab groups. This provides more control over per-group user management. To configure group syncing, edit the `group_base` **DN** (`'OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=org'`). This **OU** contains all groups that are associated with GitLab groups.
Group links can be created by using either a CN or a filter. To create these group links, go to the group's **Settings > LDAP Synchronization** page. After configuring the link, it may take more than an hour for the users to sync with the GitLab group.
For more information on the administration of LDAP and group sync, refer to the [main LDAP documentation](../../administration/auth/ldap/ldap_synchronization.md#group-sync).
NOTE:
When you add LDAP synchronization, if an LDAP user is a group member and they are not part of the LDAP group, they are removed from the group.
### Create group links via CN **(PREMIUM SELF)**
To create group links via CN:
<!-- vale gitlab.Spelling = NO -->
1. Select the **LDAP Server** for the link.
1. As the **Sync method**, select `LDAP Group cn`.
1. In the **LDAP Group cn** field, begin typing the CN of the group. There is a dropdown list with matching CNs in the configured `group_base`. Select your CN from this list.
1. In the **LDAP Access** section, select the [permission level](../permissions.md) for users synced in this group.
1. Select **Add Synchronization**.
<!-- vale gitlab.Spelling = YES -->
### Create group links via filter **(PREMIUM SELF)**
To create group links via filter:
1. Select the **LDAP Server** for the link.
1. As the **Sync method**, select `LDAP user filter`.
1. Input your filter in the **LDAP User filter** box. Follow the [documentation on user filters](../../administration/auth/ldap/index.md#set-up-ldap-user-filter).
1. In the **LDAP Access** section, select the [permission level](../permissions.md) for users synced in this group.
1. Select **Add Synchronization**.
### Override user permissions **(PREMIUM SELF)**
LDAP user permissions can be manually overridden by an administrator. To override a user's permissions:
1. Go to your group's **Group information > Members** page.
1. In the row for the user you are editing, select the pencil (**{pencil}**) icon.
1. Select **Edit permissions** in the modal.
Now you can edit the user's permissions from the **Members** page.
## Prevent group sharing outside the group hierarchy
You can configure a top-level group so its subgroups and projects
cannot invite other groups outside of the top-level group's hierarchy.
This option is only available for top-level groups.
For example, in the following group and project hierarchy:
- **Animals > Dogs > Dog Project**
- **Animals > Cats**
- **Plants > Trees**
If you prevent group sharing outside the hierarchy for the **Animals** group:
- **Dogs** can invite the group **Cats**.
- **Dogs** cannot invite the group **Trees**.
- **Dog Project** can invite the group **Cats**.
- **Dog Project** cannot invite the group **Trees**.
To prevent sharing outside of the group's hierarchy:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Settings > General**.
1. Expand **Permissions and group features**.
1. Select **Prevent members from sending invitations to groups outside of `<group_name>` and its subgroups**.
1. Select **Save changes**.
## Prevent a project from being shared with groups
Prevent projects in a group from [sharing
a project with another group](../project/members/share_project_with_groups.md) to enable tighter control over project access.
To prevent a project from being shared with other groups:
1. Go to the group's **Settings > General** page.
1. Expand the **Permissions and group features** section.
1. Select **Prevent sharing a project in `<group_name>` with other groups**.
1. Select **Save changes**.
This setting applies to all subgroups unless overridden by a group owner. Groups already
added to a project lose access when the setting is enabled.
## Prevent members from being added to projects in a group **(PREMIUM)**
As a group owner, you can prevent any new project membership for all
projects in a group, allowing tighter control over project membership.
For example, if you want to lock the group for an [Audit Event](../../administration/audit_events.md),
you can guarantee that project membership cannot be modified during the audit.
You can still invite groups or to add members to groups, implicitly giving members access to projects in the **locked** group.
The setting does not cascade. Projects in subgroups observe the subgroup configuration, ignoring the parent group.
To prevent members from being added to projects in a group:
1. Go to the group's **Settings > General** page.
1. Expand the **Permissions and group features** section.
1. Under **Membership**, select **Prevent adding new members to projects within this group**.
1. Select **Save changes**.
All users who previously had permissions can no longer add members to a group.
API requests to add a new user to a project are not possible.
## Export members as CSV **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/287940) in GitLab 14.2.
@ -193,115 +71,6 @@ You can export a list of members in a group or subgroup as a CSV.
1. Select **Export as CSV**.
1. After the CSV file has been generated, it is emailed as an attachment to the user that requested it.
## Group access restriction by IP address **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1985) in GitLab 12.0.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215410) from GitLab Ultimate to GitLab Premium in 13.1.
To ensure only people from your organization can access particular
resources, you can restrict access to groups by IP address. This group-level setting
applies to:
- The GitLab UI, including subgroups, projects, and issues.
- [In GitLab 12.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/12874), the API.
### Security implications
You should consider some security implications before configuring IP address restrictions.
- Restricting HTTP traffic on GitLab.com with IP address restrictions causes SSH requests (including Git operations over
SSH) to fail. For more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/271673).
- Administrators and group owners can access group settings from any IP address, regardless of IP restriction. However:
- Groups owners cannot access projects belonging to the group when accessing from a disallowed IP address.
- Administrators can access projects belonging to the group when accessing from a disallowed IP address.
Access to projects includes cloning code from them.
- Users can still see group and project names and hierarchies. Only the following are restricted:
- [Groups](../../api/groups.md), including all [group resources](../../api/api_resources.md#group-resources).
- [Project](../../api/projects.md), including all [project resources](../../api/api_resources.md#project-resources).
- When you register a runner, it is not bound by the IP restrictions. When the runner requests a new job or an update to
a job's state, it is also not bound by the IP restrictions. But when the running CI/CD job sends Git requests from a
restricted IP address, the IP restriction prevents code from being cloned.
- Users may still see some events from the IP restricted groups and projects on their dashboard. Activity may include
push, merge, issue, or comment events.
### Restrict group access by IP address
To restrict group access by IP address:
1. Go to the group's **Settings > General** page.
1. Expand the **Permissions and group features** section.
1. In the **Allow access to the following IP addresses** field, enter IPv4 or IPv6 address ranges in CIDR notation.
1. Select **Save changes**.
In self-managed installations of GitLab 15.1 and later, you can also configure
[globally-allowed IP address ranges](../admin_area/settings/visibility_and_access_controls.md#configure-globally-allowed-ip-address-ranges)
at the group level.
## Restrict group access by domain **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7297) in GitLab 12.2.
> - Support for specifying multiple email domains [added](https://gitlab.com/gitlab-org/gitlab/-/issues/33143) in GitLab 13.1.
> - Support for restricting access to projects in the group [added](https://gitlab.com/gitlab-org/gitlab/-/issues/14004) in GitLab 14.1.2.
You can prevent users with email addresses in specific domains from being added to a group and its projects.
To restrict group access by domain:
1. Go to the group's **Settings > General** page.
1. Expand the **Permissions and group features** section.
1. In the **Restrict membership by email** field, enter the domain names.
1. Select **Save changes**.
Any time you attempt to add a new user, the user's [primary email](../profile/index.md#change-your-primary-email) is compared against this list.
Only users with a [primary email](../profile/index.md#change-your-primary-email) that matches any of the configured email domain restrictions
can be added to the group.
The most popular public email domains cannot be restricted, such as:
- `gmail.com`, `yahoo.com`, `aol.com`, `icloud.com`
- `hotmail.com`, `hotmail.co.uk`, `hotmail.fr`
- `msn.com`, `live.com`, `outlook.com`
## Prevent project forking outside group **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216987) in GitLab 13.3.
By default, projects in a group can be forked.
Optionally, on [GitLab Premium](https://about.gitlab.com/pricing/) or higher tiers,
you can prevent the projects in a group from being forked outside of the current top-level group.
This setting will be removed from the SAML setting page, and migrated to the
group settings page. In the interim period, both of these settings are taken into consideration.
If even one is set to `true`, then the group does not allow outside forks.
To prevent projects from being forked outside the group:
1. Go to the top-level group's **Settings > General** page.
1. Expand the **Permissions and group features** section.
1. Check **Prevent project forking outside current group**.
1. Select **Save changes**.
Existing forks are not removed.
## Group push rules **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34370) in GitLab 12.8.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/224129) in GitLab 13.4.
Group push rules allow group maintainers to set
[push rules](../project/repository/push_rules.md) for newly created projects in the specific group.
To configure push rules for a group:
1. Go to the groups's **Push Rules** page.
1. Select the settings you want.
1. Select **Save Push Rules**.
The group's new subgroups have push rules set for them based on either:
- The closest parent group with push rules defined.
- Push rules set at the instance level, if no parent groups have push rules defined.
## Related topics
- [Group wikis](../project/wiki/index.md)
@ -323,20 +92,8 @@ The group's new subgroups have push rules set for them based on either:
- [Integrations](../admin_area/settings/project_integration_management.md).
- [Transfer a project into a group](../project/settings/index.md#transfer-a-project-to-another-namespace).
- [Share a project with a group](../project/members/share_project_with_groups.md): Give all group members access to the project at once.
- [Lock the sharing with group feature](#prevent-a-project-from-being-shared-with-groups).
- [Lock the sharing with group feature](access_and_permissions.md#prevent-a-project-from-being-shared-with-groups).
- [Enforce two-factor authentication (2FA)](../../security/two_factor_authentication.md#enforce-2fa-for-all-users-in-a-group): Enforce 2FA
for all group members.
- Namespaces [API](../../api/namespaces.md) and [Rake tasks](../../raketasks/index.md).
- [Control access and visibility](../admin_area/settings/visibility_and_access_controls.md).
## Troubleshooting
### Verify if access is blocked by IP restriction
If a user sees a 404 when they would normally expect access, and the problem is limited to a specific group, search the `auth.log` rails log for one or more of the following:
- `json.message`: `'Attempting to access IP restricted group'`
- `json.allowed`: `false`
In viewing the log entries, compare the `remote.ip` with the list of
[allowed IPs](#group-access-restriction-by-ip-address) for the group.

View File

@ -217,7 +217,7 @@ The following table lists project permissions available for each role:
4. If the [branch is protected](project/protected_branches.md), this depends on the access Developers and Maintainers are given.
5. Guest users can access GitLab [**Releases**](project/releases/index.md) for downloading assets but are not allowed to download the source code nor see [repository information like commits and release evidence](project/releases/index.md#view-a-release-and-download-assets).
6. Actions are limited only to records owned (referenced) by user.
7. When [Share Group Lock](group/index.md#prevent-a-project-from-being-shared-with-groups) is enabled the project can't be shared with other groups. It does not affect group with group sharing.
7. When [Share Group Lock](group/access_and_permissions.md#prevent-a-project-from-being-shared-with-groups) is enabled the project can't be shared with other groups. It does not affect group with group sharing.
8. For information on eligible approvers for merge requests, see
[Eligible approvers](project/merge_requests/approvals/rules.md#eligible-approvers).
9. Applies only to comments on [Design Management](project/issues/design_management.md) designs.
@ -412,7 +412,7 @@ The following table lists group permissions available for each role:
| Delete [group wiki](project/wiki/group.md) pages | | | ✓ | ✓ | ✓ |
| Edit [epic](group/epics/index.md) comments (posted by any user) | | | | ✓ (2) | ✓ (2) |
| List group deploy tokens | | | | ✓ | ✓ |
| Manage [group push rules](group/index.md#group-push-rules) | | | | ✓ | ✓ |
| Manage [group push rules](group/access_and_permissions.md#group-push-rules) | | | | ✓ | ✓ |
| View/manage group-level Kubernetes cluster | | | | ✓ | ✓ |
| Create and manage compliance frameworks | | | | | ✓ |
| Create/Delete group deploy tokens | | | | | ✓ |
@ -600,7 +600,7 @@ for more information.
## LDAP users permissions
LDAP user permissions can be manually overridden by an administrator.
Read through the documentation on [LDAP users permissions](group/index.md#manage-group-memberships-via-ldap) to learn more.
Read through the documentation on [LDAP users permissions](group/access_and_permissions.md#manage-group-memberships-via-ldap) to learn more.
## Project aliases

View File

@ -91,7 +91,7 @@ Each user's access is based on:
Prerequisite:
- You must have the Maintainer or Owner role.
- Sharing the project with other groups must not be [prevented](../../group/index.md#prevent-a-project-from-being-shared-with-groups).
- Sharing the project with other groups must not be [prevented](../../group/access_and_permissions.md#prevent-a-project-from-being-shared-with-groups).
To add groups to a project:
@ -173,7 +173,7 @@ To remove a member from a project:
user has not forked the private repository or created webhooks. Existing forks continue to receive
changes from the upstream project, and webhooks continue to receive updates. You may also want to configure your project
to prevent projects in a group
[from being forked outside their group](../../group/index.md#prevent-project-forking-outside-group).
[from being forked outside their group](../../group/access_and_permissions.md#prevent-project-forking-outside-group).
1. Select **Remove member**.
## Filter and sort members

View File

@ -81,4 +81,4 @@ It is possible to prevent projects in a group from [sharing
a project with another group](../members/share_project_with_groups.md).
This allows for tighter control over project access.
Learn more about [Share with group lock](../../group/index.md#prevent-a-project-from-being-shared-with-groups).
Learn more about [Share with group lock](../../group/access_and_permissions.md#prevent-a-project-from-being-shared-with-groups).

View File

@ -25,7 +25,7 @@ For custom push rules use [server hooks](../../../administration/server_hooks.md
## Enable global push rules
You can create push rules for all new projects to inherit, but they can be overridden
at the project level or the [group level](../../group/index.md#group-push-rules).
at the project level or the [group level](../../group/access_and_permissions.md#group-push-rules).
All projects created after you configure global push rules inherit this
configuration. However, each existing project must be updated manually, using the
process described in [Override global push rules per project](#override-global-push-rules-per-project).

View File

@ -2144,6 +2144,7 @@
static: |-
<p data-sourcepos="3:1-3:5" dir="auto"><a href="/url" title="title">foo</a></p>
wysiwyg: |-
<pre>[foo]: /url "title"</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__002:
canonical: |
@ -2151,6 +2152,7 @@
static: |-
<p data-sourcepos="5:1-5:5" dir="auto"><a href="/url" title="the title">foo</a></p>
wysiwyg: |-
<pre>[foo]: /url "the title"</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="the title">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__003:
canonical: |
@ -2158,6 +2160,7 @@
static: |-
<p data-sourcepos="3:1-3:11" dir="auto"><a href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
wysiwyg: |-
<pre>[foo*bar\]]: my_(url) "title (with parens)"</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
04_07__leaf_blocks__link_reference_definitions__004:
canonical: |
@ -2165,6 +2168,7 @@
static: |-
<p data-sourcepos="5:1-5:9" dir="auto"><a href="my%20url" title="title">Foo bar</a></p>
wysiwyg: |-
<pre>[foo bar]: my url "title"</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="my%20url" title="title">Foo bar</a></p>
04_07__leaf_blocks__link_reference_definitions__005:
canonical: |
@ -2180,6 +2184,11 @@
line2
">foo</a></p>
wysiwyg: |-
<pre>[foo]: /url "
title
line1
line2
"</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="
title
line1
@ -2204,6 +2213,7 @@
static: |-
<p data-sourcepos="4:1-4:5" dir="auto"><a href="/url">foo</a></p>
wysiwyg: |-
<pre>[foo]: /url</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__008:
canonical: |
@ -2221,6 +2231,7 @@
static: |-
<p data-sourcepos="3:1-3:5" dir="auto"><a href="">foo</a></p>
wysiwyg: |-
<pre>[foo]: </pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__010:
canonical: |
@ -2238,6 +2249,7 @@
static: |-
<p data-sourcepos="3:1-3:5" dir="auto"><a href="/url%5Cbar*baz" title='foo"bar\baz'>foo</a></p>
wysiwyg: |-
<pre>[foo]: /url\bar*baz "foo"bar\baz"</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url%5Cbar*baz" title="foo&quot;bar\baz">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__012:
canonical: |
@ -2246,6 +2258,7 @@
<p data-sourcepos="1:1-1:5" dir="auto"><a href="url">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="url">foo</a></p>
<pre>[foo]: url</pre>
04_07__leaf_blocks__link_reference_definitions__013:
canonical: |
<p><a href="first">foo</a></p>
@ -2253,12 +2266,15 @@
<p data-sourcepos="1:1-1:5" dir="auto"><a href="first">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="first">foo</a></p>
<pre>[foo]: first</pre>
<pre>[foo]: second</pre>
04_07__leaf_blocks__link_reference_definitions__014:
canonical: |
<p><a href="/url">Foo</a></p>
static: |-
<p data-sourcepos="3:1-3:5" dir="auto"><a href="/url">Foo</a></p>
wysiwyg: |-
<pre>[foo]: /url</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">Foo</a></p>
04_07__leaf_blocks__link_reference_definitions__015:
canonical: |
@ -2266,18 +2282,20 @@
static: |-
<p data-sourcepos="3:1-3:8" dir="auto"><a href="/%CF%86%CE%BF%CF%85">αγω</a></p>
wysiwyg: |-
<pre>[αγω]: /φου</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/%CF%86%CE%BF%CF%85">αγω</a></p>
04_07__leaf_blocks__link_reference_definitions__016:
canonical: ""
static: ""
wysiwyg: |-
<p></p>
<pre>[foo]: /url</pre>
04_07__leaf_blocks__link_reference_definitions__017:
canonical: |
<p>bar</p>
static: |-
<p data-sourcepos="1:1-4:3" dir="auto">bar</p>
wysiwyg: |-
<pre>[foo]: /url</pre>
<p>bar</p>
04_07__leaf_blocks__link_reference_definitions__018:
canonical: |
@ -2292,6 +2310,7 @@
static: |-
<p data-sourcepos="1:1-2:10" dir="auto">"title" ok</p>
wysiwyg: |-
<pre>[foo]: /url</pre>
<p>"title" ok</p>
04_07__leaf_blocks__link_reference_definitions__020:
canonical: |
@ -2349,6 +2368,7 @@
</blockquote>
wysiwyg: |-
<h1><a target="_blank" rel="noopener noreferrer nofollow" href="/url">Foo</a></h1>
<pre>[foo]: /url</pre>
<blockquote multiline="false"><p>bar</p></blockquote>
04_07__leaf_blocks__link_reference_definitions__024:
canonical: |
@ -2359,6 +2379,7 @@
<a id="user-content-bar" class="anchor" href="#bar" aria-hidden="true"></a>bar</h1>
<p data-sourcepos="4:1-4:5" dir="auto"><a href="/url">foo</a></p>
wysiwyg: |-
<pre>[foo]: /url</pre>
<h1>bar</h1>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__025:
@ -2369,6 +2390,7 @@
<p data-sourcepos="1:1-3:5" dir="auto">===
<a href="/url">foo</a></p>
wysiwyg: |-
<pre>[foo]: /url</pre>
<p>===
<a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__026:
@ -2381,6 +2403,9 @@
<a href="/bar-url" title="bar">bar</a>,
<a href="/baz-url">baz</a></p>
wysiwyg: |-
<pre>[foo]: /foo-url "foo"</pre>
<pre>[bar]: /bar-url "bar"</pre>
<pre>[baz]: /baz-url</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/foo-url" title="foo">foo</a>,
<a target="_blank" rel="noopener noreferrer nofollow" href="/bar-url" title="bar">bar</a>,
<a target="_blank" rel="noopener noreferrer nofollow" href="/baz-url">baz</a></p>
@ -2395,12 +2420,12 @@
</blockquote>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
<blockquote multiline="false"><p></p></blockquote>
<blockquote multiline="false"><pre>[foo]: /url</pre></blockquote>
04_07__leaf_blocks__link_reference_definitions__028:
canonical: ""
static: ""
wysiwyg: |-
<p></p>
<pre>[foo]: /url</pre>
04_08__leaf_blocks__paragraphs__001:
canonical: |
<p>aaa</p>
@ -4543,7 +4568,7 @@
</li>
</ul>
wysiwyg: |-
<ul bullet="*"><li><p>a</p></li><li><p>b</p></li><li><p>d</p></li></ul>
<ul bullet="*"><li><p>a</p></li><li><p>b</p><pre>[ref]: /url</pre></li><li><p>d</p></li></ul>
05_04__container_blocks__lists__018:
canonical: |
<ul>
@ -4880,6 +4905,7 @@
<p data-sourcepos="1:1-1:5" dir="auto"><a href="/bar*" title="ti*tle">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/bar*" title="ti*tle">foo</a></p>
<pre>[foo]: /bar* "ti*tle"</pre>
06_02__inlines__backslash_escapes__013:
canonical: |
<pre><code class="language-foo+bar">foo
@ -4969,6 +4995,7 @@
<p data-sourcepos="1:1-1:5" dir="auto"><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
<pre>[foo]: /föö "föö"</pre>
06_03__inlines__entity_and_numeric_character_references__010:
canonical: |
<pre><code class="language-föö">foo
@ -6475,6 +6502,7 @@
<p data-sourcepos="1:1-1:10" dir="auto"><a href="/url" title="title">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
<pre>[bar]: /url "title"</pre>
06_07__inlines__links__044:
canonical: |
<p><a href="/uri">link [foo [bar]]</a></p>
@ -6482,6 +6510,7 @@
<p data-sourcepos="1:1-1:23" dir="auto"><a href="/uri">link [foo [bar]]</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">link [foo [bar]]</a></p>
<pre>[ref]: /uri</pre>
06_07__inlines__links__045:
canonical: |
<p><a href="/uri">link [bar</a></p>
@ -6489,6 +6518,7 @@
<p data-sourcepos="1:1-1:17" dir="auto"><a href="/uri">link [bar</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">link [bar</a></p>
<pre>[ref]: /uri</pre>
06_07__inlines__links__046:
canonical: |
<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
@ -6496,6 +6526,7 @@
<p data-sourcepos="1:1-1:29" dir="auto"><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">link <em>foo </em><strong><em>bar<code>#</code></em></strong></a></p>
<pre>[ref]: /uri</pre>
06_07__inlines__links__047:
canonical: |
<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
@ -6503,6 +6534,7 @@
<p data-sourcepos="1:1-1:24" dir="auto"><a href="/uri"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="moon" decoding="async" class="lazy" data-src="moon.jpg"></a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri"><img src="moon.jpg" alt="moon"></a></p>
<pre>[ref]: /uri</pre>
06_07__inlines__links__048:
canonical: |
<p>[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>
@ -6510,6 +6542,7 @@
<p data-sourcepos="1:1-1:22" dir="auto">[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>
wysiwyg: |-
<p>[foo <a target="_blank" rel="noopener noreferrer nofollow" href="/uri">bar</a>]<a target="_blank" rel="noopener noreferrer nofollow" href="/uri">ref</a></p>
<pre>[ref]: /uri</pre>
06_07__inlines__links__049:
canonical: |
<p>[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>
@ -6517,6 +6550,7 @@
<p data-sourcepos="1:1-1:27" dir="auto">[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>
wysiwyg: |-
<p>[foo <em>bar </em><a target="_blank" rel="noopener noreferrer nofollow" href="/uri"><em>baz</em></a>]<a target="_blank" rel="noopener noreferrer nofollow" href="/uri">ref</a></p>
<pre>[ref]: /uri</pre>
06_07__inlines__links__050:
canonical: |
<p>*<a href="/uri">foo*</a></p>
@ -6524,6 +6558,7 @@
<p data-sourcepos="1:1-1:12" dir="auto">*<a href="/uri">foo*</a></p>
wysiwyg: |-
<p>*<a target="_blank" rel="noopener noreferrer nofollow" href="/uri">foo*</a></p>
<pre>[ref]: /uri</pre>
06_07__inlines__links__051:
canonical: |
<p><a href="/uri">foo *bar</a></p>
@ -6531,6 +6566,7 @@
<p data-sourcepos="1:1-1:15" dir="auto"><a href="/uri">foo *bar</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">foo *bar</a></p>
<pre>[ref]: /uri</pre>
06_07__inlines__links__052:
canonical: |
<p>[foo <bar attr="][ref]"></p>
@ -6538,6 +6574,7 @@
<p data-sourcepos="1:1-1:24" dir="auto">[foo </p>
wysiwyg: |-
<p>[foo </p>
<pre>[ref]: /uri</pre>
06_07__inlines__links__053:
canonical: |
<p>[foo<code>][ref]</code></p>
@ -6545,6 +6582,7 @@
<p data-sourcepos="1:1-1:12" dir="auto">[foo<code>][ref]</code></p>
wysiwyg: |-
<p>[foo<code>][ref]</code></p>
<pre>[ref]: /uri</pre>
06_07__inlines__links__054:
canonical: |
<p>[foo<a href="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>
@ -6552,6 +6590,7 @@
<p data-sourcepos="1:1-1:39" dir="auto">[foo<a href="http://example.com/?search=%5D%5Bref%5D" rel="nofollow noreferrer noopener" target="_blank">http://example.com/?search=][ref]</a></p>
wysiwyg: |-
<p>[foo<a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>
<pre>[ref]: /uri</pre>
06_07__inlines__links__055:
canonical: |
<p><a href="/url" title="title">foo</a></p>
@ -6559,6 +6598,7 @@
<p data-sourcepos="1:1-1:10" dir="auto"><a href="/url" title="title">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
<pre>[bar]: /url "title"</pre>
06_07__inlines__links__056:
canonical: |
<p><a href="/url">Толпой</a> is a Russian word.</p>
@ -6566,12 +6606,14 @@
<p data-sourcepos="1:1-1:47" dir="auto"><a href="/url">Толпой</a> is a Russian word.</p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">Толпой</a> is a Russian word.</p>
<pre>[толпой]: /url</pre>
06_07__inlines__links__057:
canonical: |
<p><a href="/url">Baz</a></p>
static: |-
<p data-sourcepos="4:1-4:14" dir="auto"><a href="/url">Baz</a></p>
wysiwyg: |-
<pre>[foo bar]: /url</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">Baz</a></p>
06_07__inlines__links__058:
canonical: |
@ -6580,6 +6622,7 @@
<p data-sourcepos="1:1-1:11" dir="auto">[foo] <a href="/url" title="title">bar</a></p>
wysiwyg: |-
<p>[foo] <a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">bar</a></p>
<pre>[bar]: /url "title"</pre>
06_07__inlines__links__059:
canonical: |
<p>[foo]
@ -6590,12 +6633,15 @@
wysiwyg: |-
<p>[foo]
<a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">bar</a></p>
<pre>[bar]: /url "title"</pre>
06_07__inlines__links__060:
canonical: |
<p><a href="/url1">bar</a></p>
static: |-
<p data-sourcepos="5:1-5:10" dir="auto"><a href="/url1">bar</a></p>
wysiwyg: |-
<pre>[foo]: /url1</pre>
<pre>[foo]: /url2</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url1">bar</a></p>
06_07__inlines__links__061:
canonical: |
@ -6604,6 +6650,7 @@
<p data-sourcepos="1:1-1:32" dir="auto">[bar][foo<span>!</span>]</p>
wysiwyg: |-
<p>[bar][foo!]</p>
<pre>[foo!]: /url</pre>
06_07__inlines__links__062:
canonical: |
<p>[foo][ref[]</p>
@ -6641,12 +6688,14 @@
<p data-sourcepos="1:1-1:12" dir="auto"><a href="/uri">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">foo</a></p>
<pre>[ref\[]: /uri</pre>
06_07__inlines__links__066:
canonical: |
<p><a href="/uri">bar\</a></p>
static: |-
<p data-sourcepos="3:1-3:7" dir="auto"><a href="/uri">bar\</a></p>
wysiwyg: |-
<pre>[bar\\]: /uri</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">bar\</a></p>
06_07__inlines__links__067:
canonical: |
@ -6681,6 +6730,7 @@
<p data-sourcepos="1:1-1:7" dir="auto"><a href="/url" title="title">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
<pre>[foo]: /url "title"</pre>
06_07__inlines__links__070:
canonical: |
<p><a href="/url" title="title"><em>foo</em> bar</a></p>
@ -6688,6 +6738,7 @@
<p data-sourcepos="1:1-1:13" dir="auto"><a href="/url" title="title"><em>foo</em> bar</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title"><em>foo</em> bar</a></p>
<pre>[*foo* bar]: /url "title"</pre>
06_07__inlines__links__071:
canonical: |
<p><a href="/url" title="title">Foo</a></p>
@ -6695,6 +6746,7 @@
<p data-sourcepos="1:1-1:7" dir="auto"><a href="/url" title="title">Foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">Foo</a></p>
<pre>[foo]: /url "title"</pre>
06_07__inlines__links__072:
canonical: |
<p><a href="/url" title="title">foo</a>
@ -6705,6 +6757,7 @@
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a>
[]</p>
<pre>[foo]: /url "title"</pre>
06_07__inlines__links__073:
canonical: |
<p><a href="/url" title="title">foo</a></p>
@ -6712,6 +6765,7 @@
<p data-sourcepos="1:1-1:5" dir="auto"><a href="/url" title="title">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
<pre>[foo]: /url "title"</pre>
06_07__inlines__links__074:
canonical: |
<p><a href="/url" title="title"><em>foo</em> bar</a></p>
@ -6719,6 +6773,7 @@
<p data-sourcepos="1:1-1:11" dir="auto"><a href="/url" title="title"><em>foo</em> bar</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title"><em>foo</em> bar</a></p>
<pre>[*foo* bar]: /url "title"</pre>
06_07__inlines__links__075:
canonical: |
<p>[<a href="/url" title="title"><em>foo</em> bar</a>]</p>
@ -6726,6 +6781,7 @@
<p data-sourcepos="1:1-1:13" dir="auto">[<a href="/url" title="title"><em>foo</em> bar</a>]</p>
wysiwyg: |-
<p>[<a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title"><em>foo</em> bar</a>]</p>
<pre>[*foo* bar]: /url "title"</pre>
06_07__inlines__links__076:
canonical: |
<p>[[bar <a href="/url">foo</a></p>
@ -6733,6 +6789,7 @@
<p data-sourcepos="1:1-1:11" dir="auto">[[bar <a href="/url">foo</a></p>
wysiwyg: |-
<p>[[bar <a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
<pre>[foo]: /url</pre>
06_07__inlines__links__077:
canonical: |
<p><a href="/url" title="title">Foo</a></p>
@ -6740,6 +6797,7 @@
<p data-sourcepos="1:1-1:5" dir="auto"><a href="/url" title="title">Foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">Foo</a></p>
<pre>[foo]: /url "title"</pre>
06_07__inlines__links__078:
canonical: |
<p><a href="/url">foo</a> bar</p>
@ -6747,6 +6805,7 @@
<p data-sourcepos="1:1-1:9" dir="auto"><a href="/url">foo</a> bar</p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a> bar</p>
<pre>[foo]: /url</pre>
06_07__inlines__links__079:
canonical: |
<p>[foo]</p>
@ -6754,12 +6813,14 @@
<p data-sourcepos="1:1-1:6" dir="auto">[foo]</p>
wysiwyg: |-
<p>[foo]</p>
<pre>[foo]: /url "title"</pre>
06_07__inlines__links__080:
canonical: |
<p>*<a href="/url">foo*</a></p>
static: |-
<p data-sourcepos="3:1-3:7" dir="auto">*<a href="/url">foo*</a></p>
wysiwyg: |-
<pre>[foo*]: /url</pre>
<p>*<a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo*</a></p>
06_07__inlines__links__081:
canonical: |
@ -6768,6 +6829,8 @@
<p data-sourcepos="1:1-1:10" dir="auto"><a href="/url2">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url2">foo</a></p>
<pre>[foo]: /url1</pre>
<pre>[bar]: /url2</pre>
06_07__inlines__links__082:
canonical: |
<p><a href="/url1">foo</a></p>
@ -6775,6 +6838,7 @@
<p data-sourcepos="1:1-1:7" dir="auto"><a href="/url1">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url1">foo</a></p>
<pre>[foo]: /url1</pre>
06_07__inlines__links__083:
canonical: |
<p><a href="">foo</a></p>
@ -6782,6 +6846,7 @@
<p data-sourcepos="1:1-1:7" dir="auto"><a href="">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="">foo</a></p>
<pre>[foo]: /url1</pre>
06_07__inlines__links__084:
canonical: |
<p><a href="/url1">foo</a>(not a link)</p>
@ -6789,6 +6854,7 @@
<p data-sourcepos="1:1-1:17" dir="auto"><a href="/url1">foo</a>(not a link)</p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url1">foo</a>(not a link)</p>
<pre>[foo]: /url1</pre>
06_07__inlines__links__085:
canonical: |
<p>[foo]<a href="/url">bar</a></p>
@ -6796,6 +6862,7 @@
<p data-sourcepos="1:1-1:15" dir="auto">[foo]<a href="/url">bar</a></p>
wysiwyg: |-
<p>[foo]<a target="_blank" rel="noopener noreferrer nofollow" href="/url">bar</a></p>
<pre>[baz]: /url</pre>
06_07__inlines__links__086:
canonical: |
<p><a href="/url2">foo</a><a href="/url1">baz</a></p>
@ -6803,6 +6870,8 @@
<p data-sourcepos="1:1-1:15" dir="auto"><a href="/url2">foo</a><a href="/url1">baz</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url2">foo</a><a target="_blank" rel="noopener noreferrer nofollow" href="/url1">baz</a></p>
<pre>[baz]: /url1</pre>
<pre>[bar]: /url2</pre>
06_07__inlines__links__087:
canonical: |
<p>[foo]<a href="/url1">bar</a></p>
@ -6810,6 +6879,8 @@
<p data-sourcepos="1:1-1:15" dir="auto">[foo]<a href="/url1">bar</a></p>
wysiwyg: |-
<p>[foo]<a target="_blank" rel="noopener noreferrer nofollow" href="/url1">bar</a></p>
<pre>[baz]: /url1</pre>
<pre>[foo]: /url2</pre>
06_08__inlines__images__001:
canonical: |
<p><img src="/url" alt="foo" title="title" /></p>
@ -6824,6 +6895,7 @@
<p data-sourcepos="1:1-1:12" dir="auto"><a class="no-attachment-icon" href="train.jpg" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="train &amp; tracks" decoding="async" class="lazy" data-src="train.jpg"></a></p>
wysiwyg: |-
<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks"></p>
<pre>[foo *bar*]: train.jpg "train &amp; tracks"</pre>
06_08__inlines__images__003:
canonical: |
<p><img src="/url2" alt="foo bar" /></p>
@ -6845,6 +6917,7 @@
<p data-sourcepos="1:1-1:14" dir="auto"><a class="no-attachment-icon" href="train.jpg" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="train &amp; tracks" decoding="async" class="lazy" data-src="train.jpg"></a></p>
wysiwyg: |-
<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks"></p>
<pre>[foo *bar*]: train.jpg "train &amp; tracks"</pre>
06_08__inlines__images__006:
canonical: |
<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
@ -6852,6 +6925,7 @@
<p data-sourcepos="1:1-1:20" dir="auto"><a class="no-attachment-icon" href="train.jpg" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="train &amp; tracks" decoding="async" class="lazy" data-src="train.jpg"></a></p>
wysiwyg: |-
<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks"></p>
<pre>[foobar]: train.jpg "train &amp; tracks"</pre>
06_08__inlines__images__007:
canonical: |
<p><img src="train.jpg" alt="foo" /></p>
@ -6887,6 +6961,7 @@
<p data-sourcepos="1:1-1:11" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="foo"></p>
<pre>[bar]: /url</pre>
06_08__inlines__images__012:
canonical: |
<p><img src="/url" alt="foo" /></p>
@ -6894,6 +6969,7 @@
<p data-sourcepos="1:1-1:11" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="foo"></p>
<pre>[bar]: /url</pre>
06_08__inlines__images__013:
canonical: |
<p><img src="/url" alt="foo" title="title" /></p>
@ -6901,6 +6977,7 @@
<p data-sourcepos="1:1-1:8" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="foo" title="title"></p>
<pre>[foo]: /url "title"</pre>
06_08__inlines__images__014:
canonical: |
<p><img src="/url" alt="foo bar" title="title" /></p>
@ -6908,6 +6985,7 @@
<p data-sourcepos="1:1-1:14" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="foo bar" title="title"></p>
<pre>[*foo* bar]: /url "title"</pre>
06_08__inlines__images__015:
canonical: |
<p><img src="/url" alt="Foo" title="title" /></p>
@ -6915,6 +6993,7 @@
<p data-sourcepos="1:1-1:8" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Foo" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="Foo" title="title"></p>
<pre>[foo]: /url "title"</pre>
06_08__inlines__images__016:
canonical: |
<p><img src="/url" alt="foo" title="title" />
@ -6925,6 +7004,7 @@
wysiwyg: |-
<p><img src="/url" alt="foo" title="title">
[]</p>
<pre>[foo]: /url "title"</pre>
06_08__inlines__images__017:
canonical: |
<p><img src="/url" alt="foo" title="title" /></p>
@ -6932,6 +7012,7 @@
<p data-sourcepos="1:1-1:6" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="foo" title="title"></p>
<pre>[foo]: /url "title"</pre>
06_08__inlines__images__018:
canonical: |
<p><img src="/url" alt="foo bar" title="title" /></p>
@ -6939,6 +7020,7 @@
<p data-sourcepos="1:1-1:12" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="foo bar" title="title"></p>
<pre>[*foo* bar]: /url "title"</pre>
06_08__inlines__images__019:
canonical: |
<p>![[foo]]</p>
@ -6956,6 +7038,7 @@
<p data-sourcepos="1:1-1:6" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Foo" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="Foo" title="title"></p>
<pre>[foo]: /url "title"</pre>
06_08__inlines__images__021:
canonical: |
<p>![foo]</p>
@ -6963,6 +7046,7 @@
<p data-sourcepos="1:1-1:7" dir="auto">![foo]</p>
wysiwyg: |-
<p>![foo]</p>
<pre>[foo]: /url "title"</pre>
06_08__inlines__images__022:
canonical: |
<p>!<a href="/url" title="title">foo</a></p>
@ -6970,6 +7054,7 @@
<p data-sourcepos="1:1-1:27" dir="auto"><span>!</span><a href="/url" title="title">foo</a></p>
wysiwyg: |-
<p>!<a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
<pre>[foo]: /url "title"</pre>
06_09__inlines__autolinks__001:
canonical: |
<p><a href="http://foo.bar.baz">http://foo.bar.baz</a></p>

File diff suppressed because it is too large Load Diff

View File

@ -584,12 +584,12 @@ module API
end
end
def log_artifact_size(file)
def log_artifact_file_size(file)
Gitlab::ApplicationContext.push(artifact: file.model)
end
def present_artifacts_file!(file, **args)
log_artifact_size(file) if file
log_artifact_file_size(file) if file
present_carrierwave_file!(file, **args)
end

View File

@ -41,8 +41,7 @@ module Gitlab
@unfolded = false
# Ensure items are collected in the the batch
new_blob_lazy
old_blob_lazy
add_blobs_to_batch_loader
end
def use_semantic_ipynb_diff?
@ -382,6 +381,11 @@ module Gitlab
file_path.ends_with?('.ipynb')
end
def add_blobs_to_batch_loader
new_blob_lazy
old_blob_lazy
end
private
def diffable_by_attribute?

View File

@ -36,12 +36,16 @@ module Gitlab
sleep interval_with_jitter
reports.select(&:active?).each do |report|
tms = Benchmark.measure do
report.run
end
start_monotonic_time = Gitlab::Metrics::System.monotonic_time
start_thread_cpu_time = Gitlab::Metrics::System.thread_cpu_time
log_report(report_label(report), tms)
@report_duration_counter.increment({ report: report_label(report) }, tms.real)
report.run
cpu_s = Gitlab::Metrics::System.thread_cpu_duration(start_thread_cpu_time)
duration_s = Gitlab::Metrics::System.monotonic_time - start_monotonic_time
log_report(label: report_label(report), cpu_s: cpu_s, duration_s: duration_s)
@report_duration_counter.increment({ report: report_label(report) }, duration_s)
sleep sleep_between_reports_s
end
@ -58,15 +62,14 @@ module Gitlab
sleep_s + rand(sleep_max_delta_s)
end
def log_report(report_label, tms)
def log_report(label:, duration_s:, cpu_s:)
Gitlab::AppLogger.info(
message: 'finished',
pid: $$,
worker_id: worker_id,
perf_report: report_label,
duration_s: tms.real.round(2),
cpu_s: tms.utime.round(2),
sys_cpu_s: tms.stime.round(2)
perf_report: label,
duration_s: duration_s.round(2),
cpu_s: cpu_s.round(2)
)
end

View File

@ -114,6 +114,10 @@ module Gitlab
@categories ||= known_events.map { |event| event[:category] }.uniq
end
def categories_collected_from_metrics_definitions
CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS
end
# @param category [String] the category name
# @return [Array<String>] list of event names for given category
def events_for_category(category)
@ -164,7 +168,7 @@ module Gitlab
def categories_pending_migration
if ::Feature.enabled?(:use_redis_hll_instrumentation_classes)
(categories - CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS)
(categories - categories_collected_from_metrics_definitions)
else
categories
end

View File

@ -1,25 +1,5 @@
---
# Compliance category
- name: g_compliance_dashboard
redis_slot: compliance
category: compliance
aggregation: weekly
- name: g_compliance_audit_events
category: compliance
redis_slot: compliance
aggregation: weekly
- name: i_compliance_audit_events
category: compliance
redis_slot: compliance
aggregation: weekly
- name: i_compliance_credential_inventory
category: compliance
redis_slot: compliance
aggregation: weekly
- name: a_compliance_audit_events_api
category: compliance
redis_slot: compliance
aggregation: weekly
- name: g_edit_by_web_ide
category: ide_edit
redis_slot: edit

View File

@ -0,0 +1,23 @@
# frozen_string_literal: true
module Gitlab
module Utils
module BatchLoader
# Clears batched items under the specified batch key
# https://github.com/exAspArk/batch-loader#batch-key
def self.clear_key(batch_key)
return if ::BatchLoader::Executor.current.nil?
items_to_clear = ::BatchLoader::Executor.current.items_by_block.select do |k, v|
# The Hash key here is [source_location, batch_key], so we just check k[1]
k[1] == batch_key
end
items_to_clear.each do |k, v|
::BatchLoader::Executor.current.items_by_block.delete(k)
::BatchLoader::Executor.current.loaded_values_by_block.delete(k)
end
end
end
end
end

View File

@ -11694,9 +11694,21 @@ msgstr ""
msgid "DastConfig|Enable DAST to automatically test for vulnerabilities in your project's running application, website, or API, in the CI/CD pipeline. Configuration changes must be applied to your .gitlab-ci.yml file to take effect. For details of all configuration options, see the %{linkStart}GitLab DAST documentation%{linkEnd}."
msgstr ""
msgid "DastConfig|Enabled"
msgstr ""
msgid "DastConfig|Generate code snippet"
msgstr ""
msgid "DastConfig|Last scan triggered %{runTimeAgo} in pipeline "
msgstr ""
msgid "DastConfig|No previous scans found for this project"
msgstr ""
msgid "DastConfig|Not enabled"
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."
msgstr ""
@ -28580,6 +28592,9 @@ msgstr ""
msgid "PipelineSchedules|None"
msgstr ""
msgid "PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?"
msgstr ""
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
@ -28592,6 +28607,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
msgid "PipelineSchedule|Take ownership to edit"
msgstr ""
msgid "PipelineSource|API"
msgstr ""

View File

@ -91,7 +91,6 @@
"@tiptap/vue-2": "^2.0.0-beta.84",
"apollo-upload-client": "15.0.0",
"autosize": "^5.0.1",
"aws-sdk": "^2.637.0",
"axios": "^0.24.0",
"babel-loader": "^8.2.5",
"babel-plugin-lodash": "^3.3.4",

View File

@ -82,6 +82,22 @@ RSpec.describe Projects::CommitController do
expect(response).to be_successful
end
it 'only loads blobs in the current page' do
stub_feature_flags(async_commit_diff_files: false)
stub_const('Projects::CommitController::COMMIT_DIFFS_PER_PAGE', 1)
commit = project.commit('1a0b36b3cdad1d2ee32457c102a8c0b7056fa863')
expect_next_instance_of(Repository) do |repository|
# This commit contains 3 changed files but we expect only the blobs for the first one to be loaded
expect(repository).to receive(:blobs_at).with([[commit.id, '.gitignore']], anything).and_call_original
end
go(id: commit.id)
expect(response).to be_ok
end
shared_examples "export as" do |format|
it "does generally work" do
go(id: commit.id, format: format)

View File

@ -226,8 +226,8 @@ RSpec.describe Projects::CompareController do
context 'when page is valid' do
let(:from_project_id) { nil }
let(:from_ref) { '08f22f25' }
let(:to_ref) { '66eceea0' }
let(:from_ref) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' }
let(:to_ref) { '5937ac0a7beb003549fc5fd26fc247adbce4a52e' }
let(:page) { 1 }
it 'shows the diff' do
@ -237,6 +237,21 @@ RSpec.describe Projects::CompareController do
expect(assigns(:diffs).diff_files.first).to be_present
expect(assigns(:commits).length).to be >= 1
end
it 'only loads blobs in the current page' do
stub_const('Projects::CompareController::COMMIT_DIFFS_PER_PAGE', 1)
expect_next_instance_of(Repository) do |repository|
# This comparison contains 4 changed files but we expect only the blobs for the first one to be loaded
expect(repository).to receive(:blobs_at).with(
contain_exactly([from_ref, '.gitmodules'], [to_ref, '.gitmodules']), anything
).and_call_original
end
show_request
expect(response).to be_successful
end
end
context 'when page is not valid' do

View File

@ -0,0 +1,46 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Projects::ProjectTransferedEvent do
where(:data, :valid) do
valid_event = {
project_id: 1,
old_namespace_id: 2,
old_root_namespace_id: 3,
new_namespace_id: 4,
new_root_namespace_id: 5
}
# All combinations of missing keys
with_missing_keys = 0.upto(valid_event.size - 1)
.flat_map { |size| valid_event.keys.combination(size).to_a }
.map { |keys| [valid_event.slice(*keys), false] }
[
[valid_event, true],
*with_missing_keys,
[{ project_id: 'foo', namespace_id: 2 }, false],
[{ project_id: 1, namespace_id: 'foo' }, false],
[{ project_id: [], namespace_id: 2 }, false],
[{ project_id: 1, namespace_id: [] }, false],
[{ project_id: {}, namespace_id: 2 }, false],
[{ project_id: 1, namespace_id: {} }, false],
['foo', false],
[123, false],
[[], false]
]
end
with_them do
it 'validates data' do
constructor = -> { described_class.new(data: data) }
if valid
expect { constructor.call }.not_to raise_error
else
expect { constructor.call }.to raise_error(Gitlab::EventStore::InvalidEvent)
end
end
end
end

View File

@ -109,7 +109,12 @@ RSpec.describe 'Pipeline Schedules', :js do
end
it 'changes ownership of the pipeline' do
click_link 'Take ownership'
click_button 'Take ownership'
page.within('#pipeline-take-ownership-modal') do
click_link 'Take ownership'
end
page.within('.pipeline-schedule-table-row') do
expect(page).not_to have_content('No owner')
expect(page).to have_link('Sidney Jones')

View File

@ -15,6 +15,7 @@ import Link from '~/content_editor/extensions/link';
import ListItem from '~/content_editor/extensions/list_item';
import OrderedList from '~/content_editor/extensions/ordered_list';
import Paragraph from '~/content_editor/extensions/paragraph';
import ReferenceDefinition from '~/content_editor/extensions/reference_definition';
import Sourcemap from '~/content_editor/extensions/sourcemap';
import Strike from '~/content_editor/extensions/strike';
import Table from '~/content_editor/extensions/table';
@ -45,6 +46,7 @@ const tiptapEditor = createTestEditor({
Link,
ListItem,
OrderedList,
ReferenceDefinition,
Sourcemap,
Strike,
Table,
@ -78,6 +80,7 @@ const {
listItem,
orderedList,
pre,
referenceDefinition,
strike,
table,
tableRow,
@ -105,6 +108,7 @@ const {
listItem: { nodeType: ListItem.name },
orderedList: { nodeType: OrderedList.name },
paragraph: { nodeType: Paragraph.name },
referenceDefinition: { nodeType: ReferenceDefinition.name },
strike: { nodeType: Strike.name },
table: { nodeType: Table.name },
tableCell: { nodeType: TableCell.name },
@ -1079,6 +1083,32 @@ _world_.
),
),
},
{
markdown: `
[GitLab][gitlab-url]
[gitlab-url]: https://gitlab.com "GitLab"
`,
expectedDoc: doc(
paragraph(
source('[GitLab][gitlab-url]'),
link(
{ ...source('[GitLab][gitlab-url]'), href: 'https://gitlab.com', title: 'GitLab' },
'GitLab',
),
),
referenceDefinition(
{
...source('[gitlab-url]: https://gitlab.com "GitLab"'),
identifier: 'gitlab-url',
url: 'https://gitlab.com',
title: 'GitLab',
},
'[gitlab-url]: https://gitlab.com "GitLab"',
),
),
},
];
const runOnly = examples.find((example) => example.only === true);

View File

@ -26,6 +26,7 @@ import Italic from '~/content_editor/extensions/italic';
import Link from '~/content_editor/extensions/link';
import ListItem from '~/content_editor/extensions/list_item';
import OrderedList from '~/content_editor/extensions/ordered_list';
import ReferenceDefinition from '~/content_editor/extensions/reference_definition';
import Strike from '~/content_editor/extensions/strike';
import Table from '~/content_editor/extensions/table';
import TableCell from '~/content_editor/extensions/table_cell';
@ -63,6 +64,7 @@ const tiptapEditor = createTestEditor({
Link,
ListItem,
OrderedList,
ReferenceDefinition,
Strike,
Table,
TableCell,

View File

@ -24,6 +24,7 @@ import Link from '~/content_editor/extensions/link';
import ListItem from '~/content_editor/extensions/list_item';
import OrderedList from '~/content_editor/extensions/ordered_list';
import Paragraph from '~/content_editor/extensions/paragraph';
import ReferenceDefinition from '~/content_editor/extensions/reference_definition';
import Sourcemap from '~/content_editor/extensions/sourcemap';
import Strike from '~/content_editor/extensions/strike';
import Table from '~/content_editor/extensions/table';
@ -63,6 +64,7 @@ const tiptapEditor = createTestEditor({
Link,
ListItem,
OrderedList,
ReferenceDefinition,
Sourcemap,
Strike,
Table,
@ -104,6 +106,7 @@ const {
listItem,
orderedList,
paragraph,
referenceDefinition,
strike,
table,
tableCell,
@ -139,6 +142,7 @@ const {
listItem: { nodeType: ListItem.name },
orderedList: { nodeType: OrderedList.name },
paragraph: { nodeType: Paragraph.name },
referenceDefinition: { nodeType: ReferenceDefinition.name },
strike: { markType: Strike.name },
table: { nodeType: Table.name },
tableCell: { nodeType: TableCell.name },
@ -1163,6 +1167,38 @@ Oranges are orange [^1]
);
});
it('correctly serializes reference definition', () => {
expect(
serialize(
referenceDefinition('[gitlab]: https://gitlab.com'),
referenceDefinition('[foobar]: foobar.com'),
),
).toBe(
`
[gitlab]: https://gitlab.com
[foobar]: foobar.com`.trimLeft(),
);
});
it('correctly adds a space between a reference definition and a block content', () => {
expect(
serialize(
paragraph('paragraph'),
referenceDefinition('[gitlab]: https://gitlab.com'),
referenceDefinition('[foobar]: foobar.com'),
heading({ level: 2 }, 'heading'),
),
).toBe(
`
paragraph
[gitlab]: https://gitlab.com
[foobar]: foobar.com
## heading`.trimLeft(),
);
});
const defaultEditAction = (initialContent) => {
tiptapEditor.chain().setContent(initialContent.toJSON()).insertContent(' modified').run();
};

View File

@ -96,28 +96,60 @@ describe('gfm', () => {
);
});
});
});
describe('when skipping the rendering of code blocks', () => {
it('transforms code nodes into codeblock html tags', async () => {
const result = await markdownToAST(
`
describe('when skipping the rendering of code blocks', () => {
it('transforms code nodes into codeblock html tags', async () => {
const result = await markdownToAST(
`
\`\`\`javascript
console.log('Hola');
\`\`\`\
`,
['code'],
);
['code'],
);
expectInRoot(
result,
expect.objectContaining({
tagName: 'codeblock',
properties: {
language: 'javascript',
},
}),
);
expectInRoot(
result,
expect.objectContaining({
tagName: 'codeblock',
properties: {
language: 'javascript',
},
}),
);
});
});
describe('when skipping the rendering of reference definitions', () => {
it('transforms code nodes into codeblock html tags', async () => {
const result = await markdownToAST(
`
[gitlab][gitlab]
[gitlab]: https://gitlab.com "GitLab"
`,
['definition'],
);
expectInRoot(
result,
expect.objectContaining({
type: 'element',
tagName: 'referencedefinition',
properties: {
identifier: 'gitlab',
title: 'GitLab',
url: 'https://gitlab.com',
},
children: [
{
type: 'text',
value: '[gitlab]: https://gitlab.com "GitLab"',
},
],
}),
);
});
});
});
});

View File

@ -0,0 +1,54 @@
import { GlModal } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import TakeOwnershipModal from '~/pipeline_schedules/components/take_ownership_modal.vue';
describe('Take ownership modal', () => {
let wrapper;
const url = `/root/job-log-tester/-/pipeline_schedules/3/take_ownership`;
const createComponent = (props = {}) => {
wrapper = shallowMountExtended(TakeOwnershipModal, {
propsData: {
ownershipUrl: url,
...props,
},
});
};
const findModal = () => wrapper.findComponent(GlModal);
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('has a primary action set to a url and a post data-method', () => {
const actionPrimary = findModal().props('actionPrimary');
expect(actionPrimary.attributes).toEqual(
expect.objectContaining([
{
category: 'primary',
variant: 'confirm',
href: url,
'data-method': 'post',
},
]),
);
});
it('shows a take ownership message', () => {
expect(findModal().text()).toBe(
'Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?',
);
});
it('emits the cancel event when clicking on cancel', async () => {
findModal().vm.$emit('cancel');
expect(findModal().emitted('cancel')).toBeTruthy();
});
});

View File

@ -61,29 +61,38 @@ describe('content_editor', () => {
});
});
it('renders footnote ids alongside the footnote definition', async () => {
buildWrapper();
describe('when preserveUnchangedMarkdown feature flag is enabled', () => {
beforeEach(() => {
gon.features = { preserveUnchangedMarkdown: true };
});
afterEach(() => {
gon.features = { preserveUnchangedMarkdown: false };
});
renderMarkdown.mockResolvedValue(`
<p data-sourcepos="3:1-3:56" dir="auto">
This reference tag is a mix of letters and numbers. <sup class="footnote-ref"><a href="#fn-footnote-2717" id="fnref-footnote-2717" data-footnote-ref="">2</a></sup>
</p>
<section class="footnotes" data-footnotes>
<ol>
<li id="fn-footnote-2717">
<p data-sourcepos="6:7-6:31">This is another footnote. <a href="#fnref-footnote-2717" aria-label="Back to content" class="footnote-backref" data-footnote-backref=""><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1"></gl-emoji></a></p>
</li>
</ol>
</section>
it('processes and renders footnote ids alongside the footnote definition', async () => {
buildWrapper();
await contentEditorService.setSerializedContent(`
This reference tag is a mix of letters and numbers [^footnote].
[^footnote]: This is another footnote.
`);
await nextTick();
await contentEditorService.setSerializedContent(`
This reference tag is a mix of letters and numbers [^footnote].
expect(wrapper.text()).toContain('footnote: This is another footnote');
});
[^footnote]: This is another footnote.
`);
await nextTick();
it('processes and displays reference definitions', async () => {
buildWrapper();
expect(wrapper.text()).toContain('footnote: This is another footnote');
await contentEditorService.setSerializedContent(`
[GitLab][gitlab]
[gitlab]: https://gitlab.com
`);
await nextTick();
expect(wrapper.find('pre').text()).toContain('[gitlab]: https://gitlab.com');
});
});
});

View File

@ -153,16 +153,24 @@ RSpec.describe CommitsHelper do
end
describe "#conditionally_paginate_diff_files" do
let(:diffs_collection) { instance_double(Gitlab::Diff::FileCollection::Commit, diff_files: diff_files) }
let(:diff_files) { Gitlab::Git::DiffCollection.new(files) }
let(:page) { nil }
let_it_be(:project) { create(:project, :repository) }
let(:diffs_collection) { instance_double(Gitlab::Diff::FileCollection::Commit, diff_files: decorated_diff_files, project: project) }
let(:decorated_diff_files) do
diffs.map do |diff|
Gitlab::Diff::File.new(diff, repository: project.repository)
end
end
let(:diffs) { Gitlab::Git::DiffCollection.new(files) }
let(:files) do
Array.new(85).map do
{ too_large: false, diff: "" }
end
end
let(:page) { nil }
subject { helper.conditionally_paginate_diff_files(diffs_collection, paginate: paginate, page: page, per: Projects::CommitController::COMMIT_DIFFS_PER_PAGE) }
before do
@ -203,8 +211,8 @@ RSpec.describe CommitsHelper do
context "pagination is disabled" do
let(:paginate) { false }
it "returns a standard DiffCollection" do
expect(subject).to be_a(Gitlab::Git::DiffCollection)
it "returns the unpaginated collection" do
expect(subject.size).to eq(85)
end
end
end

View File

@ -727,6 +727,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
context 'signup with linked omniauth and LDAP account' do
before do
stub_omniauth_config(auto_link_ldap_user: true)
stub_ldap_setting(enabled: true)
allow(ldap_user).to receive(:uid) { uid }
allow(ldap_user).to receive(:username) { uid }
allow(ldap_user).to receive(:email) { ['johndoe@example.com', 'john2@example.com'] }

View File

@ -32,7 +32,6 @@ RSpec.describe Gitlab::Memory::ReportsDaemon do
hash_including(
:duration_s,
:cpu_s,
:sys_cpu_s,
message: 'finished',
pid: Process.pid,
worker_id: 'worker_1',

View File

@ -82,7 +82,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
stub_feature_flags(use_redis_hll_instrumentation_classes: true)
expect(described_class.unique_events_data.keys)
.not_to include(*described_class::CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS)
.not_to include(*described_class.categories_collected_from_metrics_definitions)
end
end
@ -91,18 +91,17 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
stub_feature_flags(use_redis_hll_instrumentation_classes: false)
expect(described_class.unique_events_data.keys)
.to include(*described_class::CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS)
.to include(*described_class.categories_collected_from_metrics_definitions)
end
end
end
end
describe '.categories' do
it 'gets all unique category names' do
expect(described_class.categories).to contain_exactly(
it 'gets CE unique category names' do
expect(described_class.categories).to include(
'deploy_token_packages',
'user_packages',
'compliance',
'ecosystem',
'analytics',
'ide_edit',
@ -483,7 +482,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
describe '.weekly_redis_keys' do
using RSpec::Parameterized::TableSyntax
let(:weekly_event) { 'g_compliance_dashboard' }
let(:weekly_event) { 'i_search_total' }
let(:redis_event) { described_class.send(:event_for, weekly_event) }
subject(:weekly_redis_keys) { described_class.send(:weekly_redis_keys, events: [redis_event], start_date: DateTime.parse(start_date), end_date: DateTime.parse(end_date)) }
@ -493,13 +492,13 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
'2020-12-21' | '2020-12-20' | []
'2020-12-21' | '2020-11-21' | []
'2021-01-01' | '2020-12-28' | []
'2020-12-21' | '2020-12-28' | ['g_{compliance}_dashboard-2020-52']
'2020-12-21' | '2021-01-01' | ['g_{compliance}_dashboard-2020-52']
'2020-12-27' | '2021-01-01' | ['g_{compliance}_dashboard-2020-52']
'2020-12-26' | '2021-01-04' | ['g_{compliance}_dashboard-2020-52', 'g_{compliance}_dashboard-2020-53']
'2020-12-26' | '2021-01-11' | ['g_{compliance}_dashboard-2020-52', 'g_{compliance}_dashboard-2020-53', 'g_{compliance}_dashboard-2021-01']
'2020-12-26' | '2021-01-17' | ['g_{compliance}_dashboard-2020-52', 'g_{compliance}_dashboard-2020-53', 'g_{compliance}_dashboard-2021-01']
'2020-12-26' | '2021-01-18' | ['g_{compliance}_dashboard-2020-52', 'g_{compliance}_dashboard-2020-53', 'g_{compliance}_dashboard-2021-01', 'g_{compliance}_dashboard-2021-02']
'2020-12-21' | '2020-12-28' | ['i_{search}_total-2020-52']
'2020-12-21' | '2021-01-01' | ['i_{search}_total-2020-52']
'2020-12-27' | '2021-01-01' | ['i_{search}_total-2020-52']
'2020-12-26' | '2021-01-04' | ['i_{search}_total-2020-52', 'i_{search}_total-2020-53']
'2020-12-26' | '2021-01-11' | ['i_{search}_total-2020-52', 'i_{search}_total-2020-53', 'i_{search}_total-2021-01']
'2020-12-26' | '2021-01-17' | ['i_{search}_total-2020-52', 'i_{search}_total-2020-53', 'i_{search}_total-2021-01']
'2020-12-26' | '2021-01-18' | ['i_{search}_total-2020-52', 'i_{search}_total-2020-53', 'i_{search}_total-2021-01', 'i_{search}_total-2021-02']
end
with_them do

View File

@ -0,0 +1,82 @@
# frozen_string_literal: true
require 'fast_spec_helper'
require 'batch-loader'
RSpec.describe Gitlab::Utils::BatchLoader do
let(:stubbed_loader) do
double( # rubocop:disable RSpec/VerifiedDoubles
'Loader',
load_lazy_method: [],
load_lazy_method_same_batch_key: [],
load_lazy_method_other_batch_key: []
)
end
let(:test_module) do
Module.new do
def self.lazy_method(id)
BatchLoader.for(id).batch(key: :my_batch_name) do |ids, loader|
stubbed_loader.load_lazy_method(ids)
ids.each { |id| loader.call(id, id) }
end
end
def self.lazy_method_same_batch_key(id)
BatchLoader.for(id).batch(key: :my_batch_name) do |ids, loader|
stubbed_loader.load_lazy_method_same_batch_key(ids)
ids.each { |id| loader.call(id, id) }
end
end
def self.lazy_method_other_batch_key(id)
BatchLoader.for(id).batch(key: :other_batch_name) do |ids, loader|
stubbed_loader.load_lazy_method_other_batch_key(ids)
ids.each { |id| loader.call(id, id) }
end
end
end
end
before do
BatchLoader::Executor.clear_current
allow(test_module).to receive(:stubbed_loader).and_return(stubbed_loader)
end
describe '.clear_key' do
it 'clears batched items which match the specified batch key' do
test_module.lazy_method(1)
test_module.lazy_method_same_batch_key(2)
test_module.lazy_method_other_batch_key(3)
described_class.clear_key(:my_batch_name)
test_module.lazy_method(4).to_i
test_module.lazy_method_same_batch_key(5).to_i
test_module.lazy_method_other_batch_key(6).to_i
expect(stubbed_loader).to have_received(:load_lazy_method).with([4])
expect(stubbed_loader).to have_received(:load_lazy_method_same_batch_key).with([5])
expect(stubbed_loader).to have_received(:load_lazy_method_other_batch_key).with([3, 6])
end
it 'clears loaded values which match the specified batch key' do
test_module.lazy_method(1).to_i
test_module.lazy_method_same_batch_key(2).to_i
test_module.lazy_method_other_batch_key(3).to_i
described_class.clear_key(:my_batch_name)
test_module.lazy_method(1).to_i
test_module.lazy_method_same_batch_key(2).to_i
test_module.lazy_method_other_batch_key(3).to_i
expect(stubbed_loader).to have_received(:load_lazy_method).with([1]).twice
expect(stubbed_loader).to have_received(:load_lazy_method_same_batch_key).with([2]).twice
expect(stubbed_loader).to have_received(:load_lazy_method_other_batch_key).with([3])
end
end
end

View File

@ -844,7 +844,13 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
'Content-Disposition' => %q(attachment; filename="ci_build_artifacts.zip"; filename*=UTF-8''ci_build_artifacts.zip) }
end
before do
allow(Gitlab::ApplicationContext).to receive(:push).and_call_original
end
it 'downloads artifacts' do
expect(Gitlab::ApplicationContext).to receive(:push).with(artifact: an_instance_of(Ci::JobArtifact)).once.and_call_original
download_artifact
expect(response).to have_gitlab_http_status(:ok)

View File

@ -64,6 +64,28 @@ RSpec.describe Projects::TransferService do
expect(project.namespace).to eq(group)
end
context 'EventStore' do
let(:group) do
create(:group, :nested).tap { |g| g.add_owner(user) }
end
let(:target) do
create(:group, :nested).tap { |g| g.add_owner(user) }
end
it 'publishes a ProjectTransferedEvent' do
expect { execute_transfer }
.to publish_event(Projects::ProjectTransferedEvent)
.with(
project_id: kind_of(Numeric),
old_namespace_id: group.id,
old_root_namespace_id: group.parent_id,
new_namespace_id: target.id,
new_root_namespace_id: target.parent_id
)
end
end
context 'when project has an associated project namespace' do
it 'keeps project namespace in sync with project' do
transfer_result = execute_transfer
@ -299,6 +321,11 @@ RSpec.describe Projects::TransferService do
)
end
it 'does not publish a ProjectTransferedEvent' do
expect { attempt_project_transfer }
.not_to publish_event(Projects::ProjectTransferedEvent)
end
context 'when project has pending builds', :sidekiq_inline do
let!(:other_project) { create(:project) }
let!(:pending_build) { create(:ci_pending_build, project: project.reload) }

View File

@ -0,0 +1,81 @@
# frozen_string_literal: true
# rubocop:disable Style/RedundantFetchBlock
#
require 'spec_helper'
RSpec.describe ProtectedBranches::CacheService, :clean_gitlab_redis_cache do
subject(:service) { described_class.new(project, user) }
let_it_be(:project) { create(:project) }
let_it_be(:user) { project.first_owner }
let(:immediate_expiration) { 0 }
describe '#fetch' do
it 'caches the value' do
expect(service.fetch('main') { true }).to eq(true)
expect(service.fetch('not-found') { false }).to eq(false)
# Uses cached values
expect(service.fetch('main') { false }).to eq(true)
expect(service.fetch('not-found') { true }).to eq(false)
end
it 'sets expiry on the key' do
stub_const("#{described_class.name}::CACHE_EXPIRE_IN", immediate_expiration)
expect(service.fetch('main') { true }).to eq(true)
expect(service.fetch('not-found') { false }).to eq(false)
expect(service.fetch('main') { false }).to eq(false)
expect(service.fetch('not-found') { true }).to eq(true)
end
it 'does not set an expiry on the key after the hash is already created' do
expect(service.fetch('main') { true }).to eq(true)
stub_const("#{described_class.name}::CACHE_EXPIRE_IN", immediate_expiration)
expect(service.fetch('not-found') { false }).to eq(false)
expect(service.fetch('main') { false }).to eq(true)
expect(service.fetch('not-found') { true }).to eq(false)
end
context 'when CACHE_LIMIT is exceeded' do
before do
stub_const("#{described_class.name}::CACHE_LIMIT", 2)
end
it 'recreates cache' do
expect(service.fetch('main') { true }).to eq(true)
expect(service.fetch('not-found') { false }).to eq(false)
# Uses cached values
expect(service.fetch('main') { false }).to eq(true)
expect(service.fetch('not-found') { true }).to eq(false)
# Overflow
expect(service.fetch('new-branch') { true }).to eq(true)
# Refreshes values
expect(service.fetch('main') { false }).to eq(false)
expect(service.fetch('not-found') { true }).to eq(true)
end
end
end
describe '#refresh' do
it 'clears cached values' do
expect(service.fetch('main') { true }).to eq(true)
expect(service.fetch('not-found') { false }).to eq(false)
service.refresh
# Recreates cache
expect(service.fetch('main') { false }).to eq(false)
expect(service.fetch('not-found') { true }).to eq(true)
end
end
end
# rubocop:enable Style/RedundantFetchBlock

View File

@ -24,6 +24,14 @@ RSpec.describe ProtectedBranches::CreateService do
expect(project.protected_branches.last.merge_access_levels.map(&:access_level)).to eq([Gitlab::Access::MAINTAINER])
end
it 'refreshes the cache' do
expect_next_instance_of(ProtectedBranches::CacheService) do |cache_service|
expect(cache_service).to receive(:refresh)
end
service.execute
end
context 'when protecting a branch with a name that contains HTML tags' do
let(:name) { 'foo<b>bar<\b>' }

View File

@ -16,6 +16,14 @@ RSpec.describe ProtectedBranches::DestroyService do
expect(protected_branch).to be_destroyed
end
it 'refreshes the cache' do
expect_next_instance_of(ProtectedBranches::CacheService) do |cache_service|
expect(cache_service).to receive(:refresh)
end
service.execute(protected_branch)
end
context 'when a policy restricts rule deletion' do
before do
policy = instance_double(ProtectedBranchPolicy, allowed?: false)

View File

@ -18,6 +18,14 @@ RSpec.describe ProtectedBranches::UpdateService do
expect(result.reload.name).to eq(params[:name])
end
it 'refreshes the cache' do
expect_next_instance_of(ProtectedBranches::CacheService) do |cache_service|
expect(cache_service).to receive(:refresh)
end
result
end
context 'when updating name of a protected branch to one that contains HTML tags' do
let(:new_name) { 'foo<b>bar<\b>' }
let(:result) { service.execute(protected_branch) }

View File

@ -28,7 +28,7 @@ RSpec.describe 'projects/pipeline_schedules/_pipeline_schedule' do
it 'non-owner can take ownership of pipeline' do
render
expect(rendered).to have_link('Take ownership')
expect(rendered).to have_button('Take ownership')
end
end
@ -42,7 +42,7 @@ RSpec.describe 'projects/pipeline_schedules/_pipeline_schedule' do
it 'owner cannot take ownership of pipeline' do
render
expect(rendered).not_to have_link('Take ownership')
expect(rendered).not_to have_button('Take ownership')
end
end
end

View File

@ -2744,21 +2744,6 @@ autosize@^5.0.1:
resolved "https://registry.yarnpkg.com/autosize/-/autosize-5.0.1.tgz#ed269b0fa9b7eb47627048a1bb3299e99e003a0f"
integrity sha512-UIWUlE4TOVPNNj2jjrU39wI4hEYbneUypEqcyRmRFIx5CC2gNdg3rQr+Zh7/3h6egbBvm33TDQjNQKtj9Tk1HA==
aws-sdk@^2.637.0:
version "2.637.0"
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.637.0.tgz#810e25e53acf2250d35fc74498f9d4492e154217"
integrity sha512-e7EYX5rNtQyEaleQylUtLSNKXOmvOwfifQ4bYkfF80mFsVI3DSydczLHXrqPzXoEJaS/GI/9HqVnlQcPs6Q3ew==
dependencies:
buffer "4.9.1"
events "1.1.1"
ieee754 "1.1.13"
jmespath "0.15.0"
querystring "0.2.0"
sax "1.2.1"
url "0.10.3"
uuid "3.3.2"
xml2js "0.4.19"
axios-mock-adapter@^1.15.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/axios-mock-adapter/-/axios-mock-adapter-1.15.0.tgz#fbc06825d8302c95c3334d21023bba996255d45d"
@ -3137,7 +3122,7 @@ buffer-xor@^1.0.3:
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
buffer@4.9.1, buffer@^4.3.0:
buffer@^4.3.0:
version "4.9.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=
@ -5444,11 +5429,6 @@ eventemitter3@^4.0.0:
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
events@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=
events@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88"
@ -6582,7 +6562,7 @@ icss-utils@^4.1.0:
dependencies:
postcss "^7.0.14"
ieee754@1.1.13, ieee754@^1.1.13, ieee754@^1.1.4:
ieee754@^1.1.13, ieee754@^1.1.4:
version "1.1.13"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==
@ -7528,11 +7508,6 @@ jest@^26.5.2:
import-local "^3.0.2"
jest-cli "^26.5.2"
jmespath@0.15.0:
version "0.15.0"
resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217"
integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=
jquery.caret@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/jquery.caret/-/jquery.caret-0.3.1.tgz#9c093318faf327eff322e826ca9f3241368bc7b8"
@ -10598,11 +10573,6 @@ sass@^1.49.9:
immutable "^4.0.0"
source-map-js ">=0.6.2 <2.0.0"
sax@1.2.1, sax@>=0.6.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a"
integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o=
saxes@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d"
@ -12004,14 +11974,6 @@ url-loader@^4.1.1:
mime-types "^2.1.27"
schema-utils "^3.0.0"
url@0.10.3:
version "0.10.3"
resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64"
integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=
dependencies:
punycode "1.3.2"
querystring "0.2.0"
url@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
@ -12049,11 +12011,6 @@ utils-merge@1.0.1:
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
uuid@3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
uuid@8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d"
@ -12634,24 +12591,11 @@ xml-name-validator@^3.0.0:
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
xml2js@0.4.19:
version "0.4.19"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7"
integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==
dependencies:
sax ">=0.6.0"
xmlbuilder "~9.0.1"
xml@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"
integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=
xmlbuilder@~9.0.1:
version "9.0.7"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=
xmlchars@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"