Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
		
							parent
							
								
									7b78125a38
								
							
						
					
					
						commit
						ef615776bf
					
				| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +1 @@
 | 
			
		|||
4dd8bfe1307ffcc5a2a3f4eb70da7977a7c1d915
 | 
			
		||||
a191a5d10f0772ae2ed6ec869001ddde6d277827
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								Gemfile
								
								
								
								
							
							
						
						
									
										2
									
								
								Gemfile
								
								
								
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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];
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -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];
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -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];
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			@ -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!
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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).
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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`**:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,7 +88,7 @@ sees in the project's search results respectively.
 | 
			
		|||
|:---------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------|
 | 
			
		||||
|  |  |
 | 
			
		||||
 | 
			
		||||
## 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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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).
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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|
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
bundle exec undercover -c "${CI_MERGE_REQUEST_DIFF_BASE_SHA:-$(git merge-base origin/master HEAD)}"
 | 
			
		||||
| 
						 | 
				
			
			@ -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: |-
 | 
			
		||||
    ;;;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(),
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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');
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -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|
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue