Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
534ce3b2d0
commit
6fd670b99b
|
|
@ -684,7 +684,7 @@
|
|||
{"name":"uniform_notifier","version":"1.16.0","platform":"ruby","checksum":"99b39ee4a0864e3b49f375b5e5803eb26d35ed6eb1719c96407573a87bc4dbb5"},
|
||||
{"name":"unleash","version":"3.2.2","platform":"ruby","checksum":"0f6e56498de920de66a01bceffb93933693ade646bb853fc70eb16bd1026b93b"},
|
||||
{"name":"unparser","version":"0.6.7","platform":"ruby","checksum":"ae42e73edfa273766e66c166368fb75ca5972cd8ec50c536253e0f6299a9dec8"},
|
||||
{"name":"uri","version":"0.12.2","platform":"ruby","checksum":"be79bd8017858c9fc36c78765c69e92b6a7e049ea6a83364909476ad1b4b4439"},
|
||||
{"name":"uri","version":"0.13.0","platform":"ruby","checksum":"26553c2a9399762e1e8bebd4444b4361c4b21298cf1c864b22eeabc9c4998f24"},
|
||||
{"name":"uri_template","version":"0.7.0","platform":"ruby","checksum":"312c8fe13700db86ac9d05ea997af3db03abdf50c65b1801d775bc7a695f185d"},
|
||||
{"name":"valid_email","version":"0.1.3","platform":"ruby","checksum":"b81452b51b64c4beb67913f68db52c20ecb4d73d45512f5b282ab4a3f4416570"},
|
||||
{"name":"validate_email","version":"0.1.6","platform":"ruby","checksum":"9dfe9016d527b17a8d3a6e95e4dc50a125400eef899d13d4cc2a254393f82ee4"},
|
||||
|
|
|
|||
|
|
@ -1722,7 +1722,7 @@ GEM
|
|||
unparser (0.6.7)
|
||||
diff-lcs (~> 1.3)
|
||||
parser (>= 3.2.0)
|
||||
uri (0.12.2)
|
||||
uri (0.13.0)
|
||||
uri_template (0.7.0)
|
||||
valid_email (0.1.3)
|
||||
activemodel
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import {
|
|||
GlBadge,
|
||||
GlLoadingIcon,
|
||||
GlTable,
|
||||
GlTooltipDirective,
|
||||
GlPagination,
|
||||
GlButton,
|
||||
GlModalDirective,
|
||||
|
|
@ -27,6 +28,7 @@ export default {
|
|||
},
|
||||
directives: {
|
||||
GlModal: GlModalDirective,
|
||||
GlTooltip: GlTooltipDirective,
|
||||
},
|
||||
i18n: {
|
||||
emptyGroupMessage: s__('Badges|This group has no badges. Add an existing badge or create one.'),
|
||||
|
|
@ -107,19 +109,26 @@ export default {
|
|||
:current-page="currentPage"
|
||||
stacked="md"
|
||||
show-empty
|
||||
class="b-table-fixed"
|
||||
data-testid="badge-list"
|
||||
>
|
||||
<template #cell(name)="{ item }">
|
||||
<label class="label-bold str-truncated mb-0">{{ item.name }}</label>
|
||||
<label v-gl-tooltip class="label-bold str-truncated mb-0" :title="item.name">{{
|
||||
item.name
|
||||
}}</label>
|
||||
<gl-badge size="sm">{{ badgeKindText(item) }}</gl-badge>
|
||||
</template>
|
||||
|
||||
<template #cell(badge)="{ item }">
|
||||
<badge :image-url="item.renderedImageUrl" :link-url="item.renderedLinkUrl" />
|
||||
<div class="overflow-hidden">
|
||||
<badge :image-url="item.renderedImageUrl" :link-url="item.renderedLinkUrl" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #cell(url)="{ item }">
|
||||
{{ item.linkUrl }}
|
||||
<span v-gl-tooltip :title="item.linkUrl" class="str-truncated">
|
||||
{{ item.linkUrl }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template #cell(actions)="{ item }">
|
||||
|
|
|
|||
|
|
@ -161,6 +161,8 @@ export default {
|
|||
</div>
|
||||
</div>
|
||||
</gl-tab>
|
||||
|
||||
<slot name="ee-workspaces-tab" :agent-name="agentName" :project-path="projectPath"></slot>
|
||||
</gl-tabs>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@
|
|||
@import 'page_specific_files';
|
||||
|
||||
// Component specific styles, will be moved to gitlab-ui
|
||||
@import 'components/**/*';
|
||||
@import 'components/index';
|
||||
|
||||
// Vendors specific styles
|
||||
@import 'vendors/**/*';
|
||||
@import 'vendors/index';
|
||||
|
||||
// Styles for JS behaviors.
|
||||
@import 'behaviors';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
@import './avatar';
|
||||
@import './collapsible_card';
|
||||
@import './content_editor';
|
||||
@import './deployment_instance';
|
||||
@import './detail_page';
|
||||
@import './ref_selector';
|
||||
@import './related_items_list';
|
||||
@import './severity/icons';
|
||||
@import './shortcuts_help';
|
||||
@import './upload_dropzone/upload_dropzone';
|
||||
@import './whats_new';
|
||||
|
|
@ -130,6 +130,11 @@
|
|||
|
||||
.gl-pipeline-job-width {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
|
||||
.pipeline-graph-container & {
|
||||
max-width: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.gl-pipeline-job-width\! {
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
@import './atwho';
|
||||
|
|
@ -2189,7 +2189,7 @@ class MergeRequest < ApplicationRecord
|
|||
attr_accessor :skip_fetch_ref
|
||||
|
||||
def merge_base_pipelines
|
||||
return ::Ci::Pipeline.none unless actual_head_pipeline
|
||||
return ::Ci::Pipeline.none unless actual_head_pipeline&.target_sha
|
||||
|
||||
target_branch_pipelines_for(sha: actual_head_pipeline.target_sha)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
.login-box.gl-p-5
|
||||
.login-body
|
||||
- if @user.two_factor_enabled?
|
||||
= gitlab_ui_form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if @user.two_factor_webauthn_enabled?}" }) do |f|
|
||||
= gitlab_ui_form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: "gl-show-field-errors js-2fa-form #{'hidden' if @user.two_factor_webauthn_enabled?}", aria: { live: 'assertive' }}) do |f|
|
||||
.form-group
|
||||
= f.label :otp_attempt, _('Enter verification code')
|
||||
= f.text_field :otp_attempt, class: 'form-control gl-form-input', required: true, autofocus: true, autocomplete: 'off', inputmode: 'numeric', title: _('This field is required.'), data: { testid: 'two-fa-code-field' }
|
||||
|
|
|
|||
|
|
@ -3,26 +3,27 @@
|
|||
%label.label-bold.gl-mb-0
|
||||
= s_('Profiles|Connected Accounts')
|
||||
%p= s_('Profiles|Select a service to sign in with.')
|
||||
- providers.each do |provider|
|
||||
- unlink_allowed = unlink_provider_allowed?(provider)
|
||||
- link_allowed = link_provider_allowed?(provider)
|
||||
- has_icon = provider_has_icon?(provider)
|
||||
- if unlink_allowed || link_allowed
|
||||
- if auth_active?(provider)
|
||||
- if unlink_allowed
|
||||
= link_to unlink_profile_account_path(provider: provider), method: :delete, class: button_class do
|
||||
.gl-display-flex.gl-flex-wrap.gl-gap-3
|
||||
- providers.each do |provider|
|
||||
- unlink_allowed = unlink_provider_allowed?(provider)
|
||||
- link_allowed = link_provider_allowed?(provider)
|
||||
- has_icon = provider_has_icon?(provider)
|
||||
- if unlink_allowed || link_allowed
|
||||
- if auth_active?(provider)
|
||||
- if unlink_allowed
|
||||
= link_to unlink_profile_account_path(provider: provider), method: :delete, class: button_class do
|
||||
- if has_icon
|
||||
.social-provider-btn-image.gl-button-icon= provider_image_tag(provider)
|
||||
.gl-button-text
|
||||
= s_('Profiles|Disconnect %{provider}') % { provider: label_for_provider(provider) }
|
||||
- else
|
||||
%a{ class: button_class }
|
||||
.gl-button-text
|
||||
= s_('Profiles|%{provider} Active') % { provider: label_for_provider(provider) }
|
||||
- elsif link_allowed
|
||||
= link_to omniauth_authorize_path(:user, provider), method: :post, class: button_class do
|
||||
- if has_icon
|
||||
.social-provider-btn-image.gl-button-icon= provider_image_tag(provider)
|
||||
.gl-button-text
|
||||
= s_('Profiles|Disconnect %{provider}') % { provider: label_for_provider(provider) }
|
||||
- else
|
||||
%a{ class: button_class }
|
||||
.gl-button-text
|
||||
= s_('Profiles|%{provider} Active') % { provider: label_for_provider(provider) }
|
||||
- elsif link_allowed
|
||||
= link_to omniauth_authorize_path(:user, provider), method: :post, class: button_class do
|
||||
- if has_icon
|
||||
.social-provider-btn-image.gl-button-icon= provider_image_tag(provider)
|
||||
.gl-button-text
|
||||
= s_('Profiles|Connect %{provider}') % { provider: label_for_provider(provider) }
|
||||
= render_if_exists 'profiles/accounts/group_saml_unlink_buttons', group_saml_identities: group_saml_identities
|
||||
= s_('Profiles|Connect %{provider}') % { provider: label_for_provider(provider) }
|
||||
= render_if_exists 'profiles/accounts/group_saml_unlink_buttons', group_saml_identities: group_saml_identities
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
name: clickhouse_ci_analytics
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/130211
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/424498
|
||||
milestone: '16.4'
|
||||
name: arkose_labs_signup_data_exchange
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139070
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/435275
|
||||
milestone: '16.8'
|
||||
type: development
|
||||
group: group::runner
|
||||
group: group::anti-abuse
|
||||
default_enabled: false
|
||||
|
|
@ -687,6 +687,8 @@
|
|||
- 1
|
||||
- - security_scan_result_policies_sync_any_merge_request_approval_rules
|
||||
- 1
|
||||
- - security_scan_result_policies_sync_merge_request_approvals
|
||||
- 1
|
||||
- - security_scan_result_policies_sync_project
|
||||
- 1
|
||||
- - security_scans
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
stage: Create
|
||||
group: Editor Extensions
|
||||
description: Visual Studio Code, JetBrains, Neovim, GitLab CLI.
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
stage: Manage
|
||||
group: Import and Integrate
|
||||
description: Projects, issues, authentication, security providers.
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -300,13 +300,20 @@ actions:
|
|||
|
||||
## Understanding scan result policy approvals
|
||||
|
||||
> The branch comparison logic for `scan_finding` was [changed](https://gitlab.com/gitlab-org/gitlab/-/issues/428518) in GitLab 16.8 [with a flag](../../../administration/feature_flags.md) named `scan_result_policy_merge_base_pipeline`. Disabled by default.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available, an administrator can [enable the feature flag](../../../administration/feature_flags.md) named `scan_result_policy_merge_base_pipeline`.
|
||||
On GitLab.com, this feature is not available.
|
||||
|
||||
### Scope of scan result policy comparison
|
||||
|
||||
- To determine when approval is required on a merge request, we compare completed pipelines for each supported pipeline source for the source and target branch (for example, `feature`/`main`). This ensures the most comprehensive evaluation of scan results.
|
||||
- For the source branch, the comparison pipeline is its latest completed `HEAD` pipeline.
|
||||
- For the target branch, the comparison pipeline differs for `license_finding` rules:
|
||||
- For `license_finding` rules, we compare to a common ancestor's latest completed pipeline.
|
||||
- For all other rules, we compare to the target branch's latest completed `HEAD` pipeline.
|
||||
- For `license_finding` rules, we compare to a common ancestor's latest completed pipeline.
|
||||
- For `scan_finding` rules, the comparison pipeline may differ:
|
||||
- If the `scan_result_policy_merge_base_pipeline` feature flag is enabled, we compare to a common ancestor's latest completed pipeline.
|
||||
- Otherwise, we compare to the target branch's latest completed `HEAD` pipeline.
|
||||
- Scan result policies considers all supported pipeline sources (based on the [`CI_PIPELINE_SOURCE` variable](../../../ci/variables/predefined_variables.md)) when comparing results from both the source and target branches when determining if a merge request requires approval. Pipeline sources `webide` and `parent_pipeline` are not supported.
|
||||
|
||||
### Accepting risk and ignoring vulnerabilities in future merge requests
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ The following features are not found in standard Markdown.
|
|||
|
||||
### Colors
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#colors).
|
||||
|
||||
Markdown does not support changing text color.
|
||||
|
||||
You can write a color code in the formats: `HEX`, `RGB`, or `HSL`.
|
||||
|
|
@ -134,9 +136,6 @@ display a color chip next to the color code. For example:
|
|||
- `HSLA(540,70%,50%,0.3)`
|
||||
```
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#colors)
|
||||
to see the color chips next to the color code:
|
||||
|
||||
- `#F00`
|
||||
- `#F00A`
|
||||
- `#FF0000`
|
||||
|
|
@ -159,6 +158,8 @@ In wikis, you can also add and edit diagrams created with the [diagrams.net edit
|
|||
|
||||
#### Mermaid
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#mermaid).
|
||||
|
||||
Visit the [official page](https://mermaidjs.github.io/) for more details. The
|
||||
[Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor/) helps you
|
||||
learn Mermaid and debug issues in your Mermaid code. Use it to identify and resolve
|
||||
|
|
@ -480,11 +481,6 @@ To include task lists in tables, [use HTML list tags or HTML tables](#task-lists
|
|||
|
||||
### Table of contents
|
||||
|
||||
<!--
|
||||
Tags for the table of contents are presented in a code block to work around a Markdown bug.
|
||||
Do not change the code block back to single backticks.
|
||||
For more information, see https://gitlab.com/gitlab-org/gitlab/-/issues/359077.
|
||||
-->
|
||||
A table of contents is an unordered list that links to subheadings in the document.
|
||||
You can add a table of contents to issues, merge requests, and epics, but you can't add one
|
||||
to notes or comments.
|
||||
|
|
@ -492,9 +488,15 @@ to notes or comments.
|
|||
Add one of these tags on their own line to the **description** field of any of the supported
|
||||
content types:
|
||||
|
||||
<!--
|
||||
Tags for the table of contents are presented in a code block to work around a Markdown bug.
|
||||
Do not change the code block back to single backticks.
|
||||
For more information, see https://gitlab.com/gitlab-org/gitlab/-/issues/359077.
|
||||
-->
|
||||
|
||||
```markdown
|
||||
[[_TOC_]]
|
||||
|
||||
or
|
||||
[TOC]
|
||||
```
|
||||
|
||||
|
|
@ -767,6 +769,8 @@ If a functionality is extended, the new option is listed as a sub-section.
|
|||
|
||||
### Blockquotes
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#blockquotes).
|
||||
|
||||
Use a blockquote to highlight information, such as a side note. It's generated
|
||||
by starting the lines of the blockquote with `>`:
|
||||
|
||||
|
|
@ -788,7 +792,7 @@ Quote break.
|
|||
|
||||
#### Multiline blockquote
|
||||
|
||||
If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#multiline-blockquote).
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#multiline-blockquote).
|
||||
|
||||
GitLab Flavored Markdown extends the standard Markdown by also supporting multi-line blockquotes
|
||||
fenced by `>>>`, with a blank line before and after the block:
|
||||
|
|
@ -819,6 +823,8 @@ trigger this problem.
|
|||
|
||||
### Code spans and blocks
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#code-spans-and-blocks).
|
||||
|
||||
You can highlight anything that should be viewed as code and not standard text.
|
||||
|
||||
Inline code is highlighted with single backticks `` ` ``:
|
||||
|
|
@ -880,8 +886,7 @@ Tildes are OK too.
|
|||
|
||||
#### Colored code and syntax highlighting
|
||||
|
||||
If this section isn't rendered correctly,
|
||||
[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#colored-code-and-syntax-highlighting).
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#colored-code-and-syntax-highlighting).
|
||||
|
||||
GitLab uses the [Rouge Ruby library](https://github.com/rouge-ruby/rouge) for more colorful syntax
|
||||
highlighting in code blocks. For a list of supported languages visit the
|
||||
|
|
@ -945,6 +950,8 @@ But let's throw in a <b>tag</b>.
|
|||
|
||||
### Emphasis
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#emphasis).
|
||||
|
||||
In Markdown, you can emphasize text in multiple ways. You can italicize, bold, strikethrough,
|
||||
and combine these emphasis styles together.
|
||||
Strikethrough is not part of the core Markdown standard, but is part of GitLab Flavored Markdown.
|
||||
|
|
@ -975,8 +982,7 @@ Strikethrough with double tildes. ~~Scratch this.~~
|
|||
|
||||
#### Multiple underscores in words and mid-word emphasis
|
||||
|
||||
If this section isn't rendered correctly,
|
||||
[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#multiple-underscores-in-words).
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#multiple-underscores-in-words).
|
||||
|
||||
Avoid italicizing a portion of a word, especially when you're
|
||||
dealing with code and names that often appear with multiple underscores.
|
||||
|
|
@ -1017,6 +1023,8 @@ do*this*and*do*that*and*another thing
|
|||
|
||||
### Footnotes
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#footnotes).
|
||||
|
||||
Footnotes add a link to a note rendered at the end of a Markdown file.
|
||||
|
||||
To make a footnote, you need both a reference tag and a separate line (anywhere in the file) with
|
||||
|
|
@ -1061,9 +1069,11 @@ These are used to force the Vale ReferenceLinks check to skip these examples.
|
|||
#### H4
|
||||
##### H5
|
||||
###### H6
|
||||
```
|
||||
|
||||
Alternatively, for H1 and H2, an underline-ish style:
|
||||
Alternatively, for H1 and H2, an underline style:
|
||||
|
||||
```markdown
|
||||
Alt-H1
|
||||
======
|
||||
|
||||
|
|
@ -1073,6 +1083,8 @@ Alt-H2
|
|||
|
||||
#### Header IDs and links
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#header-ids-and-links).
|
||||
|
||||
GitLab Flavored Markdown extends the standard Markdown standard so that all Markdown-rendered headers automatically
|
||||
get IDs, which can be linked to, except in comments.
|
||||
|
||||
|
|
@ -1113,69 +1125,77 @@ emoji is converted to an image, which is then removed from the ID.
|
|||
|
||||
### Horizontal Rule
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#horizontal-rule).
|
||||
|
||||
Create a horizontal rule by using three or more hyphens, asterisks, or underscores:
|
||||
|
||||
```markdown
|
||||
Three or more hyphens,
|
||||
|
||||
---
|
||||
|
||||
asterisks,
|
||||
|
||||
***
|
||||
|
||||
or underscores
|
||||
|
||||
___
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
### Images
|
||||
|
||||
Examples:
|
||||
Embed images using inline or reference links.
|
||||
To see title text, hover over the image.
|
||||
|
||||
<!--
|
||||
The following codeblock uses HTML to skip the Vale ReferenceLinks test.
|
||||
Do not change it back to a markdown codeblock.
|
||||
The following examples use HTML to skip the Vale ReferenceLinks test.
|
||||
Do not change it back to a markdown codeblocks.
|
||||
-->
|
||||
|
||||
<!-- markdownlint-disable proper-names -->
|
||||
|
||||
<pre class="highlight"><code>Inline-style (hover to see title text):
|
||||
|
||||

|
||||
|
||||
Reference-style (hover to see title text):
|
||||
|
||||
![alt text1][logo]
|
||||
|
||||
[logo]: img/markdown_logo.png "Title Text"
|
||||
</code></pre>
|
||||
|
||||
<!-- markdownlint-enable proper-names -->
|
||||
|
||||
<!--
|
||||
DO NOT change the name of markdown_logo.png. This file is used for a test in
|
||||
spec/controllers/help_controller_spec.rb.
|
||||
-->
|
||||
|
||||
Inline-style (hover to see title text):
|
||||
|
||||

|
||||
|
||||
Reference-style (hover to see title text):
|
||||
|
||||
<!--
|
||||
The example below uses an in-line link to pass the Vale ReferenceLinks test.
|
||||
The examples below use an in-line link to pass the Vale ReferenceLinks test.
|
||||
Do not change to a reference style link.
|
||||
-->
|
||||
|
||||
Inline-style:
|
||||
|
||||
<!-- markdownlint-disable proper-names -->
|
||||
|
||||
<pre class="highlight"><code>
|
||||
|
||||

|
||||
|
||||
</code></pre>
|
||||
|
||||

|
||||
|
||||
Reference-style:
|
||||
|
||||
<pre class="highlight"><code>
|
||||
|
||||
![alt text1][logo]
|
||||
|
||||
[logo]: img/markdown_logo.png "Title Text"
|
||||
|
||||
</code></pre>
|
||||
|
||||

|
||||
|
||||
<!-- markdownlint-enable proper-names -->
|
||||
|
||||
#### Change the image or video dimensions
|
||||
|
||||
> - Support for images [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/28118) in GitLab 15.7.
|
||||
> - Support for videos [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17139) in GitLab 15.9.
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#change-the-image-or-video-dimensions).
|
||||
|
||||
You can control the width and height of an image or video by following the image with
|
||||
an attribute list.
|
||||
The value must an integer with a unit of either `px` (default) or `%`.
|
||||
|
|
@ -1195,44 +1215,39 @@ You can also use the `img` HTML tag instead of Markdown and set its `height` and
|
|||
|
||||
#### Videos
|
||||
|
||||
If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#videos).
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#videos).
|
||||
|
||||
Image tags that link to files with a video extension are automatically converted to
|
||||
a video player. The valid video extensions are `.mp4`, `.m4v`, `.mov`, `.webm`, and `.ogv`:
|
||||
|
||||
```markdown
|
||||
Here's a sample video:
|
||||
Here's an example video:
|
||||
|
||||
```markdown
|
||||

|
||||
```
|
||||
|
||||
Here's a sample video:
|
||||
|
||||

|
||||
|
||||
#### Audio
|
||||
|
||||
If this section isn't rendered correctly, [view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#audio).
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#audio).
|
||||
|
||||
Similar to videos, link tags for files with an audio extension are automatically converted to
|
||||
an audio player. The valid audio extensions are `.mp3`, `.oga`, `.ogg`, `.spx`, and `.wav`:
|
||||
|
||||
```markdown
|
||||
Here's a sample audio clip:
|
||||
Here's an example audio clip:
|
||||
|
||||
```markdown
|
||||

|
||||
```
|
||||
|
||||
Here's a sample audio clip:
|
||||
|
||||

|
||||
|
||||
### Inline HTML
|
||||
|
||||
> Allowing `rel="license"` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20857) in GitLab 14.6.
|
||||
|
||||
To see the second example of Markdown rendered in HTML,
|
||||
[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#inline-html).
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#inline-html).
|
||||
|
||||
You can also use raw HTML in your Markdown, and it usually works pretty well.
|
||||
|
||||
|
|
@ -1297,8 +1312,7 @@ Markdown is fine in GitLab.
|
|||
|
||||
#### Collapsible section
|
||||
|
||||
To see the second Markdown example rendered in HTML,
|
||||
[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#details-and-summary).
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#details-and-summary).
|
||||
|
||||
Content can be collapsed using HTML's [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details)
|
||||
and [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary)
|
||||
|
|
@ -1363,6 +1377,8 @@ These details <em>remain</em> <b>hidden</b> until expanded.
|
|||
|
||||
### Line breaks
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#line-breaks).
|
||||
|
||||
A line break is inserted (a new paragraph starts) if the previous text is
|
||||
ended with two newlines, like when you press <kbd>Enter</kbd> twice in a row. If you only
|
||||
use one newline (press <kbd>Enter</kbd> once), the next sentence remains part of the
|
||||
|
|
@ -1414,6 +1430,8 @@ A new line due to the previous backslash.
|
|||
|
||||
### Links
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#links).
|
||||
|
||||
You can create links two ways: inline-style and reference-style. For example:
|
||||
|
||||
<!--
|
||||
|
|
@ -1475,6 +1493,8 @@ points the link to `wikis/style` only when the link is inside of a wiki Markdown
|
|||
|
||||
#### URL auto-linking
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#url-auto-linking).
|
||||
|
||||
GitLab Flavored Markdown auto-links almost any URL you put into your text:
|
||||
|
||||
```markdown
|
||||
|
|
@ -1496,8 +1516,11 @@ GitLab Flavored Markdown auto-links almost any URL you put into your text:
|
|||
- <http://localhost:3000>
|
||||
|
||||
<!-- vale gitlab.Spelling = YES -->
|
||||
|
||||
### Lists
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#lists).
|
||||
|
||||
You can create ordered and unordered lists.
|
||||
|
||||
For an ordered list, add the number you want the list
|
||||
|
|
@ -1653,6 +1676,8 @@ CommonMark ignores the blank line and renders this as one list with paragraph sp
|
|||
|
||||
### Superscripts / Subscripts
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#superscripts-subscripts).
|
||||
|
||||
CommonMark and GitLab Flavored Markdown don't support the Redcarpet superscript syntax ( `x^2` ).
|
||||
Use the standard HTML syntax for superscripts and subscripts:
|
||||
|
||||
|
|
@ -1670,6 +1695,8 @@ while the equation for the theory of relativity is E = mc<sup>2</sup>.
|
|||
|
||||
### Keyboard HTML tag
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#keyboard-html-tag).
|
||||
|
||||
The `<kbd>` element is used to identify text that represents user keyboard input. Text surrounded by `<kbd>` tags is typically displayed in the browser's default monospace font.
|
||||
|
||||
```html
|
||||
|
|
@ -1680,6 +1707,8 @@ Press <kbd>Enter</kbd> to go to the next page.
|
|||
|
||||
### Tables
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#tables-1).
|
||||
|
||||
Tables are not part of the core Markdown specification, but are part of GitLab Flavored Markdown.
|
||||
|
||||
- The first line contains the headers, separated by "pipes" (`|`).
|
||||
|
|
@ -1716,6 +1745,8 @@ Example:
|
|||
|
||||
#### Alignment
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#alignment).
|
||||
|
||||
Additionally, you can choose the alignment of text in columns by adding colons (`:`)
|
||||
to the sides of the "dash" lines in the second row. This affects every cell in the column:
|
||||
|
||||
|
|
@ -1736,6 +1767,8 @@ the headers are always left-aligned in Chrome and Firefox, and centered in Safar
|
|||
|
||||
#### Cells with multiple lines
|
||||
|
||||
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#cells-with-multiple-lines).
|
||||
|
||||
You can use HTML formatting to adjust the rendering of tables. For example, you can
|
||||
use `<br>` tags to force a cell to have multiple lines:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
stage: Manage
|
||||
group: Import and Integrate
|
||||
description: Custom HTTP callbacks, used to send events.
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -70,12 +70,12 @@ The editor supports these languages:
|
|||
| Google SQL | **{dotted-circle}** No | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
|
||||
| Java | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
|
||||
| JavaScript | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
|
||||
| Kotlin | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
|
||||
| Kotlin | **{check-circle}** Yes (Requires third-party extension providing Kotlin support) | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
|
||||
| PHP | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
|
||||
| Python | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
|
||||
| Ruby | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
|
||||
| Rust | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
|
||||
| Scala | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
|
||||
| Scala | **{check-circle}** Yes (Requires third-party extension providing Scala support) | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
|
||||
| Swift | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
|
||||
| TypeScript | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
|
||||
| Terraform | **{check-circle}** Yes (Requires third-party extension providing Terraform support) | **{check-circle}** Yes | **{dotted-circle}** No | **{check-circle}** Yes (Requires third-party extension providing the `terraform` file type) |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,223 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Database
|
||||
# This class implements an iterator over the namespace hierarchy which uses a recursive
|
||||
# depth-first algorithm.
|
||||
# You can read more about the algorithm here:
|
||||
# https://docs.gitlab.com/ee/development/database/poc_tree_iterator.html
|
||||
#
|
||||
# With the class, you can iterate over the whole hierarchy including subgroups and project namespaces
|
||||
# or just iterate over the subgroups.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# # To invoke the iterator, you can take any group id.
|
||||
# # Build the cursor object that will be used for tracking our position in the tree hierarchy.
|
||||
# cursor = { current_id: 9970, depth: [9970] }
|
||||
#
|
||||
# # Instantiate the object.
|
||||
# iterator = Gitlab::Database::NamespaceEachBatch.new(namespace_class: Namespace, cursor: cursor)
|
||||
#
|
||||
# iterator.each_batch(of: 100) do |ids|
|
||||
# # return namespace ids which can be Group id or Namespaces::ProjectNamespace id
|
||||
# puts ids
|
||||
# end
|
||||
#
|
||||
# # When you need to break out of the iteration and continue later, you can yield the cursor as a second parameter:
|
||||
# iterator.each_batch(of: 100) do |ids, new_cursor|
|
||||
# save_cursor(new_cursor) && break if limit_reached?
|
||||
# puts ids
|
||||
# end
|
||||
#
|
||||
# You can build a new iterator later and resume the processing.
|
||||
#
|
||||
# # Building an iterator that only returns groups:
|
||||
# iterator = Gitlab::Database::NamespaceEachBatch.new(namespace_class: Group, cursor: cursor)
|
||||
#
|
||||
class NamespaceEachBatch
|
||||
PROJECTIONS = %w[current_id depth ids count index].freeze
|
||||
|
||||
def initialize(namespace_class:, cursor:)
|
||||
@namespace_class = namespace_class
|
||||
set_cursor!(cursor)
|
||||
end
|
||||
|
||||
def each_batch(of: 500)
|
||||
current_cursor = cursor.dup
|
||||
|
||||
first_iteration = true
|
||||
loop do
|
||||
new_cursor, ids = load_batch(cursor: current_cursor, of: of, first_iteration: first_iteration)
|
||||
break if new_cursor.nil?
|
||||
|
||||
first_iteration = false
|
||||
current_cursor = new_cursor
|
||||
|
||||
yield ids, new_cursor
|
||||
|
||||
break if new_cursor[:depth].empty?
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :namespace_class, :cursor, :namespace_id
|
||||
|
||||
def load_batch(cursor:, of:, first_iteration: false)
|
||||
recursive_scope = build_recursive_query(cursor, of, first_iteration)
|
||||
|
||||
row = Namespace
|
||||
.select(*PROJECTIONS)
|
||||
.from(recursive_scope.arel.as(Namespace.table_name)).order(count: :desc)
|
||||
.limit(1)
|
||||
.first
|
||||
|
||||
return [] unless row
|
||||
|
||||
[{ current_id: row[:current_id], depth: row[:depth] }, row[:ids]]
|
||||
end
|
||||
|
||||
# rubocop: disable Style/AsciiComments -- Rendering a graph
|
||||
# The depth-first algorithm is implemented here. Consider the following group hierarchy:
|
||||
#
|
||||
# ┌──┐
|
||||
# │10│
|
||||
# ┌────┴──┴────┐
|
||||
# │ │
|
||||
# ┌─┴┐ ┌┴─┐
|
||||
# │41│ │72│
|
||||
# └─┬┘ └──┘
|
||||
# │
|
||||
# ┌─┴┐
|
||||
# ┌────┤32├─────┐
|
||||
# │ └─┬┘ │
|
||||
# │ │ │
|
||||
# ┌─┴┐ ┌─┴┐ ┌┴─┐
|
||||
# │11│ │12│ │18│
|
||||
# └──┘ └──┘ └──┘
|
||||
#
|
||||
# 1. Start with node 10 and look up the left-hand child nodes until reaching the leaf. (walk_down)
|
||||
# 2. While walking down, record the depth in an array and also store them in the ids array.
|
||||
# 3. depth: 10, 41, 32, 11 | ids: 10, 41, 32, 11
|
||||
# 4. Start collecting the ids by looking at the nodes on the deepest level. (next_elements)
|
||||
# 5. This gives us the rest of the nodes on the same level (parent_id = 32 AND id > 11)
|
||||
# 6. depth: 10, 41, 32, 11 | ids: 10, 41, 32, 11, 12, 18
|
||||
# 7. When done, move one level up and pop the last value from the depth. (up_one_level)
|
||||
# 8. depth: 10, 41, 32 | ids: 10, 41, 32, 11, 12, 18
|
||||
# 9. Do the same, look at the nodes on the same level: no records, 32 was already collected
|
||||
# 10. depth: 10, 41, 32 | ids: 10, 41, 32, 11, 12, 18
|
||||
# 11. Move one level up again and look at the nodes on the same level.
|
||||
# 12. depth: 10, 41 | ids: 10, 41, 32, 11, 12, 18, 72
|
||||
# 13. Move one level up again, we reached the root node, iteration is done.
|
||||
# 14. depth: 10 | ids: 10, 41, 32, 11, 12, 18, 72
|
||||
#
|
||||
# By tracking the currently accessed node and the depth we can stop and restore the processing of
|
||||
# the hierarchy at any point.
|
||||
#
|
||||
# rubocop: enable Style/AsciiComments
|
||||
def build_recursive_query(cursor, of, first_iteration)
|
||||
ids = first_iteration ? cursor[:current_id] : ''
|
||||
|
||||
recursive_cte = Gitlab::SQL::RecursiveCTE.new(:result,
|
||||
union_args: {
|
||||
remove_order: false,
|
||||
remove_duplicates: false
|
||||
})
|
||||
|
||||
recursive_cte << base_namespace_class.select(
|
||||
Arel.sql(cursor[:current_id].to_s).as('current_id'),
|
||||
Arel.sql("ARRAY[#{cursor[:depth].join(',')}]::int[]").as('depth'),
|
||||
Arel.sql("ARRAY[#{ids}]::int[]").as('ids'),
|
||||
Arel.sql('1::bigint AS count'),
|
||||
Arel.sql('0::bigint AS index')
|
||||
).from('(VALUES (1)) AS initializer_row')
|
||||
.where_exists(namespace_exists_query)
|
||||
|
||||
cte = Gitlab::SQL::CTE.new(:cte, base_namespace_class.select('result.*').from('result'))
|
||||
|
||||
union_query = base_namespace_class.with(cte.to_arel).from_union(
|
||||
walk_down,
|
||||
next_elements,
|
||||
up_one_level,
|
||||
remove_duplicates: false,
|
||||
remove_order: false
|
||||
).select(*PROJECTIONS).order(base_namespace_class.arel_table[:index].asc).limit(1)
|
||||
|
||||
recursive_cte << union_query
|
||||
|
||||
base_namespace_class.with
|
||||
.recursive(recursive_cte.to_arel)
|
||||
.from(recursive_cte.alias_to(namespace_class.arel_table))
|
||||
.select(*PROJECTIONS)
|
||||
.limit(of + 1)
|
||||
end
|
||||
|
||||
def namespace_exists_query
|
||||
Namespace.where(id: cursor[:current_id])
|
||||
end
|
||||
|
||||
def walk_down
|
||||
lateral_query = namespace_class
|
||||
.select(:id)
|
||||
.where('parent_id = cte.current_id')
|
||||
.order(:id)
|
||||
.limit(1)
|
||||
|
||||
base_namespace_class.select(
|
||||
base_namespace_class.arel_table[:id].as('current_id'),
|
||||
Arel.sql("cte.depth || #{base_namespace_table}.id").as('depth'),
|
||||
Arel.sql("cte.ids || #{base_namespace_table}.id").as('ids'),
|
||||
Arel.sql('cte.count + 1').as('count'),
|
||||
Arel.sql('1::bigint AS index')
|
||||
).from("cte, LATERAL (#{lateral_query.to_sql}) #{base_namespace_table}")
|
||||
end
|
||||
|
||||
def next_elements
|
||||
lateral_query = namespace_class
|
||||
.select(:id)
|
||||
.where("#{base_namespace_table}.parent_id = cte.depth[array_length(cte.depth, 1) - 1]")
|
||||
.where("#{base_namespace_table}.id > cte.depth[array_length(cte.depth, 1)]")
|
||||
.order(:id)
|
||||
.limit(1)
|
||||
|
||||
base_namespace_class.select(
|
||||
base_namespace_class.arel_table[:id].as('current_id'),
|
||||
Arel.sql("cte.depth[:array_length(cte.depth, 1) - 1] || #{base_namespace_table}.id").as('depth'),
|
||||
Arel.sql("cte.ids || #{base_namespace_table}.id").as('ids'),
|
||||
Arel.sql('cte.count + 1').as('count'),
|
||||
Arel.sql('2::bigint AS index')
|
||||
).from("cte, LATERAL (#{lateral_query.to_sql}) #{base_namespace_table}")
|
||||
end
|
||||
|
||||
def up_one_level
|
||||
Namespace.select(
|
||||
Arel.sql('cte.current_id').as('current_id'),
|
||||
Arel.sql('cte.depth[:array_length(cte.depth, 1) - 1]').as('depth'),
|
||||
Arel.sql('cte.ids').as('ids'),
|
||||
Arel.sql('cte.count + 1').as('count'),
|
||||
Arel.sql('3::bigint AS index')
|
||||
).from('cte')
|
||||
.where('cte.depth <> ARRAY[]::int[]')
|
||||
.limit(1)
|
||||
end
|
||||
|
||||
def base_namespace_class
|
||||
Namespace
|
||||
end
|
||||
|
||||
def base_namespace_table
|
||||
Namespace.quoted_table_name
|
||||
end
|
||||
|
||||
def set_cursor!(original_cursor)
|
||||
raise ArgumentError unless original_cursor[:depth].is_a?(Array)
|
||||
|
||||
@cursor = {
|
||||
current_id: Integer(original_cursor[:current_id]),
|
||||
depth: original_cursor[:depth].map { |value| Integer(value) }
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -40308,6 +40308,9 @@ msgstr ""
|
|||
msgid "Remote object has no absolute path."
|
||||
msgstr ""
|
||||
|
||||
msgid "RemoteDevelopment|Workspaces"
|
||||
msgstr ""
|
||||
|
||||
msgid "Remove"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ ENV GITLAB_LICENSE_MODE=test \
|
|||
|
||||
# Clone GDK at specific sha and bootstrap packages
|
||||
#
|
||||
ARG GDK_SHA=88c3231079278a49ba59d37362357e5908fb7179
|
||||
ARG GDK_SHA=600866eab57a9645e2c16f6f1756ecc6e4983c86
|
||||
RUN set -eux; \
|
||||
git clone --depth 1 https://gitlab.com/gitlab-org/gitlab-development-kit.git && cd gitlab-development-kit; \
|
||||
git fetch --depth 1 origin ${GDK_SHA} && git -c advice.detachedHead=false checkout ${GDK_SHA}; \
|
||||
|
|
|
|||
|
|
@ -56,14 +56,6 @@ module QA
|
|||
storage: 10
|
||||
}.freeze
|
||||
|
||||
CODE_SUGGESTIONS = {
|
||||
# Annual plan, rate and price
|
||||
plan_id: '8a8aa0ac8874ddc4018878da1f736782',
|
||||
rate_charge_id: '8a8aa0ac8874ddc4018878da1f9a6784',
|
||||
name: 'code suggestions',
|
||||
price: 108
|
||||
}.freeze
|
||||
|
||||
LICENSE_TYPE = {
|
||||
legacy_license: 'legacy license',
|
||||
online_cloud: 'online license',
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ describe('ClusterAgentShow', () => {
|
|||
const findPaginationButtons = () => wrapper.findComponent(GlKeysetPagination);
|
||||
const findTokenCount = () => wrapper.findByTestId('cluster-agent-token-count').text();
|
||||
const findEESecurityTabSlot = () => wrapper.findByTestId('ee-security-tab');
|
||||
const findEEWorkspacesTabSlot = () => wrapper.findByTestId('ee-workspaces-tab');
|
||||
const findActivity = () => wrapper.findComponent(ActivityEvents);
|
||||
const findIntegrationStatus = () => wrapper.findComponent(IntegrationStatus);
|
||||
|
||||
|
|
@ -253,4 +254,23 @@ describe('ClusterAgentShow', () => {
|
|||
expect(findEESecurityTabSlot().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ee-workspaces-tab slot', () => {
|
||||
it('does not display when a slot is not passed in', async () => {
|
||||
createWrapperWithoutApollo({ clusterAgent: defaultClusterAgent });
|
||||
await nextTick();
|
||||
expect(findEEWorkspacesTabSlot().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('does display when a slot is passed in', async () => {
|
||||
createWrapperWithoutApollo({
|
||||
clusterAgent: defaultClusterAgent,
|
||||
slots: {
|
||||
'ee-workspaces-tab': `<gl-tab data-testid="ee-workspaces-tab">Workspaces Tab!</gl-tab>`,
|
||||
},
|
||||
});
|
||||
await nextTick();
|
||||
expect(findEEWorkspacesTabSlot().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,174 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Database::NamespaceEachBatch, feature_category: :database do
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:other_group) { create(:group) }
|
||||
let_it_be(:user) { create(:user, :admin) }
|
||||
|
||||
let(:namespace_id) { group.id }
|
||||
|
||||
let_it_be(:subgroup1) { create(:group, parent: group) }
|
||||
let_it_be(:subgroup2) { create(:group, parent: group) }
|
||||
|
||||
let_it_be(:subsubgroup1) { create(:group, parent: subgroup1) }
|
||||
let_it_be(:subsubgroup2) { create(:group, parent: subgroup1) }
|
||||
let_it_be(:subsubgroup3) { create(:group, parent: subgroup1) }
|
||||
|
||||
let_it_be(:project1) { create(:project, namespace: group) }
|
||||
let_it_be(:project2) { create(:project, namespace: group) }
|
||||
let_it_be(:project3) { create(:project, namespace: subsubgroup2) }
|
||||
let_it_be(:project4) { create(:project, namespace: subsubgroup3) }
|
||||
let_it_be(:project5) { create(:project, namespace: subsubgroup3) }
|
||||
|
||||
let(:namespace_class) { Namespace }
|
||||
let(:batch_size) { 3 }
|
||||
|
||||
def collected_ids(cursor = { current_id: namespace_id, depth: [namespace_id] })
|
||||
[].tap do |ids|
|
||||
described_class.new(namespace_class: namespace_class, cursor: cursor).each_batch(of: batch_size) do |batch_ids|
|
||||
ids.concat(batch_ids)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'iteration over the hierarchy' do
|
||||
it 'returns the correct namespace ids' do
|
||||
expect(collected_ids).to eq([
|
||||
group.id,
|
||||
subgroup1.id,
|
||||
subsubgroup1.id,
|
||||
subsubgroup2.id,
|
||||
project3.project_namespace_id,
|
||||
subsubgroup3.id,
|
||||
project4.project_namespace_id,
|
||||
project5.project_namespace_id,
|
||||
subgroup2.id,
|
||||
project1.project_namespace_id,
|
||||
project2.project_namespace_id
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'iteration over the hierarchy'
|
||||
|
||||
context 'when batch size is larger than the hierarchy' do
|
||||
let(:batch_size) { 100 }
|
||||
|
||||
it_behaves_like 'iteration over the hierarchy'
|
||||
end
|
||||
|
||||
context 'when batch size is 1' do
|
||||
let(:batch_size) { 1 }
|
||||
|
||||
it_behaves_like 'iteration over the hierarchy'
|
||||
end
|
||||
|
||||
context 'when stopping the iteration in the middle and resuming' do
|
||||
it 'returns the correct ids' do
|
||||
ids = []
|
||||
cursor = { current_id: namespace_id, depth: [namespace_id] }
|
||||
|
||||
iterator = described_class.new(namespace_class: namespace_class, cursor: cursor)
|
||||
iterator.each_batch(of: 5) do |batch_ids, new_cursor|
|
||||
ids.concat(batch_ids)
|
||||
cursor = new_cursor
|
||||
end
|
||||
|
||||
iterator = described_class.new(namespace_class: namespace_class, cursor: cursor)
|
||||
iterator.each_batch(of: 500) do |batch_ids|
|
||||
ids.concat(batch_ids)
|
||||
end
|
||||
|
||||
expect(collected_ids).to eq([
|
||||
group.id,
|
||||
subgroup1.id,
|
||||
subsubgroup1.id,
|
||||
subsubgroup2.id,
|
||||
project3.project_namespace_id,
|
||||
subsubgroup3.id,
|
||||
project4.project_namespace_id,
|
||||
project5.project_namespace_id,
|
||||
subgroup2.id,
|
||||
project1.project_namespace_id,
|
||||
project2.project_namespace_id
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when querying a subgroup' do
|
||||
let(:namespace_id) { subgroup1.id }
|
||||
|
||||
it 'returns the correct ids' do
|
||||
expect(collected_ids).to eq([
|
||||
subgroup1.id,
|
||||
subsubgroup1.id,
|
||||
subsubgroup2.id,
|
||||
project3.project_namespace_id,
|
||||
subsubgroup3.id,
|
||||
project4.project_namespace_id,
|
||||
project5.project_namespace_id
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when querying a subgroup without descendants' do
|
||||
let(:namespace_id) { subgroup2.id }
|
||||
|
||||
it 'finds only the given namespace id' do
|
||||
expect(collected_ids).to eq([subgroup2.id])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when batching over groups only' do
|
||||
let(:namespace_class) { Group }
|
||||
|
||||
it 'returns the correct namespace ids' do
|
||||
expect(collected_ids).to eq([
|
||||
group.id,
|
||||
subgroup1.id,
|
||||
subsubgroup1.id,
|
||||
subsubgroup2.id,
|
||||
subsubgroup3.id,
|
||||
subgroup2.id
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the cursor is invalid' do
|
||||
context 'when non-integer current id is given' do
|
||||
it 'raises error' do
|
||||
cursor = { current_id: 'not int', depth: [group.id] }
|
||||
|
||||
expect { collected_ids(cursor) }.to raise_error(ArgumentError)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when depth is not an array' do
|
||||
it 'raises error' do
|
||||
cursor = { current_id: group.id, depth: group.id }
|
||||
|
||||
expect { collected_ids(cursor) }.to raise_error(ArgumentError)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when non-integer depth values are given' do
|
||||
it 'raises error' do
|
||||
cursor = { current_id: group.id, depth: ['not int'] }
|
||||
|
||||
expect { collected_ids(cursor) }.to raise_error(ArgumentError)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when giving non-existing namespace id' do
|
||||
it 'returns nothing', :enable_admin_mode do
|
||||
cursor = { current_id: subgroup1.id, depth: [group.id, subgroup1.id] }
|
||||
|
||||
Groups::DestroyService.new(group, user).execute
|
||||
|
||||
expect(collected_ids(cursor)).to eq([])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -35,30 +35,32 @@ RSpec.describe Packages::Protection::Rule, type: :model, feature_category: :pack
|
|||
it { is_expected.to validate_uniqueness_of(:package_name_pattern).scoped_to(:project_id, :package_type) }
|
||||
it { is_expected.to validate_length_of(:package_name_pattern).is_at_most(255) }
|
||||
|
||||
[
|
||||
'@my-scope/my-package',
|
||||
'@my-scope/*my-package-with-wildcard-inbetween',
|
||||
'@my-scope/*my-package-with-wildcard-start',
|
||||
'@my-scope/my-*package-*with-wildcard-multiple-*',
|
||||
'@my-scope/my-package-with_____underscore',
|
||||
'@my-scope/my-package-with-regex-characters.+',
|
||||
'@my-scope/my-package-with-wildcard-end*'
|
||||
].each do |package_name_pattern|
|
||||
it { is_expected.to allow_value(package_name_pattern).for(:package_name_pattern) }
|
||||
where(:package_name_pattern, :allowed) do
|
||||
'@my-scope/my-package' | true
|
||||
'@my-scope/*my-package-with-wildcard-inbetween' | true
|
||||
'@my-scope/*my-package-with-wildcard-start' | true
|
||||
'@my-scope/my-*package-*with-wildcard-multiple-*' | true
|
||||
'@my-scope/my-package-with_____underscore' | true
|
||||
'@my-scope/my-package-with-regex-characters.+' | true
|
||||
'@my-scope/my-package-with-wildcard-end*' | true
|
||||
|
||||
'@my-scope/my-package-with-percent-sign-%' | false
|
||||
'*@my-scope/my-package-with-wildcard-start' | false
|
||||
'@my-scope/my-package-with-backslash-\*' | false
|
||||
end
|
||||
|
||||
[
|
||||
'@my-scope/my-package-with-percent-sign-%',
|
||||
'*@my-scope/my-package-with-wildcard-start',
|
||||
'@my-scope/my-package-with-backslash-\*'
|
||||
].each do |package_name_pattern|
|
||||
it {
|
||||
is_expected.not_to(
|
||||
allow_value(package_name_pattern)
|
||||
.for(:package_name_pattern)
|
||||
.with_message(_('should be a valid NPM package name with optional wildcard characters.'))
|
||||
)
|
||||
}
|
||||
with_them do
|
||||
if params[:allowed]
|
||||
it { is_expected.to allow_value(package_name_pattern).for(:package_name_pattern) }
|
||||
else
|
||||
it {
|
||||
is_expected.not_to(
|
||||
allow_value(package_name_pattern)
|
||||
.for(:package_name_pattern)
|
||||
.with_message(_('should be a valid NPM package name with optional wildcard characters.'))
|
||||
)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue