Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-12-02 00:17:32 +00:00
parent 7b78125a38
commit ef615776bf
49 changed files with 744 additions and 149 deletions

View file

@ -519,10 +519,26 @@ rspec:coverage:
paths:
- coverage/index.html
- coverage/assets/
- coverage/lcov/
- tmp/memory_test/
reports:
cobertura: coverage/coverage.xml
rspec:undercoverage:
extends:
- .coverage-base
- .rails:rules:rspec-undercoverage
stage: post-test
needs: ["rspec:coverage"]
script:
- if [ -n "$CI_MERGE_REQUEST_SOURCE_BRANCH_SHA" ]; then
echo "Checking out \$CI_MERGE_REQUEST_SOURCE_BRANCH_SHA ($CI_MERGE_REQUEST_SOURCE_BRANCH_SHA) instead of \$CI_COMMIT_SHA (merge result commit $CI_COMMIT_SHA) so we can use $CI_MERGE_REQUEST_DIFF_BASE_SHA for undercoverage in this merged result pipeline";
git checkout -f ${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA};
else
echo "Using \$CI_COMMIT_SHA ($CI_COMMIT_SHA) for this non-merge result pipeline.";
fi;
- run_timed_command "scripts/undercoverage"
rspec:feature-flags:
extends:
- .coverage-base

View file

@ -67,6 +67,9 @@
.if-merge-request-labels-run-review-app: &if-merge-request-labels-run-review-app
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-review-app/'
.if-merge-request-labels-skip-undercoverage: &if-merge-request-labels-skip-undercoverage
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:skip-undercoverage/'
.if-security-merge-request: &if-security-merge-request
if: '$CI_PROJECT_NAMESPACE == "gitlab-org/security" && $CI_MERGE_REQUEST_IID'
@ -1359,6 +1362,17 @@
- <<: *if-merge-request-labels-run-all-rspec
when: always
.rails:rules:rspec-undercoverage:
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-labels-skip-undercoverage
allow_failure: true
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request-approved
- <<: *if-merge-request
changes: *backend-patterns
.rails:rules:default-branch-schedule-nightly--code-backstage:
rules:
- <<: *if-default-branch-schedule-nightly

View file

@ -1 +1 @@
4dd8bfe1307ffcc5a2a3f4eb70da7977a7c1d915
a191a5d10f0772ae2ed6ec869001ddde6d277827

View file

@ -405,7 +405,9 @@ end
group :development, :test, :coverage do
gem 'simplecov', '~> 0.18.5', require: false
gem 'simplecov-lcov', '~> 0.8.0', require: false
gem 'simplecov-cobertura', '~> 1.3.1', require: false
gem 'undercover', '~> 0.4.4', require: false
end
# Gems required in omnibus-gitlab pipeline

View file

@ -645,6 +645,8 @@ GEM
concurrent-ruby (~> 1.0)
i18n_data (0.8.0)
icalendar (2.4.1)
imagen (0.1.8)
parser (>= 2.5, != 2.5.1.1)
invisible_captcha (1.1.0)
rails (>= 4.2)
ipaddress (0.8.3)
@ -1197,6 +1199,7 @@ GEM
simplecov-cobertura (1.3.1)
simplecov (~> 0.8)
simplecov-html (0.12.3)
simplecov-lcov (0.8.0)
sixarm_ruby_unaccent (1.2.0)
slack-messenger (2.3.4)
snowplow-tracker (0.6.1)
@ -1312,6 +1315,10 @@ GEM
concurrent-ruby (~> 1.0)
u2f (0.2.1)
uber (0.1.0)
undercover (0.4.4)
imagen (>= 0.1.8)
rainbow (>= 2.1, < 4.0)
rugged (>= 0.27, < 1.3)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
@ -1626,6 +1633,7 @@ DEPENDENCIES
simple_po_parser (~> 1.1.2)
simplecov (~> 0.18.5)
simplecov-cobertura (~> 1.3.1)
simplecov-lcov (~> 0.8.0)
slack-messenger (~> 2.3.4)
snowplow-tracker (~> 0.6.1)
solargraph (~> 0.43)
@ -1648,6 +1656,7 @@ DEPENDENCIES
toml-rb (~> 2.0)
truncato (~> 0.7.11)
u2f (~> 0.2.1)
undercover (~> 0.4.4)
unf (~> 0.1.4)
unleash (~> 3.2.2)
valid_email (~> 0.1)

View file

@ -0,0 +1,21 @@
import { mergeAttributes, Node } from '@tiptap/core';
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
export default Node.create({
name: 'footnoteDefinition',
content: 'paragraph',
group: 'block',
parseHTML() {
return [
{ tag: 'section.footnotes li' },
{ tag: '.footnote-backref', priority: PARSE_HTML_PRIORITY_HIGHEST, ignore: true },
];
},
renderHTML({ HTMLAttributes }) {
return ['li', mergeAttributes(HTMLAttributes), 0];
},
});

View file

@ -0,0 +1,37 @@
import { Node, mergeAttributes } from '@tiptap/core';
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
export default Node.create({
name: 'footnoteReference',
inline: true,
group: 'inline',
atom: true,
draggable: true,
selectable: true,
addAttributes() {
return {
footnoteId: {
default: null,
parseHTML: (element) => element.querySelector('a').getAttribute('id'),
},
footnoteNumber: {
default: null,
parseHTML: (element) => element.textContent,
},
};
},
parseHTML() {
return [{ tag: 'sup.footnote-ref', priority: PARSE_HTML_PRIORITY_HIGHEST }];
},
renderHTML({ HTMLAttributes: { footnoteNumber, footnoteId, ...HTMLAttributes } }) {
return ['sup', mergeAttributes(HTMLAttributes), footnoteNumber];
},
});

View file

@ -0,0 +1,19 @@
import { mergeAttributes, Node } from '@tiptap/core';
export default Node.create({
name: 'footnotesSection',
content: 'footnoteDefinition+',
group: 'block',
isolating: true,
parseHTML() {
return [{ tag: 'section.footnotes > ol' }];
},
renderHTML({ HTMLAttributes }) {
return ['ol', mergeAttributes(HTMLAttributes, { class: 'footnotes gl-font-sm' }), 0];
},
});

View file

@ -19,6 +19,9 @@ import Dropcursor from '../extensions/dropcursor';
import Emoji from '../extensions/emoji';
import Figure from '../extensions/figure';
import FigureCaption from '../extensions/figure_caption';
import FootnoteDefinition from '../extensions/footnote_definition';
import FootnoteReference from '../extensions/footnote_reference';
import FootnotesSection from '../extensions/footnotes_section';
import Frontmatter from '../extensions/frontmatter';
import Gapcursor from '../extensions/gapcursor';
import HardBreak from '../extensions/hard_break';
@ -94,6 +97,9 @@ export const createContentEditor = ({
Emoji,
Figure,
FigureCaption,
FootnoteDefinition,
FootnoteReference,
FootnotesSection,
Frontmatter,
Gapcursor,
HardBreak,

View file

@ -17,6 +17,9 @@ import Division from '../extensions/division';
import Emoji from '../extensions/emoji';
import Figure from '../extensions/figure';
import FigureCaption from '../extensions/figure_caption';
import FootnotesSection from '../extensions/footnotes_section';
import FootnoteDefinition from '../extensions/footnote_definition';
import FootnoteReference from '../extensions/footnote_reference';
import Frontmatter from '../extensions/frontmatter';
import HardBreak from '../extensions/hard_break';
import Heading from '../extensions/heading';
@ -156,6 +159,15 @@ const defaultSerializerConfig = {
state.write(`:${name}:`);
},
[FootnoteDefinition.name]: (state, node) => {
state.renderInline(node);
},
[FootnoteReference.name]: (state, node) => {
state.write(`[^${node.attrs.footnoteNumber}]`);
},
[FootnotesSection.name]: (state, node) => {
state.renderList(node, '', (index) => `[^${index + 1}]: `);
},
[Frontmatter.name]: (state, node) => {
const { language } = node.attrs;
const syntax = {

View file

@ -63,7 +63,7 @@ export default {
class="ide-sidebar-link js-ide-review-mode"
@click.prevent="changedActivityView($event, $options.leftSidebarViews.review.name)"
>
<gl-icon name="file-modified" />
<gl-icon name="review-list" />
</button>
</li>
<li>

View file

@ -0,0 +1,27 @@
import InputCopyToggleVisibility from './input_copy_toggle_visibility.vue';
export default {
component: InputCopyToggleVisibility,
title: 'vue_shared/components/form/input_copy_toggle_visibility',
};
const defaultProps = {
value: 'hR8x1fuJbzwu5uFKLf9e',
formInputGroupProps: { class: 'gl-form-input-xl' },
};
const Template = (args, { argTypes }) => ({
components: { InputCopyToggleVisibility },
props: Object.keys(argTypes),
template: `<input-copy-toggle-visibility
:value="value"
:initial-visibility="initialVisibility"
:show-toggle-visibility-button="showToggleVisibilityButton"
:show-copy-button="showCopyButton"
:form-input-group-props="formInputGroupProps"
:copy-button-title="copyButtonTitle"
/>`,
});
export const Default = Template.bind({});
Default.args = defaultProps;

View file

@ -0,0 +1,124 @@
<script>
import { GlFormInputGroup, GlFormGroup, GlButton, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
export default {
name: 'InputCopyToggleVisibility',
i18n: {
toggleVisibilityLabelHide: __('Click to hide'),
toggleVisibilityLabelReveal: __('Click to reveal'),
},
components: {
GlFormInputGroup,
GlFormGroup,
GlButton,
ClipboardButton,
},
directives: {
GlTooltip: GlTooltipDirective,
},
props: {
value: {
type: String,
required: false,
default: '',
},
initialVisibility: {
type: Boolean,
required: false,
default: false,
},
showToggleVisibilityButton: {
type: Boolean,
required: false,
default: true,
},
showCopyButton: {
type: Boolean,
required: false,
default: true,
},
copyButtonTitle: {
type: String,
required: false,
default: __('Copy'),
},
formInputGroupProps: {
type: Object,
required: false,
default() {
return {};
},
},
},
data() {
return {
valueIsVisible: this.initialVisibility,
};
},
computed: {
toggleVisibilityLabel() {
return this.valueIsVisible
? this.$options.i18n.toggleVisibilityLabelHide
: this.$options.i18n.toggleVisibilityLabelReveal;
},
toggleVisibilityIcon() {
return this.valueIsVisible ? 'eye-slash' : 'eye';
},
computedValueIsVisible() {
return !this.showToggleVisibilityButton || this.valueIsVisible;
},
displayedValue() {
return this.computedValueIsVisible ? this.value : '*'.repeat(this.value.length || 20);
},
},
methods: {
handleToggleVisibilityButtonClick() {
this.valueIsVisible = !this.valueIsVisible;
this.$emit('visibility-change', this.valueIsVisible);
},
handleCopyButtonClick() {
this.$emit('copy');
},
handleFormInputCopy(event) {
if (this.computedValueIsVisible) {
return;
}
event.clipboardData.setData('text/plain', this.value);
event.preventDefault();
},
},
};
</script>
<template>
<gl-form-group v-bind="$attrs">
<gl-form-input-group
:value="displayedValue"
input-class="gl-font-monospace! gl-cursor-default!"
select-on-click
readonly
v-bind="formInputGroupProps"
@copy="handleFormInputCopy"
>
<template v-if="showToggleVisibilityButton || showCopyButton" #append>
<gl-button
v-if="showToggleVisibilityButton"
v-gl-tooltip.hover="toggleVisibilityLabel"
:aria-label="toggleVisibilityLabel"
:icon="toggleVisibilityIcon"
@click="handleToggleVisibilityButtonClick"
/>
<clipboard-button
v-if="showCopyButton"
:text="value"
:title="copyButtonTitle"
@click="handleCopyButtonClick"
/>
</template>
</gl-form-input-group>
</gl-form-group>
</template>

View file

@ -1084,16 +1084,6 @@ module Ci
runner&.instance_type?
end
def job_variables_attributes
strong_memoize(:job_variables_attributes) do
job_variables.map do |variable|
variable.attributes.except('id', 'job_id', 'encrypted_value', 'encrypted_value_iv').tap do |attrs|
attrs[:value] = variable.value
end
end
end
end
protected
def run_status_commit_hooks!

View file

@ -7,7 +7,7 @@ module Ci
allow_failure stage stage_id stage_idx trigger_request
yaml_variables when environment coverage_regex
description tag_list protected needs_attributes
resource_group scheduling_type job_variables_attributes].freeze
resource_group scheduling_type].freeze
end
def self.extra_accessors

View file

@ -1,8 +0,0 @@
---
name: drop_detached_partitions
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67056
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337155
milestone: '14.2'
type: development
group: group::database
default_enabled: false

View file

@ -1,8 +0,0 @@
---
name: partition_pruning
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67056
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337153
milestone: '14.2'
type: development
group: group::database
default_enabled: false

View file

@ -10,5 +10,4 @@ link: https://docs.gitlab.com/ee/development/documentation/styleguide/index.html
level: suggestion
ignorecase: true
swap:
button: 'if possible, rewrite to not use'
area: 'use "section" instead of'
button: 'if possible, rewrite to remove'

View file

@ -252,6 +252,7 @@ Example response:
"finished_at": "2016-01-11T10:15:10.506Z",
"duration": 97.0,
"status": "failed",
"failure_reason": "script_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/42",
"user": null

View file

@ -71,6 +71,7 @@ Example of response
"runner": null,
"stage": "test",
"status": "failed",
"failure_reason": "script_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/7",
"user": {
@ -126,6 +127,7 @@ Example of response
"runner": null,
"stage": "test",
"status": "failed",
"failure_reason": "stuck_or_timeout_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/6",
"user": {
@ -207,6 +209,7 @@ Example of response
"runner": null,
"stage": "test",
"status": "failed",
"failure_reason": "stuck_or_timeout_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/6",
"user": {
@ -271,6 +274,7 @@ Example of response
"runner": null,
"stage": "test",
"status": "failed",
"failure_reason": "script_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/7",
"user": {
@ -443,6 +447,7 @@ Example of response
"runner": null,
"stage": "test",
"status": "failed",
"failure_reason": "script_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/8",
"user": {

View file

@ -145,6 +145,6 @@ PUT /projects/:id/external_status_checks/:check_id
| `external_url` | string | no | URL of external status check resource |
| `protected_branch_ids` | `array<Integer>` | no | IDs of protected branches to scope the rule by |
## Related links
## Related topics
- [External status checks](../user/project/merge_requests/status_checks.md).

View file

@ -11,7 +11,7 @@ The GitLab API v3 was [removed](https://gitlab.com/gitlab-org/gitlab-foss/-/issu
For information about the current version of the GitLab API, read the [API documentation](index.md).
## Related links
## Related topics
- [GitLab v3 API documentation](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/8-16-stable/doc/api/index.md)
- [Migration guide](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/11-0-stable/doc/api/v3_to_v4.md) from

View file

@ -199,8 +199,10 @@ use `include:file`. You can use `include:file` in combination with `include:proj
**Keyword type**: Global keyword.
**Possible inputs**: A full path, relative to the root directory (`/`).
The YAML file must have the extension `.yml` or `.yaml`.
**Possible inputs**:
- A full path, relative to the root directory (`/`). The YAML file must have the
extension `.yml` or `.yaml`.
**Example of `include:file`**:
@ -255,10 +257,10 @@ Use `include:remote` with a full URL to include a file from a different location
**Keyword type**: Global keyword.
**Possible inputs**: A public URL accessible by an HTTP/HTTPS `GET` request.
Authentication with the remote URL is not supported.
**Possible inputs**:
The YAML file must have the extension `.yml` or `.yaml`.
- A public URL accessible by an HTTP/HTTPS `GET` request. Authentication with the
remote URL is not supported. The YAML file must have the extension `.yml` or `.yaml`.
**Example of `include:remote`**:
@ -281,7 +283,9 @@ Use `include:template` to include [`.gitlab-ci.yml` templates](https://gitlab.co
**Keyword type**: Global keyword.
**Possible inputs**: [`.gitlab-ci.yml` templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
**Possible inputs**:
- [`.gitlab-ci.yml` templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
**Example of `include:template`**:
@ -556,7 +560,9 @@ The default value for `allow_failure` is:
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**: `true` or `false`.
**Possible inputs**:
- `true` or `false`.
**Example of `allow_failure`**:
@ -894,7 +900,9 @@ included templates in jobs.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
**Possible inputs**: See list of available [artifacts reports types](artifacts_reports.md).
**Possible inputs**:
- See list of available [artifacts reports types](artifacts_reports.md).
**Example of `artifacts:reports`**:
@ -1024,14 +1032,15 @@ Use the `cache:paths` keyword to choose which files or directories to cache.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
**Possible inputs**: An array of paths relative to the project directory (`$CI_PROJECT_DIR`).
You can use wildcards that use [glob](https://en.wikipedia.org/wiki/Glob_(programming))
patterns:
**Possible inputs**:
- In [GitLab Runner 13.0 and later](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620),
[`doublestar.Glob`](https://pkg.go.dev/github.com/bmatcuk/doublestar@v1.2.2?tab=doc#Match).
- In GitLab Runner 12.10 and earlier,
[`filepath.Match`](https://pkg.go.dev/path/filepath#Match).
- An array of paths relative to the project directory (`$CI_PROJECT_DIR`).
You can use wildcards that use [glob](https://en.wikipedia.org/wiki/Glob_(programming))
patterns:
- In [GitLab Runner 13.0 and later](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620),
[`doublestar.Glob`](https://pkg.go.dev/github.com/bmatcuk/doublestar@v1.2.2?tab=doc#Match).
- In GitLab Runner 12.10 and earlier,
[`filepath.Match`](https://pkg.go.dev/path/filepath#Match).
**Example of `cache:paths`**:
@ -1114,7 +1123,9 @@ which speeds up subsequent pipeline runs.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
**Possible inputs**: An array of one or two file paths.
**Possible inputs**:
- An array of one or two file paths.
**Example of `cache:key:files`**:
@ -1190,7 +1201,9 @@ Use `untracked: true` to cache all files that are untracked in your Git reposito
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
**Possible inputs**: `true` or `false` (default).
**Possible inputs**:
- `true` or `false` (default).
**Example of `cache:untracked`**:
@ -1303,7 +1316,9 @@ line in the job output matches the regular expression.
To extract the code coverage value in the matching line, GitLab uses this
regular expression: `\d+(\.\d+)?`.
**Possible inputs**: A regular expression. Must start and end with `/`.
**Possible inputs**:
- A regular expression. Must start and end with `/`.
**Example of `coverage`**:
@ -1811,7 +1826,9 @@ where each shell token is a separate string in the array.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
**Possible inputs**: A string.
**Possible inputs**:
- A string.
**Example of `image:entrypoint`**:
@ -1918,7 +1935,9 @@ You can't cancel subsequent jobs after a job with `interruptible: false` starts.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
**Possible inputs**: `true` or `false` (default).
**Possible inputs**:
- `true` or `false` (default).
**Example of `interruptible`**:
@ -2411,7 +2430,9 @@ to a pipeline, based on the status of [CI/CD variables](../variables/index.md).
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**: An array of [CI/CD variable expressions](../jobs/job_control.md#cicd-variable-expressions).
**Possible inputs**:
- An array of [CI/CD variable expressions](../jobs/job_control.md#cicd-variable-expressions).
**Example of `only:variables`**:
@ -2490,7 +2511,9 @@ when the Kubernetes service is active in the project.
**Keyword type**: Job-specific. You can use it only as part of a job.
**Possible inputs**: The `kubernetes` strategy accepts only the `active` keyword.
**Possible inputs**:
- The `kubernetes` strategy accepts only the `active` keyword.
**Example of `only:kubernetes`**:
@ -2546,7 +2569,9 @@ Parallel jobs are named sequentially from `job_name 1/N` to `job_name N/N`.
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**: A numeric value from `2` to `50`.
**Possible inputs**:
- A numeric value from `2` to `50`.
**Example of `parallel`**:
@ -2579,7 +2604,9 @@ Multiple runners must exist, or a single runner must be configured to run multip
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**: A numeric value from `2` to `50`.
**Possible inputs**:
- A numeric value from `2` to `50`.
**Example of `parallel:matrix`**:
@ -2699,7 +2726,9 @@ New tags use the SHA associated with the pipeline.
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**: A tag name. Can use [CI/CD variables](../variables/index.md).
**Possible inputs**:
- A tag name. Can use [CI/CD variables](../variables/index.md).
**Example of `release:tag_name`**:
@ -2738,7 +2767,9 @@ The release name. If omitted, it is populated with the value of `release: tag_na
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**: A text string.
**Possible inputs**:
- A text string.
**Example of `release:name`**:
@ -2843,8 +2874,10 @@ can be deployed to, but only one deployment can occur per device at any given ti
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**: Only letters, digits, `-`, `_`, `/`, `$`, `{`, `}`, `.`, and spaces.
It can't start or end with `/`.
**Possible inputs**:
- Only letters, digits, `-`, `_`, `/`, `$`, `{`, `}`, `.`, and spaces.
It can't start or end with `/`.
**Example of `resource_group`**:
@ -2875,7 +2908,9 @@ to select which failures to retry on.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
**Possible inputs**: `0` (default), `1`, or `2`.
**Possible inputs**:
- `0` (default), `1`, or `2`.
**Example of `retry`**:
@ -2894,7 +2929,9 @@ Use `retry:when` with `retry:max` to retry jobs for only specific failure cases.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
**Possible inputs**: A single failure type, or an array of one or more failure types:
**Possible inputs**:
- A single failure type, or an array of one or more failure types:
<!--
If you change any of the values below, make sure to update the `RETRY_WHEN_IN_DOCUMENTATION`
@ -3002,7 +3039,9 @@ or [custom CI/CD variables](../variables/index.md#custom-cicd-variables).
**Keyword type**: Job-specific and pipeline-specific. You can use it as part of a job
to configure the job behavior, or with [`workflow`](#workflow) to configure the pipeline behavior.
**Possible inputs**: A [CI/CD variable expression](../jobs/job_control.md#cicd-variable-expressions).
**Possible inputs**:
- A [CI/CD variable expression](../jobs/job_control.md#cicd-variable-expressions).
**Example of `rules:if`**:
@ -3048,8 +3087,9 @@ branch or merge request pipelines.
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**: An array of file paths. In GitLab 13.6 and later,
[file paths can include variables](../jobs/job_control.md#variables-in-ruleschanges).
**Possible inputs**:
- An array of file paths. In GitLab 13.6 and later, [file paths can include variables](../jobs/job_control.md#variables-in-ruleschanges).
**Example of `rules:changes`**:
@ -3083,8 +3123,10 @@ Use `exists` to run a job when certain files exist in the repository.
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**: An array of file paths. Paths are relative to the project directory (`$CI_PROJECT_DIR`)
and can't directly link outside it. File paths can use glob patterns.
**Possible inputs**:
- An array of file paths. Paths are relative to the project directory (`$CI_PROJECT_DIR`)
and can't directly link outside it. File paths can use glob patterns.
**Example of `rules:exists`**:
@ -3122,7 +3164,9 @@ job to run before continuing.
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**: `true` or `false`. Defaults to `false` if not defined.
**Possible inputs**:
- `true` or `false`. Defaults to `false` if not defined.
**Example of `rules:allow_failure`**:
@ -3151,7 +3195,9 @@ Use [`variables`](#variables) in `rules` to define variables for specific condit
**Keyword type**: Job-specific. You can use it only as part of a job.
**Possible inputs**: A hash of variables in the format `VARIABLE-NAME: value`.
**Possible inputs**:
- A hash of variables in the format `VARIABLE-NAME: value`.
**Example of `rules:variables`**:
@ -3286,7 +3332,9 @@ the secret value directly in the variable.
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**: `true` (default) or `false`.
**Possible inputs**:
- `true` (default) or `false`.
**Example of `secrets:file`**:
@ -3552,7 +3600,7 @@ Use `trigger` to start a downstream pipeline that is either:
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**:
**Possible inputs**:
- For multi-project pipelines, path to the downstream project.
- For child pipelines, path to the child pipeline CI/CD configuration file.
@ -3682,7 +3730,9 @@ Must be used with `value`, for the variable value.
**Keyword type**: Global keyword. You cannot set job-level variables to be pre-filled when you run a pipeline manually.
**Possible inputs**: A string.
**Possible inputs**:
- A string.
**Example of `variables:description`**:

View file

@ -134,7 +134,7 @@ After configuring GitLab for the two databases, create the new CI/CD database:
and run any pending migrations:
```shell
bundle exec rails rails db:create db:schema:load:ci db:migrate
bundle exec rails db:create db:schema:load:ci db:migrate
```
1. Restart GDK:

View file

@ -220,6 +220,20 @@ The `* as-if-jh` jobs are run in addition to the regular EE-context jobs. The `j
The intent is to ensure that a change doesn't introduce a failure after the `gitlab-org/gitlab` project is synced to
the `gitlab-jh/gitlab` project.
## `undercover` RSpec test
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74859) in GitLab 14.6.
The `rspec:undercoverage` job runs [`undercover`](https://rubygems.org/gems/undercover)
to detect, and fail if any changes introduced in the merge request has zero coverage.
The `rsepc:undercoverage` job obtains coverage data from the `rspec:coverage`
job.
In the event of an emergency, or false positive from this job, add the
`pipeline:skip-undercoverage` label to the merge request to allow this job to
fail.
## PostgreSQL versions testing
Our test suite runs against PG12 as GitLab.com runs on PG12 and

View file

@ -46,6 +46,6 @@ project, group, or instance level:
When the integration sends data, you can view it in the [CI Visibility](https://app.datadoghq.com/ci)
section of your Datadog account.
## Related links
## Related topics
- [Datadog's CI Visibility](https://docs.datadoghq.com/continuous_integration/) documentation.

View file

@ -74,7 +74,7 @@ into a different branch (`stable`):
git cherry-pick <SHA>
```
## Related links
## Related topics
- Cherry-pick commits with [the Commits API](../../api/commits.md#cherry-pick-a-commit)
- Git documentation [for cherry-picks](https://git-scm.com/docs/git-cherry-pick)

View file

@ -88,7 +88,7 @@ sees in the project's search results respectively.
|:---------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------|
| ![Confidential issues search by maintainer](img/confidential_issues_search_master.png) | ![Confidential issues search by guest](img/confidential_issues_search_guest.png) |
## Related links
## Related topics
- [Merge requests for confidential issues](../merge_requests/confidential.md)
- [Make an epic confidential](../../group/epics/manage_epics.md#make-an-epic-confidential)

View file

@ -105,7 +105,7 @@ Without the approvals, the work cannot merge. Required approvals enable multiple
- [Require approval from a security team](../../../application_security/index.md#security-approvals-in-merge-requests)
before merging code that could introduce a vulnerability. **(ULTIMATE)**
## Related links
## Related topics
- [Merge request approvals API](../../../../api/merge_request_approvals.md)
- [Instance-level approval rules](../../../admin_area/merge_requests_approvals.md) for self-managed installations

View file

@ -157,7 +157,7 @@ You can also enforce merge request approval settings:
If the settings are inherited by a group or project, they cannot be changed in the group or project
that inherited them.
## Related links
## Related topics
- [Instance-level merge request approval settings](../../../admin_area/merge_requests_approvals.md)
- [Compliance report](../../../compliance/compliance_report/index.md)

View file

@ -79,7 +79,7 @@ merge request is from a fork:
1. (Optional) Select **Start a new merge request** if you're ready to create a merge request.
1. Click **Cherry-pick**.
## Related links
## Related topics
- The [Commits API](../../../api/commits.md) enables you to add custom messages
to changes you cherry-pick through the API.

View file

@ -70,7 +70,7 @@ Open a merge request
- You are satisfied the problem is resolved in your private fork.
- You are ready to make the confidential commits public.
## Related links
## Related topics
- [Confidential issues](../issues/confidential_issues.md)
- [Make an epic confidential](../../group/epics/manage_epics.md#make-an-epic-confidential)

View file

@ -144,6 +144,6 @@ to your branch to address your reviewers' requests.
WARNING:
Suggestions applied from multiple authors creates a commit authored by the user applying the suggestions.
## Related links
## Related topics
- [Suggestions API](../../../../api/suggestions.md)

View file

@ -181,6 +181,6 @@ You should:
- Check the [GitLab status page](https://status.gitlab.com/) if the problem persists,
to see if there is a wider outage.
## Related links
## Related topics
- [External status checks API](../../../api/status_checks.md)

View file

@ -248,9 +248,19 @@ When you [rename a user](../../profile/index.md#change-your-username),
- The redirects are available as long as the original path is not claimed by
another group, user, or project.
## Related links
## Related topics
- [GitLab Workflow VS Code extension](vscode.md)
- [GitLab Workflow VS Code extension](vscode.md).
- To lock files and prevent change conflicts, use [file locking](../file_lock.md).
- [Repository API](../../../api/repositories.md).
- [Find files](file_finder.md) in a repository.
- [Branches](branches/index.md).
- [File templates](web_editor.md#template-dropdowns).
- [Create a directory](web_editor.md#create-a-directory).
- [Start a merge request](web_editor.md#tips).
- [Find file history](git_history.md).
- [Identify changes by line (Git blame)](git_blame.md).
- [Use Jupyter notebooks with GitLab](jupyter_notebooks/index.md).
## Troubleshooting
@ -287,16 +297,3 @@ The same approach should also allow misidentified file types to be fixed.
```
`*.txt` files have an entry in the heuristics file. This example prevents parsing of these files.
## Related topics
- To lock files and prevent change conflicts, use [file locking](../file_lock.md).
- [Repository API](../../../api/repositories.md).
- [Find files](file_finder.md) in a repository.
- [Branches](branches/index.md).
- [File templates](web_editor.md#template-dropdowns).
- [Create a directory](web_editor.md#create-a-directory).
- [Start a merge request](web_editor.md#tips).
- [Find file history](git_history.md).
- [Identify changes by line (Git blame)](git_blame.md).
- [Use Jupyter notebooks with GitLab](jupyter_notebooks/index.md).

View file

@ -123,7 +123,7 @@ To do so:
With this option enabled, `75h` is displayed instead of `1w 4d 3h`.
## Related links
## Related topics
- [Time tracking solutions page](https://about.gitlab.com/solutions/time-tracking/)
- Time tracking GraphQL references:

View file

@ -13,6 +13,7 @@ module API
expose :user, with: ::API::Entities::User
expose :commit, with: ::API::Entities::Commit
expose :pipeline, with: ::API::Entities::Ci::PipelineBasic
expose :failure_reason, if: -> (job) { job.failed? }
expose :web_url do |job, _options|
Gitlab::Routing.url_helpers.project_job_url(job.project, job)

View file

@ -4,8 +4,6 @@ module Gitlab
module Partitioning
class DetachedPartitionDropper
def perform
return unless Feature.enabled?(:drop_detached_partitions, default_enabled: :yaml)
Gitlab::AppLogger.info(message: "Checking for previously detached partitions to drop")
Postgresql::DetachedPartition.ready_to_drop.find_each do |detached_partition|

View file

@ -25,10 +25,8 @@ module Gitlab
partitions_to_create = missing_partitions
create(partitions_to_create) unless partitions_to_create.empty?
if Feature.enabled?(:partition_pruning, default_enabled: :yaml)
partitions_to_detach = extra_partitions
detach(partitions_to_detach) unless partitions_to_detach.empty?
end
partitions_to_detach = extra_partitions
detach(partitions_to_detach) unless partitions_to_detach.empty?
end
rescue StandardError => e
Gitlab::AppLogger.error(message: "Failed to create / detach partition(s)",

View file

@ -19,7 +19,7 @@ module QA
end
def image
@image || 'gitlab/gitlab-runner:alpine'
@image || 'registry.gitlab.com/gitlab-org/gitlab-runner:alpine'
end
def executor

3
scripts/undercoverage Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env bash
bundle exec undercover -c "${CI_MERGE_REQUEST_DIFF_BASE_SHA:-$(git merge-base origin/master HEAD)}"

View file

@ -429,6 +429,38 @@
</figcaption>
</figure>
- name: footnotes
substitutions:
# NOTE: We don't care about verifying specific attribute values here, that should be the
# responsibility of unit tests. These tests are about the structure of the HTML.
fn_href_substitution:
- regex: '(href)(=")(.+?)(")'
replacement: '\1\2REF\4'
footnote_id_substitution:
- regex: '(id)(=")(.+?)(")'
replacement: '\1\2ID\4'
pending:
backend: https://gitlab.com/gitlab-org/gitlab/-/issues/346591
markdown: |-
A footnote reference tag looks like this: [^1]
This reference tag is a mix of letters and numbers. [^2]
[^1]: This is the text inside a footnote.
[^2]: This is another footnote.
html: |-
<p data-sourcepos="1:1-1:46" dir="auto">A footnote reference tag looks like this: <sup class="footnote-ref"><a href="#fn-1-2717" id="fnref-1-2717" data-footnote-ref="">1</a></sup></p>
<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-2-2717" id="fnref-2-2717" data-footnote-ref="">2</a></sup></p>
<section class="footnotes" data-footnotes><ol>
<li id="fn-1-2717">
<p data-sourcepos="5:7-5:41">This is the text inside a footnote. <a href="#fnref-1-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>
<li id="fn-2-2717">
<p data-sourcepos="6:7-6:31">This is another footnote. <a href="#fnref-2-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>
- name: frontmatter_json
markdown: |-
;;;

View file

@ -11,6 +11,9 @@ import Division from '~/content_editor/extensions/division';
import Emoji from '~/content_editor/extensions/emoji';
import Figure from '~/content_editor/extensions/figure';
import FigureCaption from '~/content_editor/extensions/figure_caption';
import FootnoteDefinition from '~/content_editor/extensions/footnote_definition';
import FootnoteReference from '~/content_editor/extensions/footnote_reference';
import FootnotesSection from '~/content_editor/extensions/footnotes_section';
import HardBreak from '~/content_editor/extensions/hard_break';
import Heading from '~/content_editor/extensions/heading';
import HorizontalRule from '~/content_editor/extensions/horizontal_rule';
@ -46,6 +49,9 @@ const tiptapEditor = createTestEditor({
DetailsContent,
Division,
Emoji,
FootnoteDefinition,
FootnoteReference,
FootnotesSection,
Figure,
FigureCaption,
HardBreak,
@ -81,6 +87,9 @@ const {
descriptionItem,
descriptionList,
emoji,
footnoteDefinition,
footnoteReference,
footnotesSection,
figure,
figureCaption,
heading,
@ -117,6 +126,9 @@ const {
emoji: { markType: Emoji.name },
figure: { nodeType: Figure.name },
figureCaption: { nodeType: FigureCaption.name },
footnoteDefinition: { nodeType: FootnoteDefinition.name },
footnoteReference: { nodeType: FootnoteReference.name },
footnotesSection: { nodeType: FootnotesSection.name },
hardBreak: { nodeType: HardBreak.name },
heading: { nodeType: Heading.name },
horizontalRule: { nodeType: HorizontalRule.name },
@ -1105,4 +1117,22 @@ there
`.trim(),
);
});
it('correctly serializes footnotes', () => {
expect(
serialize(
paragraph(
'Oranges are orange ',
footnoteReference({ footnoteId: '1', footnoteNumber: '1' }),
),
footnotesSection(footnoteDefinition(paragraph('Oranges are fruits'))),
),
).toBe(
`
Oranges are orange [^1]
[^1]: Oranges are fruits
`.trim(),
);
});
});

View file

@ -0,0 +1,220 @@
import { merge } from 'lodash';
import { GlFormInputGroup } from '@gitlab/ui';
import InputCopyToggleVisibility from '~/vue_shared/components/form/input_copy_toggle_visibility.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { mountExtended } from 'helpers/vue_test_utils_helper';
describe('InputCopyToggleVisibility', () => {
let wrapper;
afterEach(() => {
wrapper.destroy();
});
const valueProp = 'hR8x1fuJbzwu5uFKLf9e';
const createComponent = (options = {}) => {
wrapper = mountExtended(
InputCopyToggleVisibility,
merge({}, options, {
directives: {
GlTooltip: createMockDirective(),
},
}),
);
};
const findFormInputGroup = () => wrapper.findComponent(GlFormInputGroup);
const findFormInput = () => findFormInputGroup().find('input');
const findRevealButton = () =>
wrapper.findByRole('button', {
name: InputCopyToggleVisibility.i18n.toggleVisibilityLabelReveal,
});
const findHideButton = () =>
wrapper.findByRole('button', {
name: InputCopyToggleVisibility.i18n.toggleVisibilityLabelHide,
});
const findCopyButton = () => wrapper.findComponent(ClipboardButton);
const createCopyEvent = () => {
const event = new Event('copy', { cancelable: true });
Object.assign(event, { preventDefault: jest.fn(), clipboardData: { setData: jest.fn() } });
return event;
};
const itDoesNotModifyCopyEvent = () => {
it('does not modify copy event', () => {
const event = createCopyEvent();
findFormInput().element.dispatchEvent(event);
expect(event.clipboardData.setData).not.toHaveBeenCalled();
expect(event.preventDefault).not.toHaveBeenCalled();
});
};
describe('when `value` prop is passed', () => {
beforeEach(() => {
createComponent({
propsData: {
value: valueProp,
},
});
});
it('displays value as hidden', () => {
expect(findFormInputGroup().props('value')).toBe('********************');
});
it('saves actual value to clipboard when manually copied', () => {
const event = createCopyEvent();
findFormInput().element.dispatchEvent(event);
expect(event.clipboardData.setData).toHaveBeenCalledWith('text/plain', valueProp);
expect(event.preventDefault).toHaveBeenCalled();
});
describe('visibility toggle button', () => {
it('renders a reveal button', () => {
const revealButton = findRevealButton();
expect(revealButton.exists()).toBe(true);
const tooltip = getBinding(revealButton.element, 'gl-tooltip');
expect(tooltip.value).toBe(InputCopyToggleVisibility.i18n.toggleVisibilityLabelReveal);
});
describe('when clicked', () => {
beforeEach(async () => {
await findRevealButton().trigger('click');
});
it('displays value', () => {
expect(findFormInputGroup().props('value')).toBe(valueProp);
});
it('renders a hide button', () => {
const hideButton = findHideButton();
expect(hideButton.exists()).toBe(true);
const tooltip = getBinding(hideButton.element, 'gl-tooltip');
expect(tooltip.value).toBe(InputCopyToggleVisibility.i18n.toggleVisibilityLabelHide);
});
it('emits `visibility-change` event', () => {
expect(wrapper.emitted('visibility-change')[0]).toEqual([true]);
});
});
});
describe('copy button', () => {
it('renders button with correct props passed', () => {
expect(findCopyButton().props()).toMatchObject({
text: valueProp,
title: 'Copy',
});
});
describe('when clicked', () => {
beforeEach(async () => {
await findCopyButton().trigger('click');
});
it('emits `copy` event', () => {
expect(wrapper.emitted('copy')[0]).toEqual([]);
});
});
});
});
describe('when `value` prop is not passed', () => {
beforeEach(() => {
createComponent();
});
it('displays value as hidden with 20 asterisks', () => {
expect(findFormInputGroup().props('value')).toBe('********************');
});
});
describe('when `initialVisibility` prop is `true`', () => {
beforeEach(() => {
createComponent({
propsData: {
value: valueProp,
initialVisibility: true,
},
});
});
it('displays value', () => {
expect(findFormInputGroup().props('value')).toBe(valueProp);
});
itDoesNotModifyCopyEvent();
});
describe('when `showToggleVisibilityButton` is `false`', () => {
beforeEach(() => {
createComponent({
propsData: {
value: valueProp,
showToggleVisibilityButton: false,
},
});
});
it('does not render visibility toggle button', () => {
expect(findRevealButton().exists()).toBe(false);
expect(findHideButton().exists()).toBe(false);
});
it('displays value', () => {
expect(findFormInputGroup().props('value')).toBe(valueProp);
});
itDoesNotModifyCopyEvent();
});
describe('when `showCopyButton` is `false`', () => {
beforeEach(() => {
createComponent({
propsData: {
showCopyButton: false,
},
});
});
it('does not render copy button', () => {
expect(findCopyButton().exists()).toBe(false);
});
});
it('passes `formInputGroupProps` prop to `GlFormInputGroup`', () => {
createComponent({
propsData: {
formInputGroupProps: {
label: 'Foo bar',
},
},
});
expect(findFormInputGroup().props('label')).toBe('Foo bar');
});
it('passes `copyButtonTitle` prop to `ClipboardButton`', () => {
createComponent({
propsData: {
copyButtonTitle: 'Copy token',
},
});
expect(findCopyButton().props('title')).toBe('Copy token');
});
});

View file

@ -90,18 +90,6 @@ RSpec.describe Gitlab::Database::Partitioning::DetachedPartitionDropper do
expect(table_oid('test_partition')).to be_nil
end
context 'when the drop_detached_partitions feature flag is disabled' do
before do
stub_feature_flags(drop_detached_partitions: false)
end
it 'does not drop the partition' do
dropper.perform
expect(table_oid('test_partition')).not_to be_nil
end
end
context 'removing foreign keys' do
it 'removes foreign keys from the table before dropping it' do
expect(dropper).to receive(:drop_detached_partition).and_wrap_original do |drop_method, partition_name|

View file

@ -101,28 +101,10 @@ RSpec.describe Gitlab::Database::Partitioning::PartitionManager do
]
end
context 'with the partition_pruning feature flag enabled' do
before do
stub_feature_flags(partition_pruning: true)
end
it 'detaches each extra partition' do
extra_partitions.each { |p| expect(manager).to receive(:detach_one_partition).with(p) }
it 'detaches each extra partition' do
extra_partitions.each { |p| expect(manager).to receive(:detach_one_partition).with(p) }
sync_partitions
end
end
context 'with the partition_pruning feature flag disabled' do
before do
stub_feature_flags(partition_pruning: false)
end
it 'returns immediately' do
expect(manager).not_to receive(:detach)
sync_partitions
end
sync_partitions
end
end

View file

@ -428,6 +428,26 @@ RSpec.describe API::Ci::Jobs do
end
end
context 'when job succeeded' do
it 'does not return failure_reason' do
get api("/projects/#{project.id}/jobs/#{job.id}", api_user)
expect(json_response).not_to include('failure_reason')
end
end
context 'when job failed' do
let(:job) do
create(:ci_build, :failed, :tags, pipeline: pipeline)
end
it 'returns failure_reason' do
get api("/projects/#{project.id}/jobs/#{job.id}", api_user)
expect(json_response).to include('failure_reason')
end
end
context 'when trace artifact record exists with no stored file', :skip_before_request do
before do
create(:ci_job_artifact, :unarchived_trace_artifact, job: job, project: job.project)

View file

@ -125,14 +125,6 @@ RSpec.describe Ci::RetryBuildService do
expect(new_build.needs_attributes).to match(build.needs_attributes)
expect(new_build.needs).not_to match(build.needs)
end
it 'clones only the job variables attributes' do
expect(new_build.job_variables.exists?).to be_truthy
expect(build.job_variables.exists?).to be_truthy
expect(new_build.job_variables_attributes).to match(build.job_variables_attributes)
expect(new_build.job_variables).not_to match(build.job_variables)
end
end
describe 'reject accessors' do
@ -155,7 +147,7 @@ RSpec.describe Ci::RetryBuildService do
Ci::Build.attribute_names.map(&:to_sym) +
Ci::Build.attribute_aliases.keys.map(&:to_sym) +
Ci::Build.reflect_on_all_associations.map(&:name) +
[:tag_list, :needs_attributes, :job_variables_attributes] -
[:tag_list, :needs_attributes] -
# ee-specific accessors should be tested in ee/spec/services/ci/retry_build_service_spec.rb instead
described_class.extra_accessors -
[:dast_site_profiles_build, :dast_scanner_profiles_build] # join tables

View file

@ -2,6 +2,7 @@
require 'simplecov'
require 'simplecov-cobertura'
require 'simplecov-lcov'
require_relative '../lib/gitlab/utils'
module SimpleCovEnv
@ -18,10 +19,13 @@ module SimpleCovEnv
end
def configure_formatter
SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
SimpleCov::Formatter::SimpleFormatter,
SimpleCov::Formatter::HTMLFormatter,
SimpleCov::Formatter::CoberturaFormatter
SimpleCov::Formatter::CoberturaFormatter,
SimpleCov::Formatter::LcovFormatter
])
end