summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-02-14 06:10:32 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-02-14 06:10:32 +0000
commitb02c014a8fd04fd3675d74d22ce855388ec66daa (patch)
tree301874cc84fe211a72c1ddd2d8a8331293646ca2
parent6be10e8588cd18091d8302fd52e166a71900f7bc (diff)
downloadgitlab-ce-b02c014a8fd04fd3675d74d22ce855388ec66daa.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.csscomb.json20
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml12
-rw-r--r--.rubocop_todo/rake/require.yml1
-rw-r--r--app/assets/javascripts/boards/components/board_filtered_search.vue1
-rw-r--r--app/assets/javascripts/issuable/components/issuable_header_warnings.vue6
-rw-r--r--app/assets/javascripts/issuable/components/status_box.vue4
-rw-r--r--app/assets/javascripts/issues/constants.js3
-rw-r--r--app/assets/javascripts/issues/show/components/app.vue14
-rw-r--r--app/assets/javascripts/issues/show/components/description.vue4
-rw-r--r--app/assets/javascripts/issues/show/components/form.vue4
-rw-r--r--app/assets/javascripts/notes/components/sidebar_subscription.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue8
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue11
-rw-r--r--app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/labels/labels_select_widget/labels_select_root.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/milestone/milestone_dropdown.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_dropdown.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue7
-rw-r--r--app/assets/javascripts/sidebar/constants.js28
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js26
-rw-r--r--app/assets/javascripts/vue_shared/components/user_select/user_select.vue4
-rw-r--r--app/assets/javascripts/vue_shared/constants.js6
-rw-r--r--config/sidekiq_queues.yml2
-rw-r--r--db/docs/automation_rules.yml10
-rw-r--r--db/migrate/20230203011359_create_automation_rules.rb28
-rw-r--r--db/post_migrate/20230131210921_prepare_index_for_vulnerability_reads_on_project_id_scanner_id_vulnerability_id.rb16
-rw-r--r--db/schema_migrations/202301312109211
-rw-r--r--db/schema_migrations/202302030113591
-rw-r--r--db/structure.sql35
-rw-r--r--doc/administration/reference_architectures/index.md14
-rw-r--r--doc/development/fe_guide/style/scss.md10
-rw-r--r--doc/user/group/roadmap/index.md2
-rw-r--r--lib/tasks/gitlab/artifacts/migrate.rake6
-rw-r--r--lib/tasks/gitlab/db.rake2
-rw-r--r--qa/Gemfile2
-rw-r--r--qa/Gemfile.lock4
-rw-r--r--spec/frontend/issues/show/components/app_spec.js11
-rw-r--r--spec/frontend/issues/show/components/locked_warning_spec.js61
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_participant_spec.js8
-rw-r--r--spec/frontend/sidebar/components/copy/sidebar_reference_widget_spec.js6
-rw-r--r--spec/frontend/sidebar/components/labels/labels_select_widget/labels_select_root_spec.js8
-rw-r--r--spec/frontend/sidebar/components/milestone/milestone_dropdown_spec.js4
-rw-r--r--spec/frontend/sidebar/components/sidebar_dropdown_spec.js6
-rw-r--r--spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/confidentiality_badge_spec.js10
-rw-r--r--spec/tasks/gitlab/db_rake_spec.rb9
48 files changed, 267 insertions, 186 deletions
diff --git a/.csscomb.json b/.csscomb.json
deleted file mode 100644
index aa6a17f7517..00000000000
--- a/.csscomb.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "exclude": [
- "app/assets/stylesheets/framework/tw_bootstrap_variables.scss",
- "app/assets/stylesheets/framework/fonts.scss"
- ],
- "always-semicolon": true,
- "color-case": "lower",
- "block-indent": " ",
- "color-shorthand": false,
- "element-case": "lower",
- "space-before-colon": "",
- "space-after-colon": " ",
- "space-before-combinator": " ",
- "space-after-combinator": " ",
- "space-between-declarations": "\n",
- "space-before-opening-brace": " ",
- "space-after-opening-brace": "\n",
- "space-before-closing-brace": "\n",
- "unitless-zero": true
-}
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index b4807bb60da..53adc2936f3 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -295,7 +295,7 @@
- ".browserslistrc"
- "babel.config.js"
- "jest.config.{base,integration,unit}.js"
- - ".csscomb.json"
+ - ".stylelintrc"
- "Dockerfile.assets"
- "config/**/*.js"
- "vendor/assets/**/*"
@@ -391,7 +391,7 @@
- ".browserslistrc"
- "babel.config.js"
- "jest.config.{base,integration,unit}.js"
- - ".csscomb.json"
+ - ".stylelintrc"
- "Dockerfile.assets"
- "vendor/assets/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
@@ -416,7 +416,7 @@
- ".browserslistrc"
- "babel.config.js"
- "jest.config.{base,integration,unit}.js"
- - ".csscomb.json"
+ - ".stylelintrc"
- "Dockerfile.assets"
- "vendor/assets/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
@@ -447,7 +447,7 @@
- ".browserslistrc"
- "babel.config.js"
- "jest.config.{base,integration,unit}.js"
- - ".csscomb.json"
+ - ".stylelintrc"
- "Dockerfile.assets"
- "vendor/assets/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
@@ -474,7 +474,7 @@
- ".browserslistrc"
- "babel.config.js"
- "jest.config.{base,integration,unit}.js"
- - ".csscomb.json"
+ - ".stylelintrc"
- "Dockerfile.assets"
- "vendor/assets/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
@@ -512,7 +512,7 @@
- ".browserslistrc"
- "babel.config.js"
- "jest.config.{base,integration,unit}.js"
- - ".csscomb.json"
+ - ".stylelintrc"
- "Dockerfile.assets"
- "vendor/assets/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
diff --git a/.rubocop_todo/rake/require.yml b/.rubocop_todo/rake/require.yml
index 60f40f20a6c..65b4fd311ad 100644
--- a/.rubocop_todo/rake/require.yml
+++ b/.rubocop_todo/rake/require.yml
@@ -2,7 +2,6 @@
Rake/Require:
Details: grace period
Exclude:
- - 'lib/tasks/gitlab/artifacts/migrate.rake'
- 'lib/tasks/gitlab/assets.rake'
- 'lib/tasks/gitlab/backup.rake'
- 'lib/tasks/gitlab/cleanup.rake'
diff --git a/app/assets/javascripts/boards/components/board_filtered_search.vue b/app/assets/javascripts/boards/components/board_filtered_search.vue
index ce86a4d3123..1bc5d910561 100644
--- a/app/assets/javascripts/boards/components/board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/board_filtered_search.vue
@@ -327,7 +327,6 @@ export default {
if (Array.isArray(value)) {
return value.map((valueItem) => encodeURIComponent(valueItem));
}
-
return encodeURIComponent(value);
}
diff --git a/app/assets/javascripts/issuable/components/issuable_header_warnings.vue b/app/assets/javascripts/issuable/components/issuable_header_warnings.vue
index 14325d6b64e..0e58f3793bc 100644
--- a/app/assets/javascripts/issuable/components/issuable_header_warnings.vue
+++ b/app/assets/javascripts/issuable/components/issuable_header_warnings.vue
@@ -2,7 +2,7 @@
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { mapGetters } from 'vuex';
import { sprintf, __ } from '~/locale';
-import { IssuableType, WorkspaceType } from '~/issues/constants';
+import { TYPE_ISSUE, WorkspaceType } from '~/issues/constants';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ConfidentialityBadge from '~/vue_shared/components/confidentiality_badge.vue';
@@ -12,8 +12,8 @@ const NoteableTypeText = {
};
export default {
+ TYPE_ISSUE,
WorkspaceType,
- IssuableType,
components: {
GlIcon,
ConfidentialityBadge,
@@ -61,7 +61,7 @@ export default {
v-if="isConfidential"
data-testid="confidential"
:workspace-type="$options.WorkspaceType.project"
- :issuable-type="$options.IssuableType.Issue"
+ :issuable-type="$options.TYPE_ISSUE"
/>
<template v-for="meta in warningIconsMeta">
<div
diff --git a/app/assets/javascripts/issuable/components/status_box.vue b/app/assets/javascripts/issuable/components/status_box.vue
index 6c4ffc44444..0c75e44443d 100644
--- a/app/assets/javascripts/issuable/components/status_box.vue
+++ b/app/assets/javascripts/issuable/components/status_box.vue
@@ -4,7 +4,7 @@ import Vue from 'vue';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { fetchPolicies } from '~/lib/graphql';
import { __ } from '~/locale';
-import { IssuableType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE } from '~/issues/constants';
import { IssuableStates } from '~/vue_shared/issuable/list/constants';
export const badgeState = Vue.observable({
@@ -92,7 +92,7 @@ export default {
return STATUS[this.state];
},
badgeIcon() {
- if (this.issuableType === IssuableType.Issue) {
+ if (this.issuableType === TYPE_ISSUE) {
return ISSUE_ICONS[this.state];
}
return MERGE_REQUEST_ICONS[this.state];
diff --git a/app/assets/javascripts/issues/constants.js b/app/assets/javascripts/issues/constants.js
index c359420a680..10d1a2d0dbf 100644
--- a/app/assets/javascripts/issues/constants.js
+++ b/app/assets/javascripts/issues/constants.js
@@ -6,12 +6,15 @@ export const STATUS_REOPENED = 'reopened';
export const TITLE_LENGTH_MAX = 255;
+export const TYPE_ISSUE = 'issue';
+
export const IssuableStatusText = {
[STATUS_CLOSED]: __('Closed'),
[STATUS_OPEN]: __('Open'),
[STATUS_REOPENED]: __('Open'),
};
+// Deprecated - use individual constants instead like `TYPE_ISSUE` above
export const IssuableType = {
Issue: 'issue',
Epic: 'epic',
diff --git a/app/assets/javascripts/issues/show/components/app.vue b/app/assets/javascripts/issues/show/components/app.vue
index ffded421f74..a0db1ddcf6f 100644
--- a/app/assets/javascripts/issues/show/components/app.vue
+++ b/app/assets/javascripts/issues/show/components/app.vue
@@ -2,7 +2,13 @@
import { GlIcon, GlBadge, GlIntersectionObserver, GlTooltipDirective } from '@gitlab/ui';
import Visibility from 'visibilityjs';
import { createAlert } from '~/flash';
-import { IssuableStatusText, WorkspaceType, IssuableType, STATUS_CLOSED } from '~/issues/constants';
+import {
+ IssuableStatusText,
+ IssuableType,
+ STATUS_CLOSED,
+ TYPE_ISSUE,
+ WorkspaceType,
+} from '~/issues/constants';
import Poll from '~/lib/utils/poll';
import { visitUrl } from '~/lib/utils/url_utility';
import { __, sprintf } from '~/locale';
@@ -151,7 +157,7 @@ export default {
issuableType: {
type: String,
required: false,
- default: IssuableType.Issue,
+ default: TYPE_ISSUE,
},
canAttachFile: {
type: Boolean,
@@ -259,7 +265,7 @@ export default {
: '';
},
statusIcon() {
- if (this.issuableType === IssuableType.Issue) {
+ if (this.issuableType === TYPE_ISSUE) {
return this.isClosed ? 'issue-closed' : 'issues';
}
return this.isClosed ? 'epic-closed' : 'epic';
@@ -271,7 +277,7 @@ export default {
return IssuableStatusText[this.issuableStatus];
},
shouldShowStickyHeader() {
- return [IssuableType.Issue, IssuableType.Epic].includes(this.issuableType);
+ return [TYPE_ISSUE, IssuableType.Epic].includes(this.issuableType);
},
},
created() {
diff --git a/app/assets/javascripts/issues/show/components/description.vue b/app/assets/javascripts/issues/show/components/description.vue
index 05edc51171f..83ba5f3371c 100644
--- a/app/assets/javascripts/issues/show/components/description.vue
+++ b/app/assets/javascripts/issues/show/components/description.vue
@@ -9,7 +9,7 @@ import SafeHtml from '~/vue_shared/directives/safe_html';
import { getIdFromGraphQLId, convertToGraphQLId } from '~/graphql_shared/utils';
import { TYPENAME_WORK_ITEM } from '~/graphql_shared/constants';
import { createAlert } from '~/flash';
-import { IssuableType } from '~/issues/constants';
+import { TYPE_ISSUE } from '~/issues/constants';
import { isMetaKey } from '~/lib/utils/common_utils';
import { isPositiveInteger } from '~/lib/utils/number_utils';
import { getParameterByName, setUrlParams, updateHistory } from '~/lib/utils/url_utility';
@@ -80,7 +80,7 @@ export default {
issuableType: {
type: String,
required: false,
- default: IssuableType.Issue,
+ default: TYPE_ISSUE,
},
updateUrl: {
type: String,
diff --git a/app/assets/javascripts/issues/show/components/form.vue b/app/assets/javascripts/issues/show/components/form.vue
index b56c91d7983..bcea9cf57a7 100644
--- a/app/assets/javascripts/issues/show/components/form.vue
+++ b/app/assets/javascripts/issues/show/components/form.vue
@@ -1,7 +1,7 @@
<script>
import { GlAlert } from '@gitlab/ui';
import { getDraft, updateDraft, getLockVersion, clearDraft } from '~/lib/utils/autosave';
-import { IssuableType } from '~/issues/constants';
+import { TYPE_ISSUE } from '~/issues/constants';
import eventHub from '../event_hub';
import EditActions from './edit_actions.vue';
import DescriptionField from './fields/description.vue';
@@ -98,7 +98,7 @@ export default {
return this.formState.lockedWarningVisible && !this.formState.updateLoading;
},
isIssueType() {
- return this.issuableType === IssuableType.Issue;
+ return this.issuableType === TYPE_ISSUE;
},
},
watch: {
diff --git a/app/assets/javascripts/notes/components/sidebar_subscription.vue b/app/assets/javascripts/notes/components/sidebar_subscription.vue
index 9fc11ff65d5..a33f4364097 100644
--- a/app/assets/javascripts/notes/components/sidebar_subscription.vue
+++ b/app/assets/javascripts/notes/components/sidebar_subscription.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions } from 'vuex';
-import { IssuableType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE } from '~/issues/constants';
import { fetchPolicies } from '~/lib/graphql';
import { confidentialityQueries } from '~/sidebar/constants';
import { defaultClient as gqlClient } from '~/graphql_shared/issuable_client';
@@ -28,7 +28,7 @@ export default {
},
},
created() {
- if (this.issuableType !== IssuableType.Issue && this.issuableType !== IssuableType.Epic) {
+ if (this.issuableType !== TYPE_ISSUE && this.issuableType !== IssuableType.Epic) {
return;
}
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
index d6c679f2f07..8893e90b1e5 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
@@ -2,7 +2,7 @@
import { GlDropdownItem } from '@gitlab/ui';
import Vue from 'vue';
import { createAlert } from '~/flash';
-import { IssuableType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE } from '~/issues/constants';
import { __, n__ } from '~/locale';
import UserSelect from '~/vue_shared/components/user_select/user_select.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -58,9 +58,9 @@ export default {
issuableType: {
type: String,
required: false,
- default: IssuableType.Issue,
+ default: TYPE_ISSUE,
validator(value) {
- return [IssuableType.Issue, IssuableType.MergeRequest, IssuableType.Alert].includes(value);
+ return [TYPE_ISSUE, IssuableType.MergeRequest, IssuableType.Alert].includes(value);
},
},
issuableId: {
@@ -118,7 +118,7 @@ export default {
computed: {
shouldEnableRealtime() {
// Note: Realtime is only available on issues right now, future support for MR wil be built later.
- return this.issuableType === IssuableType.Issue;
+ return this.issuableType === TYPE_ISSUE;
},
queryVariables() {
return {
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue
index 29298ef7627..ddbd8866680 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue
@@ -1,6 +1,6 @@
<script>
import { GlAvatarLabeled, GlIcon } from '@gitlab/ui';
-import { IssuableType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE } from '~/issues/constants';
import { s__, sprintf } from '~/locale';
const AVAILABILITY_STATUS = {
@@ -21,7 +21,7 @@ export default {
issuableType: {
type: String,
required: false,
- default: IssuableType.Issue,
+ default: TYPE_ISSUE,
},
},
computed: {
diff --git a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue
index dbedfe57325..f7526bcff3d 100644
--- a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue
@@ -1,7 +1,7 @@
<script>
import { GlSprintf, GlButton } from '@gitlab/ui';
import { createAlert } from '~/flash';
-import { IssuableType } from '~/issues/constants';
+import { TYPE_ISSUE } from '~/issues/constants';
import { __, sprintf } from '~/locale';
import { confidentialityQueries } from '../../constants';
@@ -53,11 +53,14 @@ export default {
? this.$options.i18n.confidentialityOffWarning
: this.$options.i18n.confidentialityOnWarning;
},
+ isIssue() {
+ return this.issuableType === TYPE_ISSUE;
+ },
context() {
- return this.issuableType === IssuableType.Issue ? __('project') : __('group');
+ return this.isIssue ? __('project') : __('group');
},
workspacePath() {
- return this.issuableType === IssuableType.Issue
+ return this.isIssue
? {
projectPath: this.fullPath,
}
@@ -66,7 +69,7 @@ export default {
};
},
permissions() {
- return this.issuableType === IssuableType.Issue
+ return this.isIssue
? __('at least the Reporter role, the author, and assignees')
: __('at least the Reporter role');
},
diff --git a/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue b/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue
index 3bc65e02ce4..77be8022ec0 100644
--- a/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue
+++ b/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue
@@ -1,7 +1,7 @@
<script>
import { GlIcon, GlDatepicker, GlTooltipDirective, GlLink, GlPopover } from '@gitlab/ui';
import { createAlert } from '~/flash';
-import { IssuableType } from '~/issues/constants';
+import { TYPE_ISSUE } from '~/issues/constants';
import { dateInWords, formatDate, parsePikadayDate } from '~/lib/utils/datetime_utility';
import { __, sprintf } from '~/locale';
import { dateFields, dateTypes, dueDateQueries, startDateQueries, Tracking } from '../../constants';
@@ -142,7 +142,7 @@ export default {
return dateInWords(this.parsedDate, true);
},
workspacePath() {
- return this.issuableType === IssuableType.Issue
+ return this.issuableType === TYPE_ISSUE
? {
projectPath: this.fullPath,
}
diff --git a/app/assets/javascripts/sidebar/components/labels/labels_select_widget/labels_select_root.vue b/app/assets/javascripts/sidebar/components/labels/labels_select_widget/labels_select_root.vue
index f23648c91a9..60361b7de67 100644
--- a/app/assets/javascripts/sidebar/components/labels/labels_select_widget/labels_select_root.vue
+++ b/app/assets/javascripts/sidebar/components/labels/labels_select_widget/labels_select_root.vue
@@ -4,7 +4,7 @@ import issuableLabelsSubscription from 'ee_else_ce/sidebar/queries/issuable_labe
import { MutationOperationMode, getIdFromGraphQLId } from '~/graphql_shared/utils';
import { createAlert } from '~/flash';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { IssuableType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE } from '~/issues/constants';
import { __ } from '~/locale';
import { issuableLabelsQueries } from '../../../constants';
@@ -261,7 +261,7 @@ export default {
};
switch (this.issuableType) {
- case IssuableType.Issue:
+ case TYPE_ISSUE:
case IssuableType.TestCase:
return updateVariables;
case IssuableType.MergeRequest:
@@ -318,7 +318,7 @@ export default {
};
switch (this.issuableType) {
- case IssuableType.Issue:
+ case TYPE_ISSUE:
case IssuableType.TestCase:
return {
...removeVariables,
diff --git a/app/assets/javascripts/sidebar/components/milestone/milestone_dropdown.vue b/app/assets/javascripts/sidebar/components/milestone/milestone_dropdown.vue
index e31ff94b199..8072154cd28 100644
--- a/app/assets/javascripts/sidebar/components/milestone/milestone_dropdown.vue
+++ b/app/assets/javascripts/sidebar/components/milestone/milestone_dropdown.vue
@@ -2,7 +2,7 @@
import { GlDropdownItem } from '@gitlab/ui';
import { TYPENAME_MILESTONE } from '~/graphql_shared/constants';
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { IssuableType, WorkspaceType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE, WorkspaceType } from '~/issues/constants';
import { __ } from '~/locale';
import { IssuableAttributeType } from '../../constants';
import SidebarDropdown from '../sidebar_dropdown.vue';
@@ -37,7 +37,7 @@ export default {
type: String,
required: true,
validator(value) {
- return [IssuableType.Issue, IssuableType.MergeRequest].includes(value);
+ return [TYPE_ISSUE, IssuableType.MergeRequest].includes(value);
},
},
inputName: {
diff --git a/app/assets/javascripts/sidebar/components/sidebar_dropdown.vue b/app/assets/javascripts/sidebar/components/sidebar_dropdown.vue
index 26e2bc96f54..eaf87e4d4e0 100644
--- a/app/assets/javascripts/sidebar/components/sidebar_dropdown.vue
+++ b/app/assets/javascripts/sidebar/components/sidebar_dropdown.vue
@@ -8,7 +8,7 @@ import {
GlSearchBoxByType,
} from '@gitlab/ui';
import { kebabCase, snakeCase } from 'lodash';
-import { IssuableType, WorkspaceType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE, WorkspaceType } from '~/issues/constants';
import { __ } from '~/locale';
import {
defaultEpicSort,
@@ -70,7 +70,7 @@ export default {
type: String,
required: true,
validator(value) {
- return [IssuableType.Issue, IssuableType.MergeRequest].includes(value);
+ return [TYPE_ISSUE, IssuableType.MergeRequest].includes(value);
},
},
workspaceType: {
diff --git a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
index 35667495ace..994b96b7f30 100644
--- a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
+++ b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
@@ -3,7 +3,7 @@ import { GlButton, GlIcon, GlLink, GlPopover, GlTooltipDirective } from '@gitlab
import { kebabCase, snakeCase } from 'lodash';
import { createAlert } from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { IssuableType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE } from '~/issues/constants';
import { timeFor } from '~/lib/utils/datetime_utility';
import { __ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -71,7 +71,7 @@ export default {
type: String,
required: true,
validator(value) {
- return [IssuableType.Issue, IssuableType.MergeRequest].includes(value);
+ return [TYPE_ISSUE, IssuableType.MergeRequest].includes(value);
},
},
icon: {
@@ -188,7 +188,7 @@ export default {
fullPath: this.workspacePath,
attributeId:
this.issuableAttribute === IssuableAttributeType.Milestone &&
- this.issuableType === IssuableType.Issue
+ this.issuableType === TYPE_ISSUE
? getIdFromGraphQLId(id)
: id,
iid: this.iid,
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
index b32836dc87d..c645b1649d2 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -8,7 +8,7 @@ import {
GlLoadingIcon,
GlTooltipDirective,
} from '@gitlab/ui';
-import { IssuableType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE } from '~/issues/constants';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import { s__, __ } from '~/locale';
@@ -173,10 +173,7 @@ export default {
return Boolean(this.showHelp);
},
isTimeReportSupported() {
- return (
- [IssuableType.Issue, IssuableType.MergeRequest].includes(this.issuableType) &&
- this.issuableId
- );
+ return [TYPE_ISSUE, IssuableType.MergeRequest].includes(this.issuableType) && this.issuableId;
},
timeTrackingIconTitle() {
return this.showHelpState ? '' : HOW_TO_TRACK_TIME;
diff --git a/app/assets/javascripts/sidebar/constants.js b/app/assets/javascripts/sidebar/constants.js
index 976fe524209..b2d6a111a0e 100644
--- a/app/assets/javascripts/sidebar/constants.js
+++ b/app/assets/javascripts/sidebar/constants.js
@@ -3,7 +3,7 @@ import { s__, __, sprintf } from '~/locale';
import updateIssueLabelsMutation from '~/boards/graphql/issue_set_labels.mutation.graphql';
import userSearchQuery from '~/graphql_shared/queries/users_search.query.graphql';
import userSearchWithMRPermissionsQuery from '~/graphql_shared/queries/users_search_with_mr_permissions.graphql';
-import { IssuableType, WorkspaceType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE, WorkspaceType } from '~/issues/constants';
import updateAlertAssigneesMutation from '~/vue_shared/alert_details/graphql/mutations/alert_set_assignees.mutation.graphql';
import updateTestCaseLabelsMutation from './components/labels/labels_select_widget/graphql/update_test_case_labels.mutation.graphql';
import epicLabelsQuery from './components/labels/labels_select_widget/graphql/epic_labels.query.graphql';
@@ -64,7 +64,7 @@ export const defaultEpicSort = 'TITLE_ASC';
export const epicIidPattern = /^&(?<iid>\d+)$/;
export const assigneesQueries = {
- [IssuableType.Issue]: {
+ [TYPE_ISSUE]: {
query: getIssueAssignees,
subscription: issuableAssigneesSubscription,
mutation: updateIssueAssigneesMutation,
@@ -80,7 +80,7 @@ export const assigneesQueries = {
};
export const participantsQueries = {
- [IssuableType.Issue]: {
+ [TYPE_ISSUE]: {
query: issueParticipantsQuery,
},
[IssuableType.MergeRequest]: {
@@ -96,7 +96,7 @@ export const participantsQueries = {
};
export const userSearchQueries = {
- [IssuableType.Issue]: {
+ [TYPE_ISSUE]: {
query: userSearchQuery,
},
[IssuableType.MergeRequest]: {
@@ -105,7 +105,7 @@ export const userSearchQueries = {
};
export const confidentialityQueries = {
- [IssuableType.Issue]: {
+ [TYPE_ISSUE]: {
query: issueConfidentialQuery,
mutation: updateIssueConfidentialMutation,
},
@@ -116,7 +116,7 @@ export const confidentialityQueries = {
};
export const referenceQueries = {
- [IssuableType.Issue]: {
+ [TYPE_ISSUE]: {
query: issueReferenceQuery,
},
[IssuableType.MergeRequest]: {
@@ -137,7 +137,7 @@ export const workspaceLabelsQueries = {
};
export const issuableLabelsQueries = {
- [IssuableType.Issue]: {
+ [TYPE_ISSUE]: {
issuableQuery: issueLabelsQuery,
mutation: updateIssueLabelsMutation,
mutationName: 'updateIssue',
@@ -178,7 +178,7 @@ export const dateFields = {
};
export const subscribedQueries = {
- [IssuableType.Issue]: {
+ [TYPE_ISSUE]: {
query: issueSubscribedQuery,
mutation: updateIssueSubscriptionMutation,
},
@@ -198,7 +198,7 @@ export const Tracking = {
};
export const timeTrackingQueries = {
- [IssuableType.Issue]: {
+ [TYPE_ISSUE]: {
query: issueTimeTrackingQuery,
},
[IssuableType.MergeRequest]: {
@@ -207,7 +207,7 @@ export const timeTrackingQueries = {
};
export const dueDateQueries = {
- [IssuableType.Issue]: {
+ [TYPE_ISSUE]: {
query: issueDueDateQuery,
mutation: updateIssueDueDateMutation,
},
@@ -225,7 +225,7 @@ export const startDateQueries = {
};
export const timelogQueries = {
- [IssuableType.Issue]: {
+ [TYPE_ISSUE]: {
query: getIssueTimelogsQuery,
},
[IssuableType.MergeRequest]: {
@@ -236,7 +236,7 @@ export const timelogQueries = {
export const noAttributeId = null;
export const issuableMilestoneQueries = {
- [IssuableType.Issue]: {
+ [TYPE_ISSUE]: {
query: projectIssueMilestoneQuery,
mutation: projectIssueMilestoneMutation,
},
@@ -247,7 +247,7 @@ export const issuableMilestoneQueries = {
};
export const milestonesQueries = {
- [IssuableType.Issue]: {
+ [TYPE_ISSUE]: {
query: {
[WorkspaceType.group]: groupMilestonesQuery,
[WorkspaceType.project]: projectMilestonesQuery,
@@ -286,7 +286,7 @@ export const todoQueries = {
[IssuableType.Epic]: {
query: epicTodoQuery,
},
- [IssuableType.Issue]: {
+ [TYPE_ISSUE]: {
query: issueTodoQuery,
},
[IssuableType.MergeRequest]: {
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index cecd3da7ed2..fb024d818da 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -4,7 +4,7 @@ import { TYPENAME_ISSUE, TYPENAME_MERGE_REQUEST } from '~/graphql_shared/constan
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
-import { IssuableType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE } from '~/issues/constants';
import { gqlClient } from '~/issues/list/graphql';
import {
isInDesignPage,
@@ -80,7 +80,7 @@ function mountSidebarTodoWidget() {
issuableIid: iid,
issuableType:
isInIssuePage() || isInIncidentPage() || isInDesignPage()
- ? IssuableType.Issue
+ ? TYPE_ISSUE
: IssuableType.MergeRequest,
},
}),
@@ -124,7 +124,7 @@ function mountSidebarAssigneesDeprecated(mediator) {
signedIn: Object.prototype.hasOwnProperty.call(el.dataset, 'signedIn'),
issuableType:
isInIssuePage() || isInIncidentPage() || isInDesignPage()
- ? IssuableType.Issue
+ ? TYPE_ISSUE
: IssuableType.MergeRequest,
issuableId: id,
assigneeAvailabilityStatus,
@@ -142,7 +142,7 @@ function mountSidebarAssigneesWidget() {
const { id, iid, fullPath, editable } = getSidebarOptions();
const isIssuablePage = isInIssuePage() || isInIncidentPage() || isInDesignPage();
- const issuableType = isIssuablePage ? IssuableType.Issue : IssuableType.MergeRequest;
+ const issuableType = isIssuablePage ? TYPE_ISSUE : IssuableType.MergeRequest;
// eslint-disable-next-line no-new
new Vue({
el,
@@ -205,7 +205,7 @@ function mountSidebarReviewers(mediator) {
projectPath: fullPath,
field: el.dataset.field,
issuableType:
- isInIssuePage() || isInDesignPage() ? IssuableType.Issue : IssuableType.MergeRequest,
+ isInIssuePage() || isInDesignPage() ? TYPE_ISSUE : IssuableType.MergeRequest,
},
}),
});
@@ -276,7 +276,7 @@ function mountSidebarMilestoneWidget() {
workspacePath: projectPath,
iid: issueIid,
issuableType:
- isInIssuePage() || isInDesignPage() ? IssuableType.Issue : IssuableType.MergeRequest,
+ isInIssuePage() || isInDesignPage() ? TYPE_ISSUE : IssuableType.MergeRequest,
issuableAttribute: IssuableAttributeType.Milestone,
icon: 'clock',
},
@@ -313,7 +313,7 @@ export function mountMilestoneDropdown() {
attrWorkspacePath: fullPath,
canAdminMilestone,
inputName,
- issuableType: isInIssuePage() ? IssuableType.Issue : IssuableType.MergeRequest,
+ issuableType: isInIssuePage() ? TYPE_ISSUE : IssuableType.MergeRequest,
milestoneId,
milestoneTitle,
projectMilestonesPath,
@@ -357,7 +357,7 @@ export function mountSidebarLabelsWidget() {
variant: DropdownVariant.Sidebar,
issuableType:
isInIssuePage() || isInIncidentPage() || isInDesignPage()
- ? IssuableType.Issue
+ ? TYPE_ISSUE
: IssuableType.MergeRequest,
workspaceType: 'project',
attrWorkspacePath: el.dataset.projectPath,
@@ -397,7 +397,7 @@ function mountSidebarConfidentialityWidget() {
fullPath,
issuableType:
isInIssuePage() || isInIncidentPage() || isInDesignPage()
- ? IssuableType.Issue
+ ? TYPE_ISSUE
: IssuableType.MergeRequest,
},
}),
@@ -425,7 +425,7 @@ function mountSidebarDueDateWidget() {
props: {
iid: String(iid),
fullPath,
- issuableType: IssuableType.Issue,
+ issuableType: TYPE_ISSUE,
},
}),
});
@@ -453,7 +453,7 @@ function mountSidebarReferenceWidget() {
props: {
issuableType:
isInIssuePage() || isInIncidentPage() || isInDesignPage()
- ? IssuableType.Issue
+ ? TYPE_ISSUE
: IssuableType.MergeRequest,
},
}),
@@ -505,7 +505,7 @@ function mountSidebarParticipantsWidget() {
fullPath,
issuableType:
isInIssuePage() || isInIncidentPage() || isInDesignPage()
- ? IssuableType.Issue
+ ? TYPE_ISSUE
: IssuableType.MergeRequest,
},
}),
@@ -535,7 +535,7 @@ function mountSidebarSubscriptionsWidget() {
fullPath,
issuableType:
isInIssuePage() || isInIncidentPage() || isInDesignPage()
- ? IssuableType.Issue
+ ? TYPE_ISSUE
: IssuableType.MergeRequest,
},
}),
diff --git a/app/assets/javascripts/vue_shared/components/user_select/user_select.vue b/app/assets/javascripts/vue_shared/components/user_select/user_select.vue
index 3db48bf9cfb..edcfabe7da3 100644
--- a/app/assets/javascripts/vue_shared/components/user_select/user_select.vue
+++ b/app/assets/javascripts/vue_shared/components/user_select/user_select.vue
@@ -11,7 +11,7 @@ import {
} from '@gitlab/ui';
import { __ } from '~/locale';
import SidebarParticipant from '~/sidebar/components/assignees/sidebar_participant.vue';
-import { IssuableType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE } from '~/issues/constants';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { participantsQueries, userSearchQueries } from '~/sidebar/constants';
import { TYPENAME_MERGE_REQUEST } from '~/graphql_shared/constants';
@@ -67,7 +67,7 @@ export default {
issuableType: {
type: String,
required: false,
- default: IssuableType.Issue,
+ default: TYPE_ISSUE,
},
isEditing: {
type: Boolean,
diff --git a/app/assets/javascripts/vue_shared/constants.js b/app/assets/javascripts/vue_shared/constants.js
index c93dd95a886..fd151751372 100644
--- a/app/assets/javascripts/vue_shared/constants.js
+++ b/app/assets/javascripts/vue_shared/constants.js
@@ -1,5 +1,5 @@
import { __, n__, sprintf } from '~/locale';
-import { IssuableType, WorkspaceType } from '~/issues/constants';
+import { TYPE_ISSUE, WorkspaceType } from '~/issues/constants';
const INTERVALS = {
minute: 'minute',
@@ -88,9 +88,9 @@ export const confidentialityInfoText = (workspaceType, issuableType) =>
),
{
workspaceType: workspaceType === WorkspaceType.project ? __('project') : __('group'),
- issuableType: issuableType === IssuableType.Issue ? __('issue') : __('epic'),
+ issuableType: issuableType === TYPE_ISSUE ? __('issue') : __('epic'),
permissions:
- issuableType === IssuableType.Issue
+ issuableType === TYPE_ISSUE
? __('at least the Reporter role, the author, and assignees')
: __('at least the Reporter role'),
},
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index cad453fe1de..17440acddc3 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -67,6 +67,8 @@
- 2
- - auto_merge
- 3
+- - automation_execute_rule
+ - 1
- - background_migration
- 1
- - background_migration_ci_database
diff --git a/db/docs/automation_rules.yml b/db/docs/automation_rules.yml
new file mode 100644
index 00000000000..fcbbf247f9d
--- /dev/null
+++ b/db/docs/automation_rules.yml
@@ -0,0 +1,10 @@
+---
+table_name: automation_rules
+description: Stores automation rules and their trigger events
+classes:
+- Automation::Rule
+feature_categories:
+- no_code_automation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111021
+milestone: '15.9'
+gitlab_schema: gitlab_main
diff --git a/db/migrate/20230203011359_create_automation_rules.rb b/db/migrate/20230203011359_create_automation_rules.rb
new file mode 100644
index 00000000000..d247799bee8
--- /dev/null
+++ b/db/migrate/20230203011359_create_automation_rules.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class CreateAutomationRules < Gitlab::Database::Migration[2.1]
+ enable_lock_retries!
+
+ def up
+ create_table :automation_rules do |t|
+ t.references :namespace, null: false, index: false, foreign_key: { on_delete: :cascade }
+ t.boolean :issues_events, default: false, null: false
+ t.boolean :merge_requests_events, default: false, null: false
+ t.boolean :permanently_disabled, default: false, null: false
+ t.text :name, null: false, limit: 255
+ t.text :rule, null: false, limit: 2048
+ t.timestamps_with_timezone null: false
+
+ t.index 'namespace_id, LOWER(name)',
+ name: 'index_automation_rules_namespace_id_name',
+ unique: true
+
+ t.index [:namespace_id, :permanently_disabled],
+ name: 'index_automation_rules_namespace_id_permanently_disabled'
+ end
+ end
+
+ def down
+ drop_table :automation_rules
+ end
+end
diff --git a/db/post_migrate/20230131210921_prepare_index_for_vulnerability_reads_on_project_id_scanner_id_vulnerability_id.rb b/db/post_migrate/20230131210921_prepare_index_for_vulnerability_reads_on_project_id_scanner_id_vulnerability_id.rb
new file mode 100644
index 00000000000..0ac4e805f8a
--- /dev/null
+++ b/db/post_migrate/20230131210921_prepare_index_for_vulnerability_reads_on_project_id_scanner_id_vulnerability_id.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class PrepareIndexForVulnerabilityReadsOnProjectIdScannerIdVulnerabilityId < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'idx_vulnerability_reads_project_id_scanner_id_vulnerability_id'
+
+ # Index to be created synchronously in https://gitlab.com/gitlab-org/gitlab/-/issues/382625
+ def up
+ prepare_async_index :vulnerability_reads, [:project_id, :scanner_id, :vulnerability_id], name: INDEX_NAME
+ end
+
+ def down
+ unprepare_async_index :vulnerability_reads, [:project_id, :scanner_id, :vulnerability_id], name: INDEX_NAME
+ end
+end
diff --git a/db/schema_migrations/20230131210921 b/db/schema_migrations/20230131210921
new file mode 100644
index 00000000000..8947d4ea112
--- /dev/null
+++ b/db/schema_migrations/20230131210921
@@ -0,0 +1 @@
+3057b3de5a7ccfa065cb6c279c61a454abcbd9b0e0f3735ec5b9869c450ae3d1 \ No newline at end of file
diff --git a/db/schema_migrations/20230203011359 b/db/schema_migrations/20230203011359
new file mode 100644
index 00000000000..364395a3252
--- /dev/null
+++ b/db/schema_migrations/20230203011359
@@ -0,0 +1 @@
+51ce125f058811cd0f118429049389d9b67479628472830bce4c04cc81969a37 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 43b16388c1d..b0fd5ccb7d0 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -12135,6 +12135,29 @@ CREATE SEQUENCE authentication_events_id_seq
ALTER SEQUENCE authentication_events_id_seq OWNED BY authentication_events.id;
+CREATE TABLE automation_rules (
+ id bigint NOT NULL,
+ namespace_id bigint NOT NULL,
+ issues_events boolean DEFAULT false NOT NULL,
+ merge_requests_events boolean DEFAULT false NOT NULL,
+ permanently_disabled boolean DEFAULT false NOT NULL,
+ name text NOT NULL,
+ rule text NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ CONSTRAINT check_0be3e2c953 CHECK ((char_length(name) <= 255)),
+ CONSTRAINT check_ed5a4fcbd5 CHECK ((char_length(rule) <= 2048))
+);
+
+CREATE SEQUENCE automation_rules_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE automation_rules_id_seq OWNED BY automation_rules.id;
+
CREATE TABLE award_emoji (
id integer NOT NULL,
name character varying,
@@ -24180,6 +24203,8 @@ ALTER TABLE ONLY audit_events_streaming_headers ALTER COLUMN id SET DEFAULT next
ALTER TABLE ONLY authentication_events ALTER COLUMN id SET DEFAULT nextval('authentication_events_id_seq'::regclass);
+ALTER TABLE ONLY automation_rules ALTER COLUMN id SET DEFAULT nextval('automation_rules_id_seq'::regclass);
+
ALTER TABLE ONLY award_emoji ALTER COLUMN id SET DEFAULT nextval('award_emoji_id_seq'::regclass);
ALTER TABLE ONLY background_migration_jobs ALTER COLUMN id SET DEFAULT nextval('background_migration_jobs_id_seq'::regclass);
@@ -25903,6 +25928,9 @@ ALTER TABLE ONLY audit_events_streaming_headers
ALTER TABLE ONLY authentication_events
ADD CONSTRAINT authentication_events_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY automation_rules
+ ADD CONSTRAINT automation_rules_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY award_emoji
ADD CONSTRAINT award_emoji_pkey PRIMARY KEY (id);
@@ -29010,6 +29038,10 @@ CREATE INDEX index_authentication_events_on_provider ON authentication_events US
CREATE INDEX index_authentication_events_on_user_and_ip_address_and_result ON authentication_events USING btree (user_id, ip_address, result);
+CREATE UNIQUE INDEX index_automation_rules_namespace_id_name ON automation_rules USING btree (namespace_id, lower(name));
+
+CREATE INDEX index_automation_rules_namespace_id_permanently_disabled ON automation_rules USING btree (namespace_id, permanently_disabled);
+
CREATE INDEX index_award_emoji_on_awardable_type_and_awardable_id ON award_emoji USING btree (awardable_type, awardable_id);
CREATE UNIQUE INDEX index_aws_roles_on_role_external_id ON aws_roles USING btree (role_external_id);
@@ -34654,6 +34686,9 @@ ALTER TABLE ONLY approval_merge_request_rules
ALTER TABLE ONLY namespace_statistics
ADD CONSTRAINT fk_rails_0062050394 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY automation_rules
+ ADD CONSTRAINT fk_rails_025b519b8d FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY incident_management_oncall_participants
ADD CONSTRAINT fk_rails_032b12996a FOREIGN KEY (oncall_rotation_id) REFERENCES incident_management_oncall_rotations(id) ON DELETE CASCADE;
diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md
index cfb076449c8..7b01efa183b 100644
--- a/doc/administration/reference_architectures/index.md
+++ b/doc/administration/reference_architectures/index.md
@@ -186,11 +186,17 @@ See [Recommended cloud providers and services](index.md#recommended-cloud-provid
### Additional workloads
These reference architectures have been [designed and tested](index.md#validation-and-test-results) for standard GitLab
-setups with good headroom in mind to cover most scenarios. However, if any additional workloads are being added on the
-nodes, such as security software, you may still need to adjust the specs accordingly to compensate.
+setups with good headroom in mind to cover most scenarios.
-This also applies for some GitLab features where it's possible to run custom scripts, for example
-[server hooks](../server_hooks.md).
+However, additional workloads can multiply the impact of operations by triggering follow-up actions.
+You may need to adjust the suggested specifications to compensate if you use, for example:
+
+- Security software on the nodes.
+- Hundreds of concurrent CI jobs for [large repositories](../../ci/large_repositories/index.md).
+- Custom scripts that [run at high frequency](../logs/log_parsing.md#print-top-api-user-agents).
+- [Integrations](../../integration/index.md) in many large projects.
+- [Server hooks](../server_hooks.md).
+- [System hooks](../system_hooks.md).
As a general rule, you should have robust monitoring in place to measure the impact of any additional workloads to
inform any changes needed to be made.
diff --git a/doc/development/fe_guide/style/scss.md b/doc/development/fe_guide/style/scss.md
index b84f41311b6..aed7310e95d 100644
--- a/doc/development/fe_guide/style/scss.md
+++ b/doc/development/fe_guide/style/scss.md
@@ -212,13 +212,3 @@ catch any warnings.
If the Rake task is throwing warnings you don't understand, SCSS Lint's
documentation includes [a full list of their rules](https://stylelint.io/user-guide/rules/).
-
-### Fixing issues
-
-If you want to automate changing a large portion of the codebase to conform to
-the SCSS style guide, you can use [CSSComb](https://github.com/csscomb/csscomb.js). First install
-[Node](https://github.com/nodejs/node) and [npm](https://www.npmjs.com/), then run `npm install csscomb -g` to install
-CSSComb globally (system-wide). Run it in the GitLab directory with
-`csscomb app/assets/stylesheets` to automatically fix issues with CSS/SCSS.
-
-Note that this doesn't fix every problem, but it should fix a majority.
diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md
index 2ad3c28d0ae..9e0ff22eafa 100644
--- a/doc/user/group/roadmap/index.md
+++ b/doc/user/group/roadmap/index.md
@@ -73,6 +73,7 @@ You can also [visualize roadmaps inside of an epic](../epics/index.md#roadmap-in
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345158) in GitLab 14.8 [with a flag](../../../administration/feature_flags.md) named `roadmap_settings`. Enabled by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/350830) in GitLab 14.9. Feature flag `roadmap_settings`removed.
+> - Labels visible on roadmaps [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/385231) in GitLab 15.9.
When you enable the roadmap settings sidebar, you can use it to refine epics shown in the roadmap.
@@ -84,6 +85,7 @@ You can configure the following:
- Show all, open, or closed epics.
- Turn progress tracking for child issues on or off and select whether
to use issue weights or counts.
+- Turn labels on or off.
The progress tracking setting isn't saved in user preferences, but is saved or
shared using URL parameters.
diff --git a/lib/tasks/gitlab/artifacts/migrate.rake b/lib/tasks/gitlab/artifacts/migrate.rake
index 084e7c78906..47b356aa6e6 100644
--- a/lib/tasks/gitlab/artifacts/migrate.rake
+++ b/lib/tasks/gitlab/artifacts/migrate.rake
@@ -1,10 +1,10 @@
# frozen_string_literal: true
-require 'logger'
-require 'resolv-replace'
-
desc 'GitLab | Artifacts | Migrate files for artifacts to comply with new storage format'
namespace :gitlab do
+ require 'logger'
+ require 'resolv-replace'
+
namespace :artifacts do
task migrate: :environment do
logger = Logger.new($stdout)
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index 51e361de73c..c4dc7b938cc 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -462,6 +462,8 @@ namespace :gitlab do
.each { |c| classes[c.table_name] << c.name if classes.has_key?(c.table_name) }
sources.each do |source_name|
+ next if source_name.start_with?('_test_') # Ignore test tables
+
database = model_class.connection_db_config.name
file = dictionary_file_path(source_name, views, database)
key_name = "#{data_source_type(source_name, views)}_name"
diff --git a/qa/Gemfile b/qa/Gemfile
index b04653a657c..9e41b5ddeed 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -38,7 +38,7 @@ gem 'chemlab', '~> 0.10'
gem 'chemlab-library-www-gitlab-com', '~> 0.1', '>= 0.1.1'
# dependencies for jenkins client
-gem 'nokogiri', '~> 1.14', '>= 1.14.1'
+gem 'nokogiri', '~> 1.14', '>= 1.14.2'
gem 'deprecation_toolkit', '~> 2.0.3', require: false
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 9feb930d7c9..d544aa685a5 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -180,7 +180,7 @@ GEM
multi_json (1.15.0)
multi_xml (0.6.0)
netrc (0.11.0)
- nokogiri (1.14.1)
+ nokogiri (1.14.2)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
octokit (6.0.1)
@@ -320,7 +320,7 @@ DEPENDENCIES
gitlab-qa (~> 9)
influxdb-client (~> 2.9)
knapsack (~> 4.0)
- nokogiri (~> 1.14, >= 1.14.1)
+ nokogiri (~> 1.14, >= 1.14.2)
octokit (~> 6.0.1)
parallel (~> 1.22, >= 1.22.1)
parallel_tests (~> 4.2)
diff --git a/spec/frontend/issues/show/components/app_spec.js b/spec/frontend/issues/show/components/app_spec.js
index 863657b3547..7766bc62026 100644
--- a/spec/frontend/issues/show/components/app_spec.js
+++ b/spec/frontend/issues/show/components/app_spec.js
@@ -12,6 +12,7 @@ import {
STATUS_CLOSED,
STATUS_OPEN,
STATUS_REOPENED,
+ TYPE_ISSUE,
} from '~/issues/constants';
import IssuableApp from '~/issues/show/components/app.vue';
import DescriptionComponent from '~/issues/show/components/description.vue';
@@ -484,11 +485,11 @@ describe('Issuable output', () => {
});
it.each`
- issuableType | issuableStatus | statusIcon
- ${IssuableType.Issue} | ${STATUS_OPEN} | ${'issues'}
- ${IssuableType.Issue} | ${STATUS_CLOSED} | ${'issue-closed'}
- ${IssuableType.Epic} | ${STATUS_OPEN} | ${'epic'}
- ${IssuableType.Epic} | ${STATUS_CLOSED} | ${'epic-closed'}
+ issuableType | issuableStatus | statusIcon
+ ${TYPE_ISSUE} | ${STATUS_OPEN} | ${'issues'}
+ ${TYPE_ISSUE} | ${STATUS_CLOSED} | ${'issue-closed'}
+ ${IssuableType.Epic} | ${STATUS_OPEN} | ${'epic'}
+ ${IssuableType.Epic} | ${STATUS_CLOSED} | ${'epic-closed'}
`(
'shows with state icon "$statusIcon" for $issuableType when status is $issuableStatus',
async ({ issuableType, issuableStatus, statusIcon }) => {
diff --git a/spec/frontend/issues/show/components/locked_warning_spec.js b/spec/frontend/issues/show/components/locked_warning_spec.js
index 08f0338d41b..c9d510088bf 100644
--- a/spec/frontend/issues/show/components/locked_warning_spec.js
+++ b/spec/frontend/issues/show/components/locked_warning_spec.js
@@ -1,7 +1,7 @@
import { GlAlert, GlLink } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { sprintf } from '~/locale';
-import { IssuableType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE } from '~/issues/constants';
import LockedWarning, { i18n } from '~/issues/show/components/locked_warning.vue';
describe('LockedWarning component', () => {
@@ -21,35 +21,32 @@ describe('LockedWarning component', () => {
const findAlert = () => wrapper.findComponent(GlAlert);
const findLink = () => wrapper.findComponent(GlLink);
- describe.each([IssuableType.Issue, IssuableType.Epic])(
- 'with issuableType set to %s',
- (issuableType) => {
- let alert;
- let link;
- beforeEach(() => {
- createComponent({ issuableType });
- alert = findAlert();
- link = findLink();
- });
-
- afterEach(() => {
- alert = null;
- link = null;
- });
-
- it('displays a non-closable alert', () => {
- expect(alert.exists()).toBe(true);
- expect(alert.props('dismissible')).toBe(false);
- });
-
- it(`displays correct message`, async () => {
- expect(alert.text()).toMatchInterpolatedText(sprintf(i18n.alertMessage, { issuableType }));
- });
-
- it(`displays a link with correct text`, async () => {
- expect(link.exists()).toBe(true);
- expect(link.text()).toBe(`the ${issuableType}`);
- });
- },
- );
+ describe.each([TYPE_ISSUE, IssuableType.Epic])('with issuableType set to %s', (issuableType) => {
+ let alert;
+ let link;
+ beforeEach(() => {
+ createComponent({ issuableType });
+ alert = findAlert();
+ link = findLink();
+ });
+
+ afterEach(() => {
+ alert = null;
+ link = null;
+ });
+
+ it('displays a non-closable alert', () => {
+ expect(alert.exists()).toBe(true);
+ expect(alert.props('dismissible')).toBe(false);
+ });
+
+ it(`displays correct message`, async () => {
+ expect(alert.text()).toMatchInterpolatedText(sprintf(i18n.alertMessage, { issuableType }));
+ });
+
+ it(`displays a link with correct text`, async () => {
+ expect(link.exists()).toBe(true);
+ expect(link.text()).toBe(`the ${issuableType}`);
+ });
+ });
});
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_participant_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_participant_spec.js
index 71424aaead3..be0b14fa997 100644
--- a/spec/frontend/sidebar/components/assignees/sidebar_participant_spec.js
+++ b/spec/frontend/sidebar/components/assignees/sidebar_participant_spec.js
@@ -1,6 +1,6 @@
import { GlAvatarLabeled, GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { IssuableType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE } from '~/issues/constants';
import SidebarParticipant from '~/sidebar/components/assignees/sidebar_participant.vue';
const user = {
@@ -16,11 +16,7 @@ describe('Sidebar participant component', () => {
const findAvatar = () => wrapper.findComponent(GlAvatarLabeled);
const findIcon = () => wrapper.findComponent(GlIcon);
- const createComponent = ({
- status = null,
- issuableType = IssuableType.Issue,
- canMerge = false,
- } = {}) => {
+ const createComponent = ({ status = null, issuableType = TYPE_ISSUE, canMerge = false } = {}) => {
wrapper = shallowMount(SidebarParticipant, {
propsData: {
user: {
diff --git a/spec/frontend/sidebar/components/copy/sidebar_reference_widget_spec.js b/spec/frontend/sidebar/components/copy/sidebar_reference_widget_spec.js
index 40f14d581dc..c3de076d6aa 100644
--- a/spec/frontend/sidebar/components/copy/sidebar_reference_widget_spec.js
+++ b/spec/frontend/sidebar/components/copy/sidebar_reference_widget_spec.js
@@ -3,7 +3,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { IssuableType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE } from '~/issues/constants';
import SidebarReferenceWidget from '~/sidebar/components/copy/sidebar_reference_widget.vue';
import issueReferenceQuery from '~/sidebar/queries/issue_reference.query.graphql';
import mergeRequestReferenceQuery from '~/sidebar/queries/merge_request_reference.query.graphql';
@@ -19,7 +19,7 @@ describe('Sidebar Reference Widget', () => {
const findCopyableField = () => wrapper.findComponent(CopyableField);
const createComponent = ({
- issuableType = IssuableType.Issue,
+ issuableType = TYPE_ISSUE,
referenceQuery = issueReferenceQuery,
referenceQueryHandler = jest.fn().mockResolvedValue(issueReferenceResponse(mockReferenceValue)),
} = {}) => {
@@ -51,7 +51,7 @@ describe('Sidebar Reference Widget', () => {
});
describe.each([
- [IssuableType.Issue, issueReferenceQuery],
+ [TYPE_ISSUE, issueReferenceQuery],
[IssuableType.MergeRequest, mergeRequestReferenceQuery],
])('when issuableType is %s', (issuableType, referenceQuery) => {
it('sets CopyableField `value` prop to reference value', async () => {
diff --git a/spec/frontend/sidebar/components/labels/labels_select_widget/labels_select_root_spec.js b/spec/frontend/sidebar/components/labels/labels_select_widget/labels_select_root_spec.js
index b5656ef3a7b..cda562398c5 100644
--- a/spec/frontend/sidebar/components/labels/labels_select_widget/labels_select_root_spec.js
+++ b/spec/frontend/sidebar/components/labels/labels_select_widget/labels_select_root_spec.js
@@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert } from '~/flash';
-import { IssuableType } from '~/issues/constants';
+import { IssuableType, TYPE_ISSUE } from '~/issues/constants';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import DropdownContents from '~/sidebar/components/labels/labels_select_widget/dropdown_contents.vue';
import DropdownValue from '~/sidebar/components/labels/labels_select_widget/dropdown_value.vue';
@@ -35,7 +35,7 @@ const subscriptionHandler = jest.fn().mockResolvedValue(issuableLabelsSubscripti
const errorQueryHandler = jest.fn().mockRejectedValue('Houston, we have a problem');
const updateLabelsMutation = {
- [IssuableType.Issue]: updateIssueLabelsMutation,
+ [TYPE_ISSUE]: updateIssueLabelsMutation,
[IssuableType.MergeRequest]: updateMergeRequestLabelsMutation,
[IssuableType.Epic]: updateEpicLabelsMutation,
[IssuableType.TestCase]: updateTestCaseLabelsMutation,
@@ -52,7 +52,7 @@ describe('LabelsSelectRoot', () => {
const createComponent = ({
config = mockConfig,
slots = {},
- issuableType = IssuableType.Issue,
+ issuableType = TYPE_ISSUE,
queryHandler = successfulQueryHandler,
mutationHandler = successfulMutationHandler,
} = {}) => {
@@ -213,7 +213,7 @@ describe('LabelsSelectRoot', () => {
describe.each`
issuableType
- ${IssuableType.Issue}
+ ${TYPE_ISSUE}
${IssuableType.MergeRequest}
${IssuableType.Epic}
${IssuableType.TestCase}
diff --git a/spec/frontend/sidebar/components/milestone/milestone_dropdown_spec.js b/spec/frontend/sidebar/components/milestone/milestone_dropdown_spec.js
index 843ac1da4bb..b492753867b 100644
--- a/spec/frontend/sidebar/components/milestone/milestone_dropdown_spec.js
+++ b/spec/frontend/sidebar/components/milestone/milestone_dropdown_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { IssuableType, WorkspaceType } from '~/issues/constants';
+import { TYPE_ISSUE, WorkspaceType } from '~/issues/constants';
import { __ } from '~/locale';
import MilestoneDropdown from '~/sidebar/components/milestone/milestone_dropdown.vue';
import SidebarDropdown from '~/sidebar/components/sidebar_dropdown.vue';
@@ -11,7 +11,7 @@ describe('MilestoneDropdown component', () => {
const propsData = {
attrWorkspacePath: 'full/path',
- issuableType: IssuableType.Issue,
+ issuableType: TYPE_ISSUE,
workspaceType: WorkspaceType.project,
};
diff --git a/spec/frontend/sidebar/components/sidebar_dropdown_spec.js b/spec/frontend/sidebar/components/sidebar_dropdown_spec.js
index 83bc8cf7002..9f3d689edee 100644
--- a/spec/frontend/sidebar/components/sidebar_dropdown_spec.js
+++ b/spec/frontend/sidebar/components/sidebar_dropdown_spec.js
@@ -11,7 +11,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert } from '~/flash';
-import { IssuableType } from '~/issues/constants';
+import { TYPE_ISSUE } from '~/issues/constants';
import SidebarDropdown from '~/sidebar/components/sidebar_dropdown.vue';
import { IssuableAttributeType } from '~/sidebar/constants';
import projectIssueMilestoneQuery from '~/sidebar/queries/project_issue_milestone.query.graphql';
@@ -66,7 +66,7 @@ describe('SidebarDropdown component', () => {
propsData: {
attrWorkspacePath: mockIssue.projectPath,
currentAttribute: {},
- issuableType: IssuableType.Issue,
+ issuableType: TYPE_ISSUE,
issuableAttribute: IssuableAttributeType.Milestone,
},
attachTo: document.body,
@@ -83,7 +83,7 @@ describe('SidebarDropdown component', () => {
propsData: {
attrWorkspacePath: mockIssue.projectPath,
currentAttribute: {},
- issuableType: IssuableType.Issue,
+ issuableType: TYPE_ISSUE,
issuableAttribute: IssuableAttributeType.Milestone,
...props,
},
diff --git a/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
index cf5e220a705..060a2873e04 100644
--- a/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
+++ b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
@@ -9,7 +9,7 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createAlert } from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { IssuableType } from '~/issues/constants';
+import { TYPE_ISSUE } from '~/issues/constants';
import { timeFor } from '~/lib/utils/datetime_utility';
import SidebarDropdown from '~/sidebar/components/sidebar_dropdown.vue';
import SidebarDropdownWidget from '~/sidebar/components/sidebar_dropdown_widget.vue';
@@ -105,7 +105,7 @@ describe('SidebarDropdownWidget', () => {
workspacePath: mockIssue.projectPath,
attrWorkspacePath: mockIssue.projectPath,
iid: mockIssue.iid,
- issuableType: IssuableType.Issue,
+ issuableType: TYPE_ISSUE,
issuableAttribute: IssuableAttributeType.Milestone,
},
attachTo: document.body,
@@ -126,7 +126,7 @@ describe('SidebarDropdownWidget', () => {
workspacePath: '',
attrWorkspacePath: '',
iid: '',
- issuableType: IssuableType.Issue,
+ issuableType: TYPE_ISSUE,
issuableAttribute: IssuableAttributeType.Milestone,
},
mocks: {
diff --git a/spec/frontend/vue_shared/components/confidentiality_badge_spec.js b/spec/frontend/vue_shared/components/confidentiality_badge_spec.js
index e1860d3399b..127869e99b9 100644
--- a/spec/frontend/vue_shared/components/confidentiality_badge_spec.js
+++ b/spec/frontend/vue_shared/components/confidentiality_badge_spec.js
@@ -1,13 +1,13 @@
import { GlBadge } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { WorkspaceType, IssuableType } from '~/issues/constants';
+import { WorkspaceType, IssuableType, TYPE_ISSUE } from '~/issues/constants';
import ConfidentialityBadge from '~/vue_shared/components/confidentiality_badge.vue';
const createComponent = ({
workspaceType = WorkspaceType.project,
- issuableType = IssuableType.Issue,
+ issuableType = TYPE_ISSUE,
} = {}) =>
shallowMount(ConfidentialityBadge, {
propsData: {
@@ -28,9 +28,9 @@ describe('ConfidentialityBadge', () => {
});
it.each`
- workspaceType | issuableType | expectedTooltip
- ${WorkspaceType.project} | ${IssuableType.Issue} | ${'Only project members with at least the Reporter role, the author, and assignees can view or be notified about this issue.'}
- ${WorkspaceType.group} | ${IssuableType.Epic} | ${'Only group members with at least the Reporter role can view or be notified about this epic.'}
+ workspaceType | issuableType | expectedTooltip
+ ${WorkspaceType.project} | ${TYPE_ISSUE} | ${'Only project members with at least the Reporter role, the author, and assignees can view or be notified about this issue.'}
+ ${WorkspaceType.group} | ${IssuableType.Epic} | ${'Only group members with at least the Reporter role can view or be notified about this epic.'}
`(
'should render gl-badge with correct tooltip when workspaceType is $workspaceType and issuableType is $issuableType',
({ workspaceType, issuableType, expectedTooltip }) => {
diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb
index 748f062948f..933eba40719 100644
--- a/spec/tasks/gitlab/db_rake_spec.rb
+++ b/spec/tasks/gitlab/db_rake_spec.rb
@@ -360,11 +360,12 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout, feature_categor
let(:base_models) { { 'fake_db' => model }.with_indifferent_access }
- let(:tables) { %w[table1] }
+ let(:tables) { %w[table1 _test_dictionary_table_name] }
let(:views) { %w[view1] }
let(:table_file_path) { 'db/docs/table1.yml' }
let(:view_file_path) { 'db/docs/views/view1.yml' }
+ let(:test_table_path) { 'db/docs/_test_dictionary_table_name.yml' }
before do
allow(Gitlab::Database).to receive(:db_config_for_connection).and_return(db_config)
@@ -386,6 +387,12 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout, feature_categor
expect(File).to exist(File.join(table_file_path))
expect(File).to exist(File.join(view_file_path))
end
+
+ it 'do not generate the dictionary files for test tables' do
+ run_rake_task('gitlab:db:dictionary:generate')
+
+ expect(File).not_to exist(File.join(test_table_path))
+ end
end
context 'when the dictionary files already exist' do