Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-01-05 21:11:24 +00:00
parent 534ce3b2d0
commit 6fd670b99b
26 changed files with 618 additions and 130 deletions

View File

@ -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"},

View File

@ -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

View File

@ -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 }">

View File

@ -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>

View File

@ -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';

View File

@ -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';

View File

@ -130,6 +130,11 @@
.gl-pipeline-job-width {
width: 100%;
max-width: 400px;
.pipeline-graph-container & {
max-width: unset;
}
}
.gl-pipeline-job-width\! {

View File

@ -0,0 +1 @@
@import './atwho';

View File

@ -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

View File

@ -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' }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
---

View File

@ -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
---

View File

@ -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

View File

@ -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):
![alt text](img/markdown_logo.png "Title Text")
Reference-style (hover to see title text):
![alt text1][logo]
&#91;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):
![alt text](img/markdown_logo.png "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>
![alt text](img/markdown_logo.png "Title Text")
</code></pre>
![alt text](img/markdown_logo.png "Title Text")
Reference-style:
<pre class="highlight"><code>
![alt text1][logo]
&#91;logo]: img/markdown_logo.png "Title Text"
</code></pre>
![alt text](img/markdown_logo.png "Title Text")
<!-- 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
![Sample Video](img/markdown_video.mp4)
```
Here's a sample video:
![Sample Video](img/markdown_video.mp4)
#### 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
![Sample Audio](img/markdown_audio.mp3)
```
Here's a sample audio clip:
![Sample Audio](img/markdown_audio.mp3)
### 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:

View File

@ -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
---

View File

@ -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) |

View File

@ -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

View File

@ -40308,6 +40308,9 @@ msgstr ""
msgid "Remote object has no absolute path."
msgstr ""
msgid "RemoteDevelopment|Workspaces"
msgstr ""
msgid "Remove"
msgstr ""

View File

@ -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}; \

View File

@ -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',

View File

@ -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);
});
});
});

View File

@ -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

View File

@ -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