Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-04-30 18:09:46 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-04-30 18:09:46 +0300
commit7f305b576b51c3503970ef224cf4b31e247a322d (patch)
tree9a3b0ddfb8640fd1a66307a38fe6ba264e5d99dd
parent04edf6545802ed0515e221038b63fc96ad3e6d54 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock10
-rw-r--r--app/assets/javascripts/boards/components/board.js3
-rw-r--r--app/assets/javascripts/boards/components/board_column.vue4
-rw-r--r--app/assets/javascripts/boards/components/board_form.vue6
-rw-r--r--app/assets/javascripts/boards/components/board_sidebar.js3
-rw-r--r--app/assets/javascripts/boards/components/boards_selector.vue6
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.vue4
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js1
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue6
-rw-r--r--app/assets/javascripts/jira_import/components/jira_import_app.vue60
-rw-r--r--app/assets/javascripts/jira_import/components/jira_import_form.vue23
-rw-r--r--app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql2
-rw-r--r--app/assets/javascripts/labels_select.js14
-rw-r--r--app/assets/javascripts/monitoring/components/alert_widget.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel.vue2
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/index/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/show/index.js2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_name_component.vue4
-rw-r--r--app/assets/javascripts/releases/components/evidence_block.vue4
-rw-r--r--app/assets/javascripts/releases/components/release_block_header.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_collapsible_extension.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue15
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/state.js1
-rw-r--r--app/assets/stylesheets/application.scss8
-rw-r--r--app/assets/stylesheets/framework/common.scss43
-rw-r--r--app/assets/stylesheets/utilities.scss19
-rw-r--r--app/views/ci/status/_dropdown_graph_badge.html.haml4
-rw-r--r--app/views/devise/registrations/new.html.haml2
-rw-r--r--app/views/projects/blob/_template_selectors.html.haml2
-rw-r--r--app/views/projects/graphs/show.html.haml2
-rw-r--r--app/views/shared/boards/components/_board.html.haml3
-rw-r--r--app/views/shared/boards/components/sidebar/_labels.html.haml3
-rw-r--r--app/views/shared/issuable/form/_branch_chooser.html.haml2
-rw-r--r--app/workers/project_export_worker.rb4
-rw-r--r--changelogs/unreleased/213238-fix-ide-discard-empty-file.yml5
-rw-r--r--changelogs/unreleased/215164-show-correct-import-label-and-import-count-on-jira-import-form.yml5
-rw-r--r--changelogs/unreleased/215569-jira-import-fix-default-author.yml5
-rw-r--r--danger/utility_css/Dangerfile51
-rw-r--r--doc/administration/external_pipeline_validation.md2
-rw-r--r--doc/administration/high_availability/gitlab.md4
-rw-r--r--doc/administration/lfs/index.md2
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md134
-rw-r--r--doc/api/releases/index.md2
-rw-r--r--doc/api/repository_files.md12
-rw-r--r--doc/api/services.md26
-rw-r--r--doc/api/settings.md2
-rw-r--r--doc/development/go_guide/index.md10
-rw-r--r--doc/development/packages.md2
-rw-r--r--doc/development/testing_guide/frontend_testing.md2
-rw-r--r--doc/development/testing_guide/review_apps.md25
-rw-r--r--doc/integration/jira_development_panel.md2
-rw-r--r--doc/topics/git/lfs/index.md4
-rw-r--r--doc/user/admin_area/settings/index.md2
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md2
-rw-r--r--doc/user/project/clusters/serverless/aws.md2
-rw-r--r--doc/user/project/integrations/prometheus.md16
-rw-r--r--lib/gitlab/jira_import/base_importer.rb5
-rw-r--r--lib/gitlab/jira_import/issue_serializer.rb7
-rw-r--r--lib/gitlab/jira_import/issues_importer.rb2
-rw-r--r--lib/gitlab_danger.rb1
-rw-r--r--locale/gitlab.pot25
-rw-r--r--package.json2
-rw-r--r--spec/frontend/ide/components/commit_sidebar/editor_header_spec.js50
-rw-r--r--spec/frontend/jira_import/components/jira_import_app_spec.js101
-rw-r--r--spec/frontend/jira_import/components/jira_import_form_spec.js31
-rw-r--r--spec/frontend/jira_import/components/jira_import_progress_spec.js10
-rw-r--r--spec/frontend/jira_import/components/jira_import_setup_spec.js10
-rw-r--r--spec/frontend/labels_select_spec.js15
-rw-r--r--spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js1
-rw-r--r--spec/initializers/action_mailer_hooks_spec.rb4
-rw-r--r--spec/lib/gitlab/jira_import/issue_serializer_spec.rb13
-rw-r--r--spec/lib/gitlab/jira_import/issues_importer_spec.rb33
-rw-r--r--spec/lib/gitlab_danger_spec.rb2
-rw-r--r--spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb4
-rw-r--r--spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb3
-rw-r--r--spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb53
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_allow_failure_test_on_failure.yml47
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_fails.yml39
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test.yml39
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test_when_always.yml43
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds.yml62
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_always.yml63
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_allow_failure.yml40
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_always.yml35
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_on_failure.yml35
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_succeeds_test_on_failure.yml35
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure.yml63
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_always.yml64
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_allow_failure_true.yml43
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml66
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml58
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_always.yml27
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml48
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_other_test_succeeds.yml42
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_failure.yml66
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_success.yml40
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_build_allow_failure_test_on_failure.yml53
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_build_fails.yml38
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_build_fails_test_allow_failure.yml39
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml65
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml54
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml44
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_failure.yml52
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_success.yml52
-rw-r--r--spec/workers/project_export_worker_spec.rb22
-rw-r--r--yarn.lock66
115 files changed, 2078 insertions, 367 deletions
diff --git a/Gemfile b/Gemfile
index 941155dc22a..6bd15a9a190 100644
--- a/Gemfile
+++ b/Gemfile
@@ -355,7 +355,7 @@ group :development, :test do
gem 'database_cleaner', '~> 1.7.0'
gem 'factory_bot_rails', '~> 5.1.0'
- gem 'rspec-rails', '~> 4.0.0.beta4'
+ gem 'rspec-rails', '~> 4.0.0'
# Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826)
gem 'minitest', '~> 5.11.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 4dca441e53c..e796144f62a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -614,7 +614,7 @@ GEM
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
- loofah (2.4.0)
+ loofah (2.5.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
lru_redux (1.1.0)
@@ -906,7 +906,7 @@ GEM
rspec-mocks (~> 3.9.0)
rspec-core (3.9.1)
rspec-support (~> 3.9.1)
- rspec-expectations (3.9.0)
+ rspec-expectations (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-mocks (3.9.1)
@@ -918,7 +918,7 @@ GEM
proc_to_ast
rspec (>= 2.13, < 4)
unparser
- rspec-rails (4.0.0.beta4)
+ rspec-rails (4.0.0)
actionpack (>= 4.2)
activesupport (>= 4.2)
railties (>= 4.2)
@@ -1078,7 +1078,7 @@ GEM
truncato (0.7.11)
htmlentities (~> 4.3.1)
nokogiri (>= 1.7.0, <= 2.0)
- tzinfo (1.2.6)
+ tzinfo (1.2.7)
thread_safe (~> 0.1)
u2f (0.2.1)
uber (0.1.0)
@@ -1357,7 +1357,7 @@ DEPENDENCIES
rouge (~> 3.18.0)
rqrcode-rails3 (~> 0.1.7)
rspec-parameterized
- rspec-rails (~> 4.0.0.beta4)
+ rspec-rails (~> 4.0.0)
rspec-retry (~> 0.6.1)
rspec_junit_formatter
rspec_profiling (~> 0.0.5)
diff --git a/app/assets/javascripts/boards/components/board.js b/app/assets/javascripts/boards/components/board.js
index ac02c229a07..517a13ceb27 100644
--- a/app/assets/javascripts/boards/components/board.js
+++ b/app/assets/javascripts/boards/components/board.js
@@ -113,9 +113,6 @@ export default Vue.extend({
// eslint-disable-next-line @gitlab/require-i18n-strings
return `boards.${this.boardId}.${this.list.type}.${this.list.id}`;
},
- helpLink() {
- return boardsStore.scopedLabels.helpLink;
- },
},
watch: {
filter: {
diff --git a/app/assets/javascripts/boards/components/board_column.vue b/app/assets/javascripts/boards/components/board_column.vue
index faecd77d598..fb854616a04 100644
--- a/app/assets/javascripts/boards/components/board_column.vue
+++ b/app/assets/javascripts/boards/components/board_column.vue
@@ -113,9 +113,6 @@ export default {
// eslint-disable-next-line @gitlab/require-i18n-strings
return `boards.${this.boardId}.${this.list.type}.${this.list.id}`;
},
- helpLink() {
- return boardsStore.scopedLabels.helpLink;
- },
},
watch: {
filter: {
@@ -286,7 +283,6 @@ export default {
:background-color="list.label.color"
:description="list.label.description"
:scoped="showScopedLabels(list.label)"
- :scoped-labels-documentation-link="helpLink"
:size="!list.isExpanded ? 'sm' : ''"
:title="list.label.title"
tooltip-placement="bottom"
diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index c0df8b72095..ec715759406 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -58,11 +58,6 @@ export default {
required: false,
default: false,
},
- scopedLabelsDocumentationLink: {
- type: String,
- required: false,
- default: '#',
- },
},
data() {
return {
@@ -208,7 +203,6 @@ export default {
:can-admin-board="canAdminBoard"
:milestone-path="milestonePath"
:labels-path="labelsPath"
- :scoped-labels-documentation-link="scopedLabelsDocumentationLink"
:enable-scoped-labels="enableScopedLabels"
:project-id="projectId"
:group-id="groupId"
diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js
index 66a5e134205..0433b612d0b 100644
--- a/app/assets/javascripts/boards/components/board_sidebar.js
+++ b/app/assets/javascripts/boards/components/board_sidebar.js
@@ -70,9 +70,6 @@ export default Vue.extend({
selectedLabels() {
return this.hasLabels ? this.issue.labels.map(l => l.title).join(',') : '';
},
- helpLink() {
- return boardsStore.scopedLabels.helpLink;
- },
},
watch: {
detail: {
diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue
index f2c976be7ae..80db9930259 100644
--- a/app/assets/javascripts/boards/components/boards_selector.vue
+++ b/app/assets/javascripts/boards/components/boards_selector.vue
@@ -86,11 +86,6 @@ export default {
required: false,
default: false,
},
- scopedLabelsDocumentationLink: {
- type: String,
- required: false,
- default: '#',
- },
},
data() {
return {
@@ -348,7 +343,6 @@ export default {
:scoped-issue-board-feature-enabled="scopedIssueBoardFeatureEnabled"
:weights="weights"
:enable-scoped-labels="enabledScopedLabels"
- :scoped-labels-documentation-link="scopedLabelsDocumentationLink"
/>
</span>
</div>
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue
index daaa12c096b..a589fb325b2 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner.vue
@@ -102,9 +102,6 @@ export default {
orderedLabels() {
return sortBy(this.issue.labels.filter(this.isNonListLabel), 'title');
},
- helpLink() {
- return boardsStore.scopedLabels.helpLink;
- },
},
methods: {
isIndexLessThanlimit(index) {
@@ -181,7 +178,6 @@ export default {
:description="label.description"
size="sm"
:scoped="showScopedLabel(label)"
- :scoped-labels-documentation-link="helpLink"
@click="filterByLabel(label)"
/>
</template>
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index b8ae6396475..fdbd7e89bfb 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -28,7 +28,6 @@ const boardsStore = {
limitToHours: false,
},
scopedLabels: {
- helpLink: '',
enabled: false,
},
filter: {
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
index e618fb3daae..24499fb9f6d 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
@@ -24,8 +24,8 @@ export default {
discardModalTitle() {
return sprintf(__('Discard changes to %{path}?'), { path: this.activeFile.path });
},
- isStaged() {
- return !this.activeFile.changed && this.activeFile.staged;
+ canDiscard() {
+ return this.activeFile.changed || this.activeFile.staged;
},
},
methods: {
@@ -53,7 +53,7 @@ export default {
<changed-file-icon :file="activeFile" :is-centered="false" />
<div class="ml-auto">
<button
- v-if="!isStaged"
+ v-if="canDiscard"
ref="discardButton"
type="button"
class="btn btn-remove btn-inverted append-right-8"
diff --git a/app/assets/javascripts/jira_import/components/jira_import_app.vue b/app/assets/javascripts/jira_import/components/jira_import_app.vue
index b2c6ec47a26..b6c50b89382 100644
--- a/app/assets/javascripts/jira_import/components/jira_import_app.vue
+++ b/app/assets/javascripts/jira_import/components/jira_import_app.vue
@@ -1,5 +1,6 @@
<script>
-import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
+import { GlAlert, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
+import last from 'lodash/last';
import { __ } from '~/locale';
import getJiraImportDetailsQuery from '../queries/get_jira_import_details.query.graphql';
import initiateJiraImportMutation from '../queries/initiate_jira_import.mutation.graphql';
@@ -13,6 +14,7 @@ export default {
components: {
GlAlert,
GlLoadingIcon,
+ GlSprintf,
JiraImportForm,
JiraImportProgress,
JiraImportSetup,
@@ -51,6 +53,7 @@ export default {
return {
errorMessage: '',
showAlert: false,
+ selectedProject: undefined,
};
},
apollo: {
@@ -63,7 +66,7 @@ export default {
},
update: ({ project }) => ({
status: project.jiraImportStatus,
- import: project.jiraImports.nodes[0],
+ imports: project.jiraImports.nodes,
}),
skip() {
return !this.isJiraConfigured;
@@ -77,6 +80,24 @@ export default {
jiraProjectsOptions() {
return this.jiraProjects.map(([text, value]) => ({ text, value }));
},
+ mostRecentImport() {
+ // The backend returns JiraImports ordered by created_at asc in app/models/project.rb
+ return last(this.jiraImportDetails?.imports);
+ },
+ numberOfPreviousImportsForProject() {
+ return this.jiraImportDetails?.imports?.reduce?.(
+ (acc, jiraProject) => (jiraProject.jiraProjectKey === this.selectedProject ? acc + 1 : acc),
+ 0,
+ );
+ },
+ importLabel() {
+ return this.selectedProject
+ ? `jira-import::${this.selectedProject}-${this.numberOfPreviousImportsForProject + 1}`
+ : 'jira-import::KEY-1';
+ },
+ hasPreviousImports() {
+ return this.numberOfPreviousImportsForProject > 0;
+ },
},
methods: {
dismissAlert() {
@@ -97,6 +118,13 @@ export default {
return;
}
+ const cacheData = store.readQuery({
+ query: getJiraImportDetailsQuery,
+ variables: {
+ fullPath: this.projectPath,
+ },
+ });
+
store.writeQuery({
query: getJiraImportDetailsQuery,
variables: {
@@ -106,7 +134,10 @@ export default {
project: {
jiraImportStatus: IMPORT_STATE.SCHEDULED,
jiraImports: {
- nodes: [data.jiraImportStart.jiraImport],
+ nodes: [
+ ...cacheData.project.jiraImports.nodes,
+ data.jiraImportStart.jiraImport,
+ ],
__typename: 'JiraImportConnection',
},
// eslint-disable-next-line @gitlab/require-i18n-strings
@@ -119,6 +150,8 @@ export default {
.then(({ data }) => {
if (data.jiraImportStart.errors.length) {
this.setAlertMessage(data.jiraImportStart.errors.join('. '));
+ } else {
+ this.selectedProject = undefined;
}
})
.catch(() => this.setAlertMessage(__('There was an error importing the Jira project.')));
@@ -136,6 +169,19 @@ export default {
<gl-alert v-if="showAlert" variant="danger" @dismiss="dismissAlert">
{{ errorMessage }}
</gl-alert>
+ <gl-alert v-if="hasPreviousImports" variant="warning" :dismissible="false">
+ <gl-sprintf
+ :message="
+ __(
+ 'You have imported from this project %{numberOfPreviousImportsForProject} times before. Each new import will create duplicate issues.',
+ )
+ "
+ >
+ <template #numberOfPreviousImportsForProject>{{
+ numberOfPreviousImportsForProject
+ }}</template>
+ </gl-sprintf>
+ </gl-alert>
<jira-import-setup
v-if="!isJiraConfigured"
@@ -146,13 +192,15 @@ export default {
<jira-import-progress
v-else-if="isImportInProgress"
:illustration="inProgressIllustration"
- :import-initiator="jiraImportDetails.import.scheduledBy.name"
- :import-project="jiraImportDetails.import.jiraProjectKey"
- :import-time="jiraImportDetails.import.scheduledAt"
+ :import-initiator="mostRecentImport.scheduledBy.name"
+ :import-project="mostRecentImport.jiraProjectKey"
+ :import-time="mostRecentImport.scheduledAt"
:issues-path="issuesPath"
/>
<jira-import-form
v-else
+ v-model="selectedProject"
+ :import-label="importLabel"
:issues-path="issuesPath"
:jira-projects="jiraProjectsOptions"
@initiateJiraImport="initiateJiraImport"
diff --git a/app/assets/javascripts/jira_import/components/jira_import_form.vue b/app/assets/javascripts/jira_import/components/jira_import_form.vue
index 0146f564260..c2fe7b29c28 100644
--- a/app/assets/javascripts/jira_import/components/jira_import_form.vue
+++ b/app/assets/javascripts/jira_import/components/jira_import_form.vue
@@ -13,6 +13,10 @@ export default {
currentUserAvatarUrl: gon.current_user_avatar_url,
currentUsername: gon.current_username,
props: {
+ importLabel: {
+ type: String,
+ required: true,
+ },
issuesPath: {
type: String,
required: true,
@@ -21,21 +25,25 @@ export default {
type: Array,
required: true,
},
+ value: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
},
data() {
return {
- selectedOption: null,
selectState: null,
};
},
methods: {
initiateJiraImport(event) {
event.preventDefault();
- if (!this.selectedOption) {
- this.showValidationError();
- } else {
+ if (this.value) {
this.hideValidationError();
- this.$emit('initiateJiraImport', this.selectedOption);
+ this.$emit('initiateJiraImport', this.value);
+ } else {
+ this.showValidationError();
}
},
hideValidationError() {
@@ -62,10 +70,11 @@ export default {
>
<gl-form-select
id="jira-project-select"
- v-model="selectedOption"
class="mb-2"
:options="jiraProjects"
:state="selectState"
+ :value="value"
+ @change="$emit('input', $event)"
/>
</gl-form-group>
@@ -79,7 +88,7 @@ export default {
id="jira-project-label"
class="mb-2"
background-color="#428BCA"
- title="jira-import::KEY-1"
+ :title="importLabel"
scoped
/>
</gl-form-group>
diff --git a/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql b/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql
index 0eaaad580fc..aa8d03c7f17 100644
--- a/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql
+++ b/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql
@@ -3,7 +3,7 @@
query($fullPath: ID!) {
project(fullPath: $fullPath) {
jiraImportStatus
- jiraImports(last: 1) {
+ jiraImports {
nodes {
...JiraImport
}
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index fb7e06cad15..9edce353a66 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -55,7 +55,6 @@ export default class LabelsSelect {
})
.get();
const scopedLabels = $dropdown.data('scopedLabels');
- const scopedLabelsDocumentationLink = $dropdown.data('scopedLabelsDocumentationLink');
const { handleClick } = options;
$sidebarLabelTooltip.tooltip();
@@ -104,7 +103,6 @@ export default class LabelsSelect {
labels: sortBy(data.labels, 'title'),
issueUpdateURL,
enableScopedLabels: scopedLabels,
- scopedLabelsDocumentationLink,
});
labelCount = data.labels.length;
@@ -497,14 +495,6 @@ export default class LabelsSelect {
return escapeStr(label.text_color === '#FFFFFF' ? label.color : label.text_color);
};
- const infoIconTemplate = template(
- [
- '<a href="<%= scopedLabelsDocumentationLink %>" class="gl-link gl-label-icon" target="_blank" rel="noopener">',
- '<i class="fa fa-question-circle"></i>',
- '</a>',
- ].join(''),
- );
-
const scopedLabelTemplate = template(
[
'<span class="gl-label gl-label-scoped" style="color: <%= escapeStr(label.color) %>;">',
@@ -516,7 +506,6 @@ export default class LabelsSelect {
'<%- label.title.slice(label.title.lastIndexOf("::") + 2) %>',
'</span>',
'</a>',
- '<%= infoIconTemplate({ label, scopedLabelsDocumentationLink, escapeStr }) %>',
'</span>',
].join(''),
);
@@ -538,7 +527,7 @@ export default class LabelsSelect {
'<% labels.forEach(function(label){ %>',
'<% if (isScopedLabel(label) && enableScopedLabels) { %>',
'<span class="d-inline-block position-relative scoped-label-wrapper">',
- '<%= scopedLabelTemplate({ label, issueUpdateURL, isScopedLabel, enableScopedLabels, rightLabelTextColor, infoIconTemplate, scopedLabelsDocumentationLink, tooltipTitleTemplate, escapeStr, linkAttrs: \'data-html="true"\' }) %>',
+ '<%= scopedLabelTemplate({ label, issueUpdateURL, isScopedLabel, enableScopedLabels, rightLabelTextColor, tooltipTitleTemplate, escapeStr, linkAttrs: \'data-html="true"\' }) %>',
'</span>',
'<% } else { %>',
'<%= labelTemplate({ label, issueUpdateURL, isScopedLabel, enableScopedLabels, tooltipTitleTemplate, escapeStr, linkAttrs: "" }) %>',
@@ -551,7 +540,6 @@ export default class LabelsSelect {
...tplData,
labelTemplate,
rightLabelTextColor,
- infoIconTemplate,
scopedLabelTemplate,
tooltipTitleTemplate,
isScopedLabel,
diff --git a/app/assets/javascripts/monitoring/components/alert_widget.vue b/app/assets/javascripts/monitoring/components/alert_widget.vue
index 2c6223c5dd7..86a793c854e 100644
--- a/app/assets/javascripts/monitoring/components/alert_widget.vue
+++ b/app/assets/javascripts/monitoring/components/alert_widget.vue
@@ -240,7 +240,7 @@ export default {
class="d-flex-center text-truncate"
>
<gl-icon name="warning" :size="16" class="flex-shrink-0" />
- <span class="text-truncate gl-pl-1">
+ <span class="text-truncate gl-pl-1-deprecated-no-really-do-not-use-me">
<gl-sprintf
:message="
hasMultipleAlerts ? multipleAlertsSummary.message : singleAlertSummary.message
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel.vue b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
index 29d6a2a46c5..a269ef83799 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
@@ -268,7 +268,7 @@ export default {
<slot name="topLeft"></slot>
<h5
ref="graphTitle"
- class="prometheus-graph-title gl-font-size-large font-weight-bold text-truncate append-right-8"
+ class="prometheus-graph-title gl-font-lg font-weight-bold text-truncate append-right-8"
>
{{ title }}
</h5>
diff --git a/app/assets/javascripts/pages/projects/pipelines/index/index.js b/app/assets/javascripts/pages/projects/pipelines/index/index.js
index 4b4a274794d..894185fa8c2 100644
--- a/app/assets/javascripts/pages/projects/pipelines/index/index.js
+++ b/app/assets/javascripts/pages/projects/pipelines/index/index.js
@@ -10,6 +10,7 @@ import { __ } from '~/locale';
import PipelinesStore from '../../../../pipelines/stores/pipelines_store';
import pipelinesComponent from '../../../../pipelines/components/pipelines.vue';
import Translate from '../../../../vue_shared/translate';
+import initVueAlerts from '../../../../vue_alerts';
Vue.use(Translate);
Vue.use(GlToast);
@@ -55,3 +56,5 @@ document.addEventListener(
},
}),
);
+
+document.addEventListener('DOMContentLoaded', initVueAlerts);
diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js
index 6ae10c98058..f74a7b41895 100644
--- a/app/assets/javascripts/pages/projects/show/index.js
+++ b/app/assets/javascripts/pages/projects/show/index.js
@@ -12,8 +12,10 @@ import initReadMore from '~/read_more';
import leaveByUrl from '~/namespaces/leave_by_url';
import Star from '../../../star';
import notificationsDropdown from '../../../notifications_dropdown';
+import initVueAlerts from '../../../vue_alerts';
document.addEventListener('DOMContentLoaded', () => {
+ initVueAlerts();
initReadMore();
new Star(); // eslint-disable-line no-new
notificationsDropdown();
diff --git a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
index ebd7a17040a..15c220a554d 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
@@ -69,7 +69,9 @@ export default {
>
<ci-icon :status="group.status" />
- <span class="ci-status-text text-truncate mw-70p gl-pl-1 d-inline-block align-bottom">
+ <span
+ class="ci-status-text text-truncate mw-70p gl-pl-1-deprecated-no-really-do-not-use-me d-inline-block align-bottom"
+ >
{{ group.name }}
</span>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue b/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
index 7125790ac3d..74a261f35d7 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
@@ -27,7 +27,9 @@ export default {
<template>
<span class="ci-job-name-component mw-100">
<ci-icon :status="status" />
- <span class="ci-status-text text-truncate mw-70p gl-pl-1 d-inline-block align-bottom">
+ <span
+ class="ci-status-text text-truncate mw-70p gl-pl-1-deprecated-no-really-do-not-use-me d-inline-block align-bottom"
+ >
{{ name }}
</span>
</span>
diff --git a/app/assets/javascripts/releases/components/evidence_block.vue b/app/assets/javascripts/releases/components/evidence_block.vue
index 59c1b3eb48e..9bb423ef2fa 100644
--- a/app/assets/javascripts/releases/components/evidence_block.vue
+++ b/app/assets/javascripts/releases/components/evidence_block.vue
@@ -80,7 +80,9 @@ export default {
<span class="js-short monospace">{{ shortSha(index) }}</span>
</template>
<template slot="expanded">
- <span class="js-expanded monospace gl-pl-1">{{ sha(index) }}</span>
+ <span class="js-expanded monospace gl-pl-1-deprecated-no-really-do-not-use-me">{{
+ sha(index)
+ }}</span>
</template>
</expand-button>
<clipboard-button
diff --git a/app/assets/javascripts/releases/components/release_block_header.vue b/app/assets/javascripts/releases/components/release_block_header.vue
index 6f7e1dcfe2f..1e703c247ae 100644
--- a/app/assets/javascripts/releases/components/release_block_header.vue
+++ b/app/assets/javascripts/releases/components/release_block_header.vue
@@ -41,7 +41,7 @@ export default {
<template>
<div class="card-header d-flex align-items-center bg-white pr-0">
- <h2 class="card-title my-2 mr-auto gl-font-size-20">
+ <h2 class="card-title my-2 mr-auto gl-font-size-20-deprecated-no-really-do-not-use-me">
<gl-link v-if="selfLink" :href="selfLink" class="font-size-inherit">
{{ release.name }}
</gl-link>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue
index 33db9b87b17..2f922b990d9 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue
@@ -75,7 +75,7 @@ export default {
:href="deployment.url"
target="_blank"
rel="noopener noreferrer nofollow"
- class="js-deploy-meta gl-font-size-12"
+ class="js-deploy-meta gl-font-sm"
>
{{ deployment.name }}
</gl-link>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_collapsible_extension.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_collapsible_extension.vue
index ba8da46d207..294871ca5c2 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_collapsible_extension.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_collapsible_extension.vue
@@ -51,7 +51,7 @@ export default {
<div class="mr-widget-extension d-flex align-items-center pl-3">
<div v-if="hasError" class="ci-widget media">
<div class="media-body">
- <span class="gl-font-size-small mr-widget-margin-left gl-line-height-24 js-error-state">{{
+ <span class="gl-font-sm mr-widget-margin-left gl-line-height-24 js-error-state">{{
title
}}</span>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
index ffc616d7309..37998f8aa97 100644
--- a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
+++ b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
@@ -169,15 +169,15 @@ export default {
menu-class="date-time-picker-menu"
toggle-class="date-time-picker-toggle text-truncate"
>
- <div class="d-flex justify-content-between gl-p-2">
+ <div class="d-flex justify-content-between gl-p-2-deprecated-no-really-do-not-use-me">
<gl-form-group
v-if="customEnabled"
:label="__('Custom range')"
label-for="custom-from-time"
- label-class="gl-pb-1"
- class="custom-time-range-form-group col-md-7 gl-pl-1 gl-pr-0 m-0"
+ label-class="gl-pb-1-deprecated-no-really-do-not-use-me"
+ class="custom-time-range-form-group col-md-7 gl-pl-1-deprecated-no-really-do-not-use-me gl-pr-0 m-0"
>
- <div class="gl-pt-2">
+ <div class="gl-pt-2-deprecated-no-really-do-not-use-me">
<date-time-picker-input
id="custom-time-from"
v-model="startInput"
@@ -198,9 +198,12 @@ export default {
</gl-deprecated-button>
</gl-form-group>
</gl-form-group>
- <gl-form-group label-for="group-id-dropdown" class="col-md-5 gl-pl-1 gl-pr-1 m-0">
+ <gl-form-group
+ label-for="group-id-dropdown"
+ class="col-md-5 gl-pl-1-deprecated-no-really-do-not-use-me gl-pr-1-deprecated-no-really-do-not-use-me m-0"
+ >
<template #label>
- <span class="gl-pl-5">{{ __('Quick range') }}</span>
+ <span class="gl-pl-5-deprecated-no-really-do-not-use-me">{{ __('Quick range') }}</span>
</template>
<gl-dropdown-item
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
index 44cc11a6aaa..5eef439aa90 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
@@ -80,11 +80,6 @@ export default {
required: false,
default: false,
},
- scopedLabelsDocumentationLink: {
- type: String,
- required: false,
- default: '#',
- },
},
computed: {
hiddenInputName() {
@@ -136,7 +131,6 @@ export default {
<dropdown-value
:labels="context.labels"
:label-filter-base-path="labelFilterBasePath"
- :scoped-labels-documentation-link="scopedLabelsDocumentationLink"
:enable-scoped-labels="enableScopedLabels"
>
<slot></slot>
@@ -157,7 +151,6 @@ export default {
:namespace="namespace"
:labels="context.labels"
:show-extra-options="!showCreate"
- :scoped-labels-documentation-link="scopedLabelsDocumentationLink"
:enable-scoped-labels="enableScopedLabels"
/>
<div
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue
index c3bc61d0053..30f7e6a5980 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue
@@ -36,11 +36,6 @@ export default {
required: false,
default: false,
},
- scopedLabelsDocumentationLink: {
- type: String,
- required: false,
- default: '#',
- },
},
computed: {
dropdownToggleText() {
@@ -72,7 +67,6 @@ export default {
:data-namespace-path="namespace"
:data-show-any="showExtraOptions"
:data-scoped-labels="enableScopedLabels"
- :data-scoped-labels-documentation-link="scopedLabelsDocumentationLink"
type="button"
class="dropdown-menu-toggle wide js-label-select js-multiselect js-context-config-modal"
data-toggle="dropdown"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue
index fe43f77b1ee..71d7069dd57 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue
@@ -20,11 +20,6 @@ export default {
required: false,
default: false,
},
- scopedLabelsDocumentationLink: {
- type: String,
- required: false,
- default: '#',
- },
},
computed: {
isEmpty() {
@@ -64,7 +59,6 @@ export default {
:title="label.title"
:description="label.description"
:scoped="showScopedLabels(label)"
- :scoped-labels-documentation-link="scopedLabelsDocumentationLink"
/>
</template>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue
index 695af775750..12ad2acf308 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue
@@ -9,12 +9,7 @@ export default {
GlLabel,
},
computed: {
- ...mapState([
- 'selectedLabels',
- 'allowScopedLabels',
- 'labelsFilterBasePath',
- 'scopedLabelsDocumentationPath',
- ]),
+ ...mapState(['selectedLabels', 'allowScopedLabels', 'labelsFilterBasePath']),
},
methods: {
labelFilterUrl(label) {
@@ -45,7 +40,6 @@ export default {
:background-color="label.color"
:target="labelFilterUrl(label)"
:scoped="scopedLabel(label)"
- :scoped-labels-documentation-link="scopedLabelsDocumentationPath"
tooltip-placement="top"
/>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
index 78102caacf5..0ab45e3308c 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
@@ -67,11 +67,6 @@ export default {
required: false,
default: '',
},
- scopedLabelsDocumentationPath: {
- type: String,
- required: false,
- default: '',
- },
labelsListTitle: {
type: String,
required: false,
@@ -113,7 +108,6 @@ export default {
labelsFetchPath: this.labelsFetchPath,
labelsManagePath: this.labelsManagePath,
labelsFilterBasePath: this.labelsFilterBasePath,
- scopedLabelsDocumentationPath: this.scopedLabelsDocumentationPath,
labelsListTitle: this.labelsListTitle,
labelsCreateTitle: this.labelsCreateTitle,
footerCreateLabelTitle: this.footerCreateLabelTitle,
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/state.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/state.js
index ceabc696693..c83bf9e47ec 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/state.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/state.js
@@ -11,7 +11,6 @@ export default () => ({
namespace: '',
labelsFetchPath: '',
labelsFilterBasePath: '',
- scopedLabelsDocumentationPath: '#',
// UI Flags
allowLabelCreate: false,
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index 657e52674db..cc4d13db150 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -37,4 +37,12 @@
@import "application_ee";
// CSS util classes
+/**
+ These are deprecated in favor of the Gitlab UI utilities imported below.
+ Please check https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss
+ to see the available utility classes.
+**/
@import "utilities";
+
+// Gitlab UI util classes
+@import "@gitlab/ui/src/scss/utilities";
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 7f50c50145b..dfa65656739 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -516,11 +516,36 @@ img.emoji {
These will be replaced when the Gitlab UI utilities are included.
**/
@each $index, $padding in $spacing-scale {
- #{'.gl-p-#{$index}'} { padding: $padding; }
- #{'.gl-pl-#{$index}'} { padding-left: $padding; }
- #{'.gl-pr-#{$index}'} { padding-right: $padding; }
- #{'.gl-pt-#{$index}'} { padding-top: $padding; }
- #{'.gl-pb-#{$index}'} { padding-bottom: $padding; }
+ #{'.gl-p-#{$index}-deprecated-no-really-do-not-use-me'} { padding: $padding; }
+ #{'.gl-pl-#{$index}-deprecated-no-really-do-not-use-me'} { padding-left: $padding; }
+ #{'.gl-pr-#{$index}-deprecated-no-really-do-not-use-me'} { padding-right: $padding; }
+ #{'.gl-pt-#{$index}-deprecated-no-really-do-not-use-me'} { padding-top: $padding; }
+ #{'.gl-pb-#{$index}-deprecated-no-really-do-not-use-me'} { padding-bottom: $padding; }
+}
+
+/**
+ The zero-indexed classes will not change and do not need to be updated.
+ These can be removed when the Gitlab UI class include is merged.
+**/
+
+.gl-p-0 {
+ padding: 0;
+}
+
+.gl-pl-0 {
+ padding-left: 0;
+}
+
+.gl-pr-0 {
+ padding-right: 0;
+}
+
+.gl-pt-0 {
+ padding-top: 0;
+}
+
+.gl-pb-0 {
+ padding-bottom: 0;
}
/**
@@ -611,15 +636,13 @@ img.emoji {
}
}
-.gl-font-size-small { font-size: $gl-font-size-small; }
-.gl-font-size-large { font-size: $gl-font-size-large; }
+.gl-font-sm { font-size: $gl-font-size-small; }
+.gl-font-lg { font-size: $gl-font-size-large; }
+.gl-font-base { font-size: $gl-font-size-14; }
.gl-line-height-24 { line-height: $gl-line-height-24; }
.gl-font-size-0 { font-size: 0; }
-.gl-font-size-12 { font-size: $gl-font-size-12; }
-.gl-font-size-14 { font-size: $gl-font-size-14; }
-.gl-font-size-16 { font-size: $gl-font-size-16; }
.gl-font-size-28 { font-size: $gl-font-size-28; }
.gl-font-size-42 { font-size: $gl-font-size-42; }
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index a095d957bb8..a8223a8ff56 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -1,3 +1,10 @@
+/**
+ Please note: These are deprecated in favor of the Gitlab UI utility classes.
+ Check https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss
+ to see the available utility classes. If you cannot find the class you need,
+ consider adding it to Gitlab UI before adding it here.
+**/
+
@each $variant, $range in $color-ranges {
@each $suffix, $color in $range {
#{'.bg-#{$variant}-#{$suffix}'} {
@@ -82,6 +89,14 @@
width: px-to-rem(16px);
}
+.gl-shim-pb-3 {
+ padding-bottom: 8px;
+}
+
+.gl-shim-pt-5 {
+ padding-top: 16px;
+}
+
.gl-text-purple { color: $purple; }
.gl-text-gray-800 { color: $gray-800; }
.gl-bg-purple-light { background-color: $purple-light; }
@@ -124,5 +139,5 @@
.gl-white-space-normal { @include gl-white-space-normal; }
.gl-word-break-all { @include gl-word-break-all; }
-.gl-line-height-inherit { line-height: inherit; }
-.gl-text-align-inherit { text-align: inherit; }
+.gl-reset-line-height { @include gl-reset-line-height; }
+.gl-reset-text-align { @include gl-reset-text-align; }
diff --git a/app/views/ci/status/_dropdown_graph_badge.html.haml b/app/views/ci/status/_dropdown_graph_badge.html.haml
index 369b0f7e62c..d9d646c77d9 100644
--- a/app/views/ci/status/_dropdown_graph_badge.html.haml
+++ b/app/views/ci/status/_dropdown_graph_badge.html.haml
@@ -8,12 +8,12 @@
- if status.has_details?
= link_to status.details_path, class: 'mini-pipeline-graph-dropdown-item d-flex', data: { toggle: 'tooltip', title: tooltip, container: 'body' } do
%span{ class: klass }= sprite_icon(status.icon)
- %span.ci-build-text.text-truncate.mw-70p.gl-pl-1= subject.name
+ %span.ci-build-text.text-truncate.mw-70p.gl-pl-1-deprecated-no-really-do-not-use-me= subject.name
- else
.menu-item.mini-pipeline-graph-dropdown-item.d-flex{ data: { toggle: 'tooltip', title: tooltip, container: 'body' } }
%span{ class: klass }= sprite_icon(status.icon)
- %span.ci-build-text.text-truncate.mw-70p.gl-pl-1= subject.name
+ %span.ci-build-text.text-truncate.mw-70p.gl-pl-1-deprecated-no-really-do-not-use-me= subject.name
- if status.has_action?
= link_to status.action_path, class: "ci-action-icon-container ci-action-icon-wrapper js-ci-action-icon", method: status.action_method, data: { toggle: 'tooltip', title: status.action_title, container: 'body' } do
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index 232dffa28b4..9fb5e27b692 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -8,7 +8,7 @@
= _("GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security.")
.col-lg-5.order-12
.text-center.mb-3
- %h2.font-weight-bold.gl-font-size-20= _('Register for GitLab')
+ %h2.font-weight-bold.gl-font-size-20-deprecated-no-really-do-not-use-me= _('Register for GitLab')
= render 'devise/shared/experimental_separate_sign_up_flow_box'
= render 'devise/shared/sign_in_link'
- else
diff --git a/app/views/projects/blob/_template_selectors.html.haml b/app/views/projects/blob/_template_selectors.html.haml
index 2be95bc5541..ba8029ac32a 100644
--- a/app/views/projects/blob/_template_selectors.html.haml
+++ b/app/views/projects/blob/_template_selectors.html.haml
@@ -1,4 +1,4 @@
-.template-selectors-menu.gl-pl-2
+.template-selectors-menu.gl-pl-2-deprecated-no-really-do-not-use-me
.template-selector-dropdowns-wrap
.template-type-selector.js-template-type-selector-wrap.hidden
- toggle_text = should_suggest_gitlab_ci_yml? ? '.gitlab-ci.yml' : 'Select a template type'
diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml
index a952db0eea3..495a4ac50bf 100644
--- a/app/views/projects/graphs/show.html.haml
+++ b/app/views/projects/graphs/show.html.haml
@@ -1,6 +1,6 @@
- page_title _('Contributors')
-.sub-header-block.bg-gray-light.gl-p-3
+.sub-header-block.bg-gray-light.gl-p-3-deprecated-no-really-do-not-use-me
.tree-ref-holder.inline.vertical-align-middle
= render 'shared/ref_switcher', destination: 'graphs'
= link_to s_('Commits|History'), project_commits_path(@project, current_ref), class: 'btn'
diff --git a/app/views/shared/boards/components/_board.html.haml b/app/views/shared/boards/components/_board.html.haml
index ffb406ac35b..2a5b72d478a 100644
--- a/app/views/shared/boards/components/_board.html.haml
+++ b/app/views/shared/boards/components/_board.html.haml
@@ -38,8 +38,7 @@
":description" => "list.label.description",
"tooltipPlacement" => "bottom",
":size" => '(!list.isExpanded ? "sm" : "")',
- ":scoped" => "showScopedLabels(list.label)",
- ":scoped-labels-documentation-link" => "helpLink" }
+ ":scoped" => "showScopedLabels(list.label)" }
- if can?(current_user, :admin_list, current_board_parent)
%board-delete{ "inline-template" => true,
diff --git a/app/views/shared/boards/components/sidebar/_labels.html.haml b/app/views/shared/boards/components/sidebar/_labels.html.haml
index a1088dc5222..58ffa3942ef 100644
--- a/app/views/shared/boards/components/sidebar/_labels.html.haml
+++ b/app/views/shared/boards/components/sidebar/_labels.html.haml
@@ -12,8 +12,7 @@
":background-color" => "label.color",
":title" => "label.title",
":description" => "label.description",
- ":scoped" => "showScopedLabels(label)",
- ":scoped-labels-documentation-link" => "helpLink" }
+ ":scoped" => "showScopedLabels(label)" }
- if can_admin_issue?
.selectbox
diff --git a/app/views/shared/issuable/form/_branch_chooser.html.haml b/app/views/shared/issuable/form/_branch_chooser.html.haml
index d8253924e0a..3794a3b3845 100644
--- a/app/views/shared/issuable/form/_branch_chooser.html.haml
+++ b/app/views/shared/issuable/form/_branch_chooser.html.haml
@@ -6,7 +6,7 @@
- source_title, target_title = format_mr_branch_names(@merge_request)
-.form-group.row.d-flex.gl-pl-3.gl-pr-3.branch-selector
+.form-group.row.d-flex.gl-pl-3-deprecated-no-really-do-not-use-me.gl-pr-3-deprecated-no-really-do-not-use-me.branch-selector
.align-self-center
%span
= _('From <code>%{source_title}</code> into').html_safe % { source_title: source_title }
diff --git a/app/workers/project_export_worker.rb b/app/workers/project_export_worker.rb
index a287c511a65..fd3408bc13a 100644
--- a/app/workers/project_export_worker.rb
+++ b/app/workers/project_export_worker.rb
@@ -9,7 +9,7 @@ class ProjectExportWorker # rubocop:disable Scalability/IdempotentWorker
worker_resource_boundary :memory
urgency :throttled
- def perform(current_user_id, project_id, after_export_strategy = {}, params = {})
+ def perform(current_user_id, project_id, after_export_strategy = {}, params = {}, options = {})
current_user = User.find(current_user_id)
project = Project.find(project_id)
export_job = project.export_jobs.safe_find_or_create_by(jid: self.jid)
@@ -17,7 +17,7 @@ class ProjectExportWorker # rubocop:disable Scalability/IdempotentWorker
export_job&.start
- ::Projects::ImportExport::ExportService.new(project, current_user, params).execute(after_export)
+ ::Projects::ImportExport::ExportService.new(project, current_user, params).execute(after_export, options)
export_job&.finish
rescue ActiveRecord::RecordNotFound, Gitlab::ImportExport::AfterExportStrategyBuilder::StrategyNotFoundError => e
diff --git a/changelogs/unreleased/213238-fix-ide-discard-empty-file.yml b/changelogs/unreleased/213238-fix-ide-discard-empty-file.yml
new file mode 100644
index 00000000000..1a8ac3400c5
--- /dev/null
+++ b/changelogs/unreleased/213238-fix-ide-discard-empty-file.yml
@@ -0,0 +1,5 @@
+---
+title: Fix discard button not showing for new empty files in Web IDE
+merge_request: 30767
+author:
+type: fixed
diff --git a/changelogs/unreleased/215164-show-correct-import-label-and-import-count-on-jira-import-form.yml b/changelogs/unreleased/215164-show-correct-import-label-and-import-count-on-jira-import-form.yml
new file mode 100644
index 00000000000..e5735296a52
--- /dev/null
+++ b/changelogs/unreleased/215164-show-correct-import-label-and-import-count-on-jira-import-form.yml
@@ -0,0 +1,5 @@
+---
+title: Show correct label and count on Jira import form
+merge_request: 30072
+author:
+type: changed
diff --git a/changelogs/unreleased/215569-jira-import-fix-default-author.yml b/changelogs/unreleased/215569-jira-import-fix-default-author.yml
new file mode 100644
index 00000000000..4c7583c0958
--- /dev/null
+++ b/changelogs/unreleased/215569-jira-import-fix-default-author.yml
@@ -0,0 +1,5 @@
+---
+title: Use Jira import owner as the issue author when importing issues from Jira
+merge_request: 30504
+author:
+type: fixed
diff --git a/danger/utility_css/Dangerfile b/danger/utility_css/Dangerfile
new file mode 100644
index 00000000000..4f56c40379e
--- /dev/null
+++ b/danger/utility_css/Dangerfile
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+common = 'app/assets/stylesheets/framework/common.scss'
+utilities = 'app/assets/stylesheets/utilities.scss'
+
+def get_css_files(files, common_filepath, utilities_filepath)
+ files.select do |file|
+ file.include?(common_filepath) ||
+ file.include?(utilities_filepath)
+ end
+end
+
+changed_util_files = get_css_files(helper.all_changed_files.to_a, common, utilities)
+
+unless changed_util_files.empty?
+
+ markdown(<<~MARKDOWN)
+ ## Changes to utility SCSS files
+ MARKDOWN
+
+ if changed_util_files.include?(common)
+
+ markdown(<<~MARKDOWN)
+ ### Addition to `#{common}`
+
+ You have added a new rule to `#{common}`. Are you sure you need this rule?
+
+ If it is a component class shared across items, could it be added to the component as a utility class or to the component's stylesheet? If not, you can ignore this warning.
+
+ If it is a new utility class, is there another class that shares the same values in either this file or in `#{utilities}`? If not, please add it to `#{utilities}`, following the [Gitlab UI naming style](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss).
+
+ MARKDOWN
+
+ end
+
+ if changed_util_files.include?(utilities)
+ markdown(<<~MARKDOWN)
+ ### Addition to `#{utilities}`
+
+ You have added a new rule to `#{utilities}`. Are you sure you need this rule?
+
+ If it is a component class shared across items, could it be added to the component as a utility class or to the component's stylesheet? If not, consider adding it to `#{common}`
+
+ If it is a new utility class, is there another class that shares the same values in either this file or in `#{utilities}`? If not, please be sure this addition follows the [Gitlab UI naming style](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss) so it may be removed when these rules are included. See [Include gitlab-ui utility-class library](https://gitlab.com/gitlab-org/gitlab/issues/36857) for more about this project.
+
+ MARKDOWN
+ end
+
+ warn "This merge request adds a new rule to #{common} or #{utilities}."
+
+end
diff --git a/doc/administration/external_pipeline_validation.md b/doc/administration/external_pipeline_validation.md
index 19d4de3b705..489d1924803 100644
--- a/doc/administration/external_pipeline_validation.md
+++ b/doc/administration/external_pipeline_validation.md
@@ -20,7 +20,7 @@ Response Code Legend:
## Configuration
-Set the `EXTERNAL_VALIDATION_SERVICE_URL` to the external service url.
+Set the `EXTERNAL_VALIDATION_SERVICE_URL` to the external service URL.
## Payload Schema
diff --git a/doc/administration/high_availability/gitlab.md b/doc/administration/high_availability/gitlab.md
index f0b6d637c3f..cb5910decaa 100644
--- a/doc/administration/high_availability/gitlab.md
+++ b/doc/administration/high_availability/gitlab.md
@@ -79,8 +79,8 @@ is recommended over [NFS](nfs.md) wherever possible for improved performance.
NOTE: **Note:** To maintain uniformity of links across HA clusters, the `external_url`
on the first application server as well as the additional application
- servers should point to the external url that users will use to access GitLab.
- In a typical HA setup, this will be the url of the load balancer which will
+ servers should point to the external URL that users will use to access GitLab.
+ In a typical HA setup, this will be the URL of the load balancer which will
route traffic to all GitLab application servers in the HA cluster.
NOTE: **Note:** When you specify `https` in the `external_url`, as in the example
diff --git a/doc/administration/lfs/index.md b/doc/administration/lfs/index.md
index 242758b395a..d333d3ff3b8 100644
--- a/doc/administration/lfs/index.md
+++ b/doc/administration/lfs/index.md
@@ -129,7 +129,7 @@ Here is a configuration example with Rackspace Cloud Files.
NOTE: **Note:**
Regardless of whether the container has public access enabled or disabled, Fog will
use the TempURL method to grant access to LFS objects. If you see errors in logs referencing
-instantiating storage with a temp-url-key, ensure that you have set the key properly
+instantiating storage with a `temp-url-key`, ensure that you have set the key properly
on the Rackspace API and in `gitlab.rb`. You can verify the value of the key Rackspace
has set by sending a GET request with token header to the service access endpoint URL
and comparing the output of the returned headers.
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index fff7762bd99..ef1d9d95ffa 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -31,17 +31,17 @@ The following metrics are available:
| Metric | Type | Since | Description | Labels |
|:---------------------------------------------------------------|:----------|-----------------------:|:----------------------------------------------------------------------------------------------------|:----------------------------------------------------|
-| `gitlab_banzai_cached_render_real_duration_seconds` | Histogram | 9.4 | Duration of rendering Markdown into HTML when cached output exists | controller, action |
-| `gitlab_banzai_cacheless_render_real_duration_seconds` | Histogram | 9.4 | Duration of rendering Markdown into HTML when cached output does not exist | controller, action |
-| `gitlab_cache_misses_total` | Counter | 10.2 | Cache read miss | controller, action |
+| `gitlab_banzai_cached_render_real_duration_seconds` | Histogram | 9.4 | Duration of rendering Markdown into HTML when cached output exists | `controller`, `action` |
+| `gitlab_banzai_cacheless_render_real_duration_seconds` | Histogram | 9.4 | Duration of rendering Markdown into HTML when cached output does not exist | `controller`, `action` |
+| `gitlab_cache_misses_total` | Counter | 10.2 | Cache read miss | `controller`, `action` |
| `gitlab_cache_operation_duration_seconds` | Histogram | 10.2 | Cache access time | |
-| `gitlab_cache_operations_total` | Counter | 12.2 | Cache operations by controller/action | controller, action, operation |
+| `gitlab_cache_operations_total` | Counter | 12.2 | Cache operations by controller/action | `controller`, `action`, `operation` |
| `gitlab_ci_pipeline_creation_duration_seconds` | Histogram | 13.0 | Time in seconds it takes to create a CI/CD pipeline | |
-| `job_waiter_started_total` | Counter | 12.9 | Number of batches of jobs started where a web request is waiting for the jobs to complete | worker |
-| `job_waiter_timeouts_total` | Counter | 12.9 | Number of batches of jobs that timed out where a web request is waiting for the jobs to complete | worker |
+| `job_waiter_started_total` | Counter | 12.9 | Number of batches of jobs started where a web request is waiting for the jobs to complete | `worker` |
+| `job_waiter_timeouts_total` | Counter | 12.9 | Number of batches of jobs that timed out where a web request is waiting for the jobs to complete | `worker` |
| `gitlab_database_transaction_seconds` | Histogram | 12.1 | Time spent in database transactions, in seconds | |
-| `gitlab_method_call_duration_seconds` | Histogram | 10.2 | Method calls real duration | controller, action, module, method |
-| `gitlab_page_out_of_bounds` | Counter | 12.8 | Counter for the PageLimiter pagination limit being hit | controller, action, bot |
+| `gitlab_method_call_duration_seconds` | Histogram | 10.2 | Method calls real duration | `controller`, `action`, `module`, `method` |
+| `gitlab_page_out_of_bounds` | Counter | 12.8 | Counter for the PageLimiter pagination limit being hit | `controller`, `action`, `bot` |
| `gitlab_rails_queue_duration_seconds` | Histogram | 9.4 | Measures latency between GitLab Workhorse forwarding a request to Rails | |
| `gitlab_sql_duration_seconds` | Histogram | 10.2 | SQL execution time, excluding SCHEMA operations and BEGIN / COMMIT | |
| `gitlab_transaction_allocated_memory_bytes` | Histogram | 10.2 | Allocated memory for all transactions (gitlab_transaction_* metrics) | |
@@ -49,27 +49,27 @@ The following metrics are available:
| `gitlab_transaction_cache_<key>_duration_total` | Counter | 10.2 | Counter for total time (seconds) spent in Rails cache calls (per key) | |
| `gitlab_transaction_cache_count_total` | Counter | 10.2 | Counter for total Rails cache calls (aggregate) | |
| `gitlab_transaction_cache_duration_total` | Counter | 10.2 | Counter for total time (seconds) spent in Rails cache calls (aggregate) | |
-| `gitlab_transaction_cache_read_hit_count_total` | Counter | 10.2 | Counter for cache hits for Rails cache calls | controller, action |
-| `gitlab_transaction_cache_read_miss_count_total` | Counter | 10.2 | Counter for cache misses for Rails cache calls | controller, action |
-| `gitlab_transaction_duration_seconds` | Histogram | 10.2 | Duration for all transactions (gitlab_transaction_* metrics) | controller, action |
+| `gitlab_transaction_cache_read_hit_count_total` | Counter | 10.2 | Counter for cache hits for Rails cache calls | `controller`, `action` |
+| `gitlab_transaction_cache_read_miss_count_total` | Counter | 10.2 | Counter for cache misses for Rails cache calls | `controller`, `action` |
+| `gitlab_transaction_duration_seconds` | Histogram | 10.2 | Duration for all transactions (gitlab_transaction_* metrics) | `controller`, `action` |
| `gitlab_transaction_event_build_found_total` | Counter | 9.4 | Counter for build found for API /jobs/request | |
| `gitlab_transaction_event_build_invalid_total` | Counter | 9.4 | Counter for build invalid due to concurrency conflict for API /jobs/request | |
| `gitlab_transaction_event_build_not_found_cached_total` | Counter | 9.4 | Counter for cached response of build not found for API /jobs/request | |
| `gitlab_transaction_event_build_not_found_total` | Counter | 9.4 | Counter for build not found for API /jobs/request | |
| `gitlab_transaction_event_change_default_branch_total` | Counter | 9.4 | Counter when default branch is changed for any repository | |
| `gitlab_transaction_event_create_repository_total` | Counter | 9.4 | Counter when any repository is created | |
-| `gitlab_transaction_event_etag_caching_cache_hit_total` | Counter | 9.4 | Counter for etag cache hit. | endpoint |
-| `gitlab_transaction_event_etag_caching_header_missing_total` | Counter | 9.4 | Counter for etag cache miss - header missing | endpoint |
-| `gitlab_transaction_event_etag_caching_key_not_found_total` | Counter | 9.4 | Counter for etag cache miss - key not found | endpoint |
-| `gitlab_transaction_event_etag_caching_middleware_used_total` | Counter | 9.4 | Counter for etag middleware accessed | endpoint |
-| `gitlab_transaction_event_etag_caching_resource_changed_total` | Counter | 9.4 | Counter for etag cache miss - resource changed | endpoint |
+| `gitlab_transaction_event_etag_caching_cache_hit_total` | Counter | 9.4 | Counter for etag cache hit. | `endpoint` |
+| `gitlab_transaction_event_etag_caching_header_missing_total` | Counter | 9.4 | Counter for etag cache miss - header missing | `endpoint` |
+| `gitlab_transaction_event_etag_caching_key_not_found_total` | Counter | 9.4 | Counter for etag cache miss - key not found | `endpoint` |
+| `gitlab_transaction_event_etag_caching_middleware_used_total` | Counter | 9.4 | Counter for etag middleware accessed | `endpoint` |
+| `gitlab_transaction_event_etag_caching_resource_changed_total` | Counter | 9.4 | Counter for etag cache miss - resource changed | `endpoint` |
| `gitlab_transaction_event_fork_repository_total` | Counter | 9.4 | Counter for repository forks (RepositoryForkWorker). Only incremented when source repository exists | |
| `gitlab_transaction_event_import_repository_total` | Counter | 9.4 | Counter for repository imports (RepositoryImportWorker) | |
| `gitlab_transaction_event_push_branch_total` | Counter | 9.4 | Counter for all branch pushes | |
-| `gitlab_transaction_event_push_commit_total` | Counter | 9.4 | Counter for commits | branch |
+| `gitlab_transaction_event_push_commit_total` | Counter | 9.4 | Counter for commits | `branch` |
| `gitlab_transaction_event_push_tag_total` | Counter | 9.4 | Counter for tag pushes | |
| `gitlab_transaction_event_rails_exception_total` | Counter | 9.4 | Counter for number of rails exceptions | |
-| `gitlab_transaction_event_receive_email_total` | Counter | 9.4 | Counter for received emails | handler |
+| `gitlab_transaction_event_receive_email_total` | Counter | 9.4 | Counter for received emails | `handler` |
| `gitlab_transaction_event_remote_mirrors_failed_total` | Counter | 10.8 | Counter for failed remote mirrors | |
| `gitlab_transaction_event_remote_mirrors_finished_total` | Counter | 10.8 | Counter for finished remote mirrors | |
| `gitlab_transaction_event_remote_mirrors_running_total` | Counter | 10.8 | Counter for running remote mirrors | |
@@ -77,15 +77,15 @@ The following metrics are available:
| `gitlab_transaction_event_remove_repository_total` | Counter | 9.4 | Counter when a repository is removed | |
| `gitlab_transaction_event_remove_tag_total` | Counter | 9.4 | Counter when a tag is remove for any repository | |
| `gitlab_transaction_event_sidekiq_exception_total` | Counter | 9.4 | Counter of Sidekiq exceptions | |
-| `gitlab_transaction_event_stuck_import_jobs_total` | Counter | 9.4 | Count of stuck import jobs | projects_without_jid_count, projects_with_jid_count |
+| `gitlab_transaction_event_stuck_import_jobs_total` | Counter | 9.4 | Count of stuck import jobs | `projects_without_jid_count`, `projects_with_jid_count` |
| `gitlab_transaction_event_update_build_total` | Counter | 9.4 | Counter for update build for API /jobs/request/:id | |
| `gitlab_transaction_new_redis_connections_total` | Counter | 9.4 | Counter for new Redis connections | |
| `gitlab_transaction_queue_duration_total` | Counter | 9.4 | Duration jobs were enqueued before processing | |
-| `gitlab_transaction_rails_queue_duration_total` | Counter | 9.4 | Measures latency between GitLab Workhorse forwarding a request to Rails | controller, action |
-| `gitlab_transaction_view_duration_total` | Counter | 9.4 | Duration for views | controller, action, view |
-| `gitlab_view_rendering_duration_seconds` | Histogram | 10.2 | Duration for views (histogram) | controller, action, view |
-| `http_requests_total` | Counter | 9.4 | Rack request count | method |
-| `http_request_duration_seconds` | Histogram | 9.4 | HTTP response time from rack middleware | method, status |
+| `gitlab_transaction_rails_queue_duration_total` | Counter | 9.4 | Measures latency between GitLab Workhorse forwarding a request to Rails | `controller`, `action` |
+| `gitlab_transaction_view_duration_total` | Counter | 9.4 | Duration for views | `controller`, `action`, `view` |
+| `gitlab_view_rendering_duration_seconds` | Histogram | 10.2 | Duration for views (histogram) | `controller`, `action`, `view` |
+| `http_requests_total` | Counter | 9.4 | Rack request count | `method` |
+| `http_request_duration_seconds` | Histogram | 9.4 | HTTP response time from rack middleware | `method`, `status` |
| `pipelines_created_total` | Counter | 9.4 | Counter of pipelines created | |
| `rack_uncaught_errors_total` | Counter | 9.4 | Rack connections handling uncaught errors count | |
| `user_session_logins_total` | Counter | 9.4 | Counter of how many users have logged in | |
@@ -113,51 +113,51 @@ configuration option in `gitlab.yml`. These metrics are served from the
| Metric | Type | Since | Description | Labels |
|:---------------------------------------------- |:------- |:----- |:----------- |:------ |
-| `sidekiq_jobs_cpu_seconds` | Histogram | 12.4 | Seconds of cpu time to run Sidekiq job | queue, boundary, external_dependencies, feature_category, job_status, urgency |
-| `sidekiq_jobs_completion_seconds` | Histogram | 12.2 | Seconds to complete Sidekiq job | queue, boundary, external_dependencies, feature_category, job_status, urgency |
-| `sidekiq_jobs_db_seconds` | Histogram | 12.9 | Seconds of DB time to run Sidekiq job | queue, boundary, external_dependencies, feature_category, job_status, urgency |
-| `sidekiq_jobs_gitaly_seconds` | Histogram | 12.9 | Seconds of Gitaly time to run Sidekiq job | queue, boundary, external_dependencies, feature_category, job_status, urgency |
-| `sidekiq_jobs_queue_duration_seconds` | Histogram | 12.5 | Duration in seconds that a Sidekiq job was queued before being executed | queue, boundary, external_dependencies, feature_category, urgency |
-| `sidekiq_jobs_failed_total` | Counter | 12.2 | Sidekiq jobs failed | queue, boundary, external_dependencies, feature_category, urgency |
-| `sidekiq_jobs_retried_total` | Counter | 12.2 | Sidekiq jobs retried | queue, boundary, external_dependencies, feature_category, urgency |
-| `sidekiq_running_jobs` | Gauge | 12.2 | Number of Sidekiq jobs running | queue, boundary, external_dependencies, feature_category, urgency |
+| `sidekiq_jobs_cpu_seconds` | Histogram | 12.4 | Seconds of cpu time to run Sidekiq job | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` |
+| `sidekiq_jobs_completion_seconds` | Histogram | 12.2 | Seconds to complete Sidekiq job | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` |
+| `sidekiq_jobs_db_seconds` | Histogram | 12.9 | Seconds of DB time to run Sidekiq job | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` |
+| `sidekiq_jobs_gitaly_seconds` | Histogram | 12.9 | Seconds of Gitaly time to run Sidekiq job | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` |
+| `sidekiq_jobs_queue_duration_seconds` | Histogram | 12.5 | Duration in seconds that a Sidekiq job was queued before being executed | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` |
+| `sidekiq_jobs_failed_total` | Counter | 12.2 | Sidekiq jobs failed | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` |
+| `sidekiq_jobs_retried_total` | Counter | 12.2 | Sidekiq jobs retried | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` |
+| `sidekiq_running_jobs` | Gauge | 12.2 | Number of Sidekiq jobs running | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` |
| `sidekiq_concurrency` | Gauge | 12.5 | Maximum number of Sidekiq jobs | |
-| `geo_db_replication_lag_seconds` | Gauge | 10.2 | Database replication lag (seconds) | url |
-| `geo_repositories` | Gauge | 10.2 | Total number of repositories available on primary | url |
-| `geo_repositories_synced` | Gauge | 10.2 | Number of repositories synced on secondary | url |
-| `geo_repositories_failed` | Gauge | 10.2 | Number of repositories failed to sync on secondary | url |
-| `geo_lfs_objects` | Gauge | 10.2 | Total number of LFS objects available on primary | url |
-| `geo_lfs_objects_synced` | Gauge | 10.2 | Number of LFS objects synced on secondary | url |
-| `geo_lfs_objects_failed` | Gauge | 10.2 | Number of LFS objects failed to sync on secondary | url |
-| `geo_attachments` | Gauge | 10.2 | Total number of file attachments available on primary | url |
-| `geo_attachments_synced` | Gauge | 10.2 | Number of attachments synced on secondary | url |
-| `geo_attachments_failed` | Gauge | 10.2 | Number of attachments failed to sync on secondary | url |
-| `geo_last_event_id` | Gauge | 10.2 | Database ID of the latest event log entry on the primary | url |
-| `geo_last_event_timestamp` | Gauge | 10.2 | UNIX timestamp of the latest event log entry on the primary | url |
-| `geo_cursor_last_event_id` | Gauge | 10.2 | Last database ID of the event log processed by the secondary | url |
-| `geo_cursor_last_event_timestamp` | Gauge | 10.2 | Last UNIX timestamp of the event log processed by the secondary | url |
-| `geo_status_failed_total` | Counter | 10.2 | Number of times retrieving the status from the Geo Node failed | url |
-| `geo_last_successful_status_check_timestamp` | Gauge | 10.2 | Last timestamp when the status was successfully updated | url |
-| `geo_lfs_objects_synced_missing_on_primary` | Gauge | 10.7 | Number of LFS objects marked as synced due to the file missing on the primary | url |
-| `geo_job_artifacts_synced_missing_on_primary` | Gauge | 10.7 | Number of job artifacts marked as synced due to the file missing on the primary | url |
-| `geo_attachments_synced_missing_on_primary` | Gauge | 10.7 | Number of attachments marked as synced due to the file missing on the primary | url |
-| `geo_repositories_checksummed_count` | Gauge | 10.7 | Number of repositories checksummed on primary | url |
-| `geo_repositories_checksum_failed_count` | Gauge | 10.7 | Number of repositories failed to calculate the checksum on primary | url |
-| `geo_wikis_checksummed_count` | Gauge | 10.7 | Number of wikis checksummed on primary | url |
-| `geo_wikis_checksum_failed_count` | Gauge | 10.7 | Number of wikis failed to calculate the checksum on primary | url |
-| `geo_repositories_verified_count` | Gauge | 10.7 | Number of repositories verified on secondary | url |
-| `geo_repositories_verification_failed_count` | Gauge | 10.7 | Number of repositories failed to verify on secondary | url |
-| `geo_repositories_checksum_mismatch_count` | Gauge | 10.7 | Number of repositories that checksum mismatch on secondary | url |
-| `geo_wikis_verified_count` | Gauge | 10.7 | Number of wikis verified on secondary | url |
-| `geo_wikis_verification_failed_count` | Gauge | 10.7 | Number of wikis failed to verify on secondary | url |
-| `geo_wikis_checksum_mismatch_count` | Gauge | 10.7 | Number of wikis that checksum mismatch on secondary | url |
-| `geo_repositories_checked_count` | Gauge | 11.1 | Number of repositories that have been checked via `git fsck` | url |
-| `geo_repositories_checked_failed_count` | Gauge | 11.1 | Number of repositories that have a failure from `git fsck` | url |
-| `geo_repositories_retrying_verification_count` | Gauge | 11.2 | Number of repositories verification failures that Geo is actively trying to correct on secondary | url |
-| `geo_wikis_retrying_verification_count` | Gauge | 11.2 | Number of wikis verification failures that Geo is actively trying to correct on secondary | url |
+| `geo_db_replication_lag_seconds` | Gauge | 10.2 | Database replication lag (seconds) | `url` |
+| `geo_repositories` | Gauge | 10.2 | Total number of repositories available on primary | `url` |
+| `geo_repositories_synced` | Gauge | 10.2 | Number of repositories synced on secondary | `url` |
+| `geo_repositories_failed` | Gauge | 10.2 | Number of repositories failed to sync on secondary | `url` |
+| `geo_lfs_objects` | Gauge | 10.2 | Total number of LFS objects available on primary | `url` |
+| `geo_lfs_objects_synced` | Gauge | 10.2 | Number of LFS objects synced on secondary | `url` |
+| `geo_lfs_objects_failed` | Gauge | 10.2 | Number of LFS objects failed to sync on secondary | `url` |
+| `geo_attachments` | Gauge | 10.2 | Total number of file attachments available on primary | `url` |
+| `geo_attachments_synced` | Gauge | 10.2 | Number of attachments synced on secondary | `url` |
+| `geo_attachments_failed` | Gauge | 10.2 | Number of attachments failed to sync on secondary | `url` |
+| `geo_last_event_id` | Gauge | 10.2 | Database ID of the latest event log entry on the primary | `url` |
+| `geo_last_event_timestamp` | Gauge | 10.2 | UNIX timestamp of the latest event log entry on the primary | `url` |
+| `geo_cursor_last_event_id` | Gauge | 10.2 | Last database ID of the event log processed by the secondary | `url` |
+| `geo_cursor_last_event_timestamp` | Gauge | 10.2 | Last UNIX timestamp of the event log processed by the secondary | `url` |
+| `geo_status_failed_total` | Counter | 10.2 | Number of times retrieving the status from the Geo Node failed | `url` |
+| `geo_last_successful_status_check_timestamp` | Gauge | 10.2 | Last timestamp when the status was successfully updated | `url` |
+| `geo_lfs_objects_synced_missing_on_primary` | Gauge | 10.7 | Number of LFS objects marked as synced due to the file missing on the primary | `url` |
+| `geo_job_artifacts_synced_missing_on_primary` | Gauge | 10.7 | Number of job artifacts marked as synced due to the file missing on the primary | `url` |
+| `geo_attachments_synced_missing_on_primary` | Gauge | 10.7 | Number of attachments marked as synced due to the file missing on the primary | `url` |
+| `geo_repositories_checksummed_count` | Gauge | 10.7 | Number of repositories checksummed on primary | `url` |
+| `geo_repositories_checksum_failed_count` | Gauge | 10.7 | Number of repositories failed to calculate the checksum on primary | `url` |
+| `geo_wikis_checksummed_count` | Gauge | 10.7 | Number of wikis checksummed on primary | `url` |
+| `geo_wikis_checksum_failed_count` | Gauge | 10.7 | Number of wikis failed to calculate the checksum on primary | `url` |
+| `geo_repositories_verified_count` | Gauge | 10.7 | Number of repositories verified on secondary | `url` |
+| `geo_repositories_verification_failed_count` | Gauge | 10.7 | Number of repositories failed to verify on secondary | `url` |
+| `geo_repositories_checksum_mismatch_count` | Gauge | 10.7 | Number of repositories that checksum mismatch on secondary | `url` |
+| `geo_wikis_verified_count` | Gauge | 10.7 | Number of wikis verified on secondary | `url` |
+| `geo_wikis_verification_failed_count` | Gauge | 10.7 | Number of wikis failed to verify on secondary | `url` |
+| `geo_wikis_checksum_mismatch_count` | Gauge | 10.7 | Number of wikis that checksum mismatch on secondary | `url` |
+| `geo_repositories_checked_count` | Gauge | 11.1 | Number of repositories that have been checked via `git fsck` | `url` |
+| `geo_repositories_checked_failed_count` | Gauge | 11.1 | Number of repositories that have a failure from `git fsck` | `url` |
+| `geo_repositories_retrying_verification_count` | Gauge | 11.2 | Number of repositories verification failures that Geo is actively trying to correct on secondary | `url` |
+| `geo_wikis_retrying_verification_count` | Gauge | 11.2 | Number of wikis verification failures that Geo is actively trying to correct on secondary | `url` |
| `global_search_bulk_cron_queue_size` | Gauge | 12.10 | Number of database records waiting to be synchronized to Elasticsearch | |
-| `package_files_count` | Gauge | 13.0 | Number of package files on primary | url |
-| `package_files_checksummed_count` | Gauge | 13.0 | Number of package files checksummed on primary | url |
+| `package_files_count` | Gauge | 13.0 | Number of package files on primary | `url` |
+| `package_files_checksummed_count` | Gauge | 13.0 | Number of package files checksummed on primary | `url` |
| `package_files_checksum_failed_count` | Gauge | 13.0 | Number of package files failed to calculate the checksum on primary
## Database load balancing metrics **(PREMIUM ONLY)**
diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md
index 47cef0e5fa0..d327a76b683 100644
--- a/doc/api/releases/index.md
+++ b/doc/api/releases/index.md
@@ -338,7 +338,7 @@ POST /projects/:id/releases
| `milestones` | array of string | no | The title of each milestone the release is associated with. |
| `assets:links` | array of hash | no | An array of assets links. |
| `assets:links:name`| string | required by: `assets:links` | The name of the link. |
-| `assets:links:url` | string | required by: `assets:links` | The url of the link. |
+| `assets:links:url` | string | required by: `assets:links` | The URL of the link. |
| `assets:links:filepath` | string | no | Optional path for a [Direct Asset link](../../user/project/releases.md).
| `released_at` | datetime | no | The date when the release will be/was ready. Defaults to the current time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md
index e6425c3fe17..746d982e16d 100644
--- a/doc/api/repository_files.md
+++ b/doc/api/repository_files.md
@@ -47,7 +47,7 @@ Example response:
Parameters:
-- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
+- `file_path` (required) - URL encoded full path to new file. Ex. lib%2Fclass%2Erb
- `ref` (required) - The name of branch, tag or commit
NOTE: **Note:**
@@ -122,7 +122,7 @@ Example response:
Parameters:
-- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
+- `file_path` (required) - URL encoded full path to new file. Ex. lib%2Fclass%2Erb
- `ref` (required) - The name of branch, tag or commit
NOTE: **Note:**
@@ -161,7 +161,7 @@ curl --header 'PRIVATE-TOKEN: <your_access_token>' 'https://gitlab.example.com/a
Parameters:
-- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
+- `file_path` (required) - URL encoded full path to new file. Ex. lib%2Fclass%2Erb
- `ref` (required) - The name of branch, tag or commit
NOTE: **Note:**
@@ -193,7 +193,7 @@ Example response:
Parameters:
-- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
+- `file_path` (required) - URL encoded full path to new file. Ex. lib%2Fclass%2Erb
- `branch` (required) - Name of the branch
- `start_branch` (optional) - Name of the branch to start the new commit from
- `encoding` (optional) - Change encoding to 'base64'. Default is text.
@@ -228,7 +228,7 @@ Example response:
Parameters:
-- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
+- `file_path` (required) - URL encoded full path to new file. Ex. lib%2Fclass%2Erb
- `branch` (required) - Name of the branch
- `start_branch` (optional) - Name of the branch to start the new commit from
- `encoding` (optional) - Change encoding to 'base64'. Default is text.
@@ -265,7 +265,7 @@ curl --request DELETE --header 'PRIVATE-TOKEN: <your_access_token>' --header "Co
Parameters:
-- `file_path` (required) - Url encoded full path to new file. Ex. lib%2Fclass%2Erb
+- `file_path` (required) - URL encoded full path to new file. Ex. lib%2Fclass%2Erb
- `branch` (required) - Name of the branch
- `start_branch` (optional) - Name of the branch to start the new commit from
- `author_email` (optional) - Specify the commit author's email address
diff --git a/doc/api/services.md b/doc/api/services.md
index 823e2e0b5eb..c384f57008a 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -189,9 +189,9 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `new_issue_url` | string | true | New Issue url |
-| `issues_url` | string | true | Issue url |
-| `project_url` | string | true | Project url |
+| `new_issue_url` | string | true | New Issue URL |
+| `issues_url` | string | true | Issue URL |
+| `project_url` | string | true | Project URL |
| `description` | string | false | Description |
| `title` | string | false | Title |
| `push_events` | boolean | false | Enable notifications for push events |
@@ -347,11 +347,11 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `new_issue_url` | string | true | New Issue url
-| `issues_url` | string | true | Issue url
-| `project_url` | string | true | Project url
-| `description` | string | false | Description
-| `title` | string | false | Title
+| `new_issue_url` | string | true | New Issue URL |
+| `issues_url` | string | true | Issue URL |
+| `project_url` | string | true | Project URL |
+| `description` | string | false | Description |
+| `title` | string | false | Title |
| `push_events` | boolean | false | Enable notifications for push events |
### Delete Custom Issue Tracker service
@@ -1034,9 +1034,9 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `new_issue_url` | string | true | New Issue url |
-| `project_url` | string | true | Project url |
-| `issues_url` | string | true | Issue url |
+| `new_issue_url` | string | true | New Issue URL |
+| `project_url` | string | true | Project URL |
+| `issues_url` | string | true | Issue URL |
| `description` | string | false | Description |
| `push_events` | boolean | false | Enable notifications for push events |
@@ -1385,8 +1385,8 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `issues_url` | string | true | Issue url |
-| `project_url` | string | true | Project url |
+| `issues_url` | string | true | Issue URL |
+| `project_url` | string | true | Project URL |
| `description` | string | false | Description |
| `push_events` | boolean | false | Enable notifications for push events |
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 5e432c11b3d..53166c5cf63 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -240,7 +240,7 @@ are listed in the descriptions of the relevant settings.
| `elasticsearch_namespace_ids` | array of integers | no | **(PREMIUM)** The namespaces to index via Elasticsearch if `elasticsearch_limit_indexing` is enabled. |
| `elasticsearch_project_ids` | array of integers | no | **(PREMIUM)** The projects to index via Elasticsearch if `elasticsearch_limit_indexing` is enabled. |
| `elasticsearch_search` | boolean | no | **(PREMIUM)** Enable Elasticsearch search |
-| `elasticsearch_url` | string | no | **(PREMIUM)** The url to use for connecting to Elasticsearch. Use a comma-separated list to support cluster (for example, `http://localhost:9200, http://localhost:9201"`). If your Elasticsearch instance is password protected, pass the `username:password` in the URL (for example, `http://<username>:<password>@<elastic_host>:9200/`). |
+| `elasticsearch_url` | string | no | **(PREMIUM)** The URL to use for connecting to Elasticsearch. Use a comma-separated list to support cluster (for example, `http://localhost:9200, http://localhost:9201"`). If your Elasticsearch instance is password protected, pass the `username:password` in the URL (for example, `http://<username>:<password>@<elastic_host>:9200/`). |
| `email_additional_text` | string | no | **(PREMIUM)** Additional text added to the bottom of every email for legal/auditing/compliance reasons |
| `email_author_in_body` | boolean | no | Some email servers do not support overriding the email sender name. Enable this option to include the name of the author of the issue, merge request or comment in the email body instead. |
| `enabled_git_access_protocol` | string | no | Enabled protocols for Git access. Allowed values are: `ssh`, `http`, and `nil` to allow both protocols. |
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index 48135c14b9b..cb9b76f6e5e 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -374,13 +374,13 @@ Once you've picked a new Go version to use, the steps to update Omnibus and CNG
are:
- [Create a merge request in the CNG project](https://gitlab.com/gitlab-org/build/CNG/edit/master/ci_files/variables.yml?branch_name=update-go-version),
- updating the `GO_VERSION` in `ci_files/variables.yml`.
+ updating the `GO_VERSION` in `ci_files/variables.yml`.
- Create a merge request in the [`gitlab-omnibus-builder` project](https://gitlab.com/gitlab-org/gitlab-omnibus-builder),
- updating every file in the `docker/` directory so the `GO_VERSION` is set
- appropriately. [Here's an example](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/125/diffs).
+ updating every file in the `docker/` directory so the `GO_VERSION` is set
+ appropriately. [Here's an example](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/125/diffs).
- Tag a new release of `gitlab-omnibus-builder` containing the change.
-- [Create a merge request in the `gitlab-omnibus` project](https://gitlab.com/gitlab-org/omnibus-gitlab/edit/master/.gitlab-ci.yml?branch_name=update-gitlab-omnibus-builder-version),
- updating the `BUILDER_IMAGE_REVISION` to match the newly-created tag.
+- [Create a merge request in the `omnibus-gitlab` project](https://gitlab.com/gitlab-org/omnibus-gitlab/edit/master/.gitlab-ci.yml?branch_name=update-gitlab-omnibus-builder-version),
+ updating the `BUILDER_IMAGE_REVISION` to match the newly-created tag.
To reduce unnecessary differences between two distribution methods, Omnibus and
CNG **should always use the same Go version**.
diff --git a/doc/development/packages.md b/doc/development/packages.md
index c6d874d6815..2d93343a7dd 100644
--- a/doc/development/packages.md
+++ b/doc/development/packages.md
@@ -110,7 +110,7 @@ The way new package systems are integrated in GitLab is using an [MVC](https://a
Required actions are all the additional requests that GitLab will need to handle so the corresponding package manager CLI can work properly. It could be a search feature or an endpoint providing meta information about a package. For example:
- For NuGet, the search request was implemented during the first MVC iteration, to support Visual Studio.
-- For NPM, there is a metadata endpoint used by `npm` to get the tarball url.
+- For NPM, there is a metadata endpoint used by `npm` to get the tarball URL.
For the first MVC iteration, it's recommended to stay at the project level of the [remote hierarchy](#remote-hierarchy). Other levels can be tackled with [future Merge Requests](#future-work).
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index 4d016048fb7..a956a054a8c 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -638,7 +638,7 @@ Karma allows something similar, but it's way more costly.
Running Karma with `yarn run karma-start` will compile the JavaScript
assets and run a server at `http://localhost:9876/` where it will automatically
-run the tests on any browser which connects to it. You can enter that url on
+run the tests on any browser which connects to it. You can enter that URL on
multiple browsers at once to have it run the tests on each in parallel.
While Karma is running, any changes you make will instantly trigger a recompile
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index 9eb5d5add8a..606f7c4d6b5 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -209,6 +209,31 @@ Leading indicators may be health check failures leading to restarts or majority
The [Review Apps Overview dashboard](https://app.google.stackdriver.com/dashboards/6798952013815386466?project=gitlab-review-apps&timeDomain=1d)
aids in identifying load spikes on the cluster, and if nodes are problematic or the entire cluster is trending towards unhealthy.
+### Release failed with `ImagePullBackOff`
+
+**Potential cause:**
+
+If you see an `ImagePullBackoff` status, check for a missing Docker image.
+
+**Where to look for further debugging:**
+
+To check that the Docker images were created, run the following Docker command:
+
+```shell
+`DOCKER_CLI_EXPERIMENTAL=enabled docker manifest repository:tag`
+```
+
+The output of this command indicates if the Docker image exists. For example:
+
+```shell
+DOCKER_CLI_EXPERIMENTAL=enabled docker manifest inspect registry.gitlab.com/gitlab-org/build/cng-mirror/gitlab-rails-ee:39467-allow-a-release-s-associated-milestones-to-be-edited-thro
+```
+
+If the Docker image does not exist:
+
+- Verify the `image.repository` and `image.tag` options in the `helm upgrade --install` command match the repository names used by CNG-mirror pipeline.
+- Look further in the corresponding downstream CNG-mirror pipeline in `review-build-cng` job.
+
### Node count is always increasing (i.e. never stabilizing or decreasing)
**Potential cause:**
diff --git a/doc/integration/jira_development_panel.md b/doc/integration/jira_development_panel.md
index 7753629c371..188eca6b6a9 100644
--- a/doc/integration/jira_development_panel.md
+++ b/doc/integration/jira_development_panel.md
@@ -164,7 +164,7 @@ Click the links to see your GitLab repository data.
## Limitations
-- This integration is currently not supported on GitLab instances under a [relative url](https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab) (for example, `http://example.com/gitlab`).
+- This integration is currently not supported on GitLab instances under a [relative URL](https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab) (for example, `http://example.com/gitlab`).
## Changelog
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index 674745cb50f..8f84f8b8e17 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -220,7 +220,7 @@ instance is being served on HTTP.
This behavior is caused by Git LFS using HTTPS connections by default when a
`lfsurl` is not set in the Git config.
-To prevent this from happening, set the lfs url in project Git config:
+To prevent this from happening, set the lfs URL in project Git config:
```shell
git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs"
@@ -265,7 +265,7 @@ If you are storing LFS files outside of GitLab you can disable LFS on the projec
### Hosting LFS objects externally
-It is possible to host LFS objects externally by setting a custom LFS url with `git config -f .lfsconfig lfs.url https://example.com/<project>.git/info/lfs`.
+It is possible to host LFS objects externally by setting a custom LFS URL with `git config -f .lfsconfig lfs.url https://example.com/<project>.git/info/lfs`.
You might choose to do this if you are using an appliance like a Sonatype Nexus to store LFS data. If you choose to use an external LFS store,
GitLab will not be able to verify LFS objects which means that pushes will fail if you have GitLab LFS support enabled.
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index f0e7bf272a7..5a578e743eb 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -103,7 +103,7 @@ Access the default page for admin area settings by navigating to
| Option | Description |
| ------ | ----------- |
| [Email](email.md) | Various email settings. |
-| [Help page](../../../customization/help_message.md) | Help page text and support page url. |
+| [Help page](../../../customization/help_message.md) | Help page text and support page URL. |
| [Pages](../../../administration/pages/index.md#custom-domain-verification) | Size and domain settings for static websites |
| [Real-time features](../../../administration/polling.md) | Change this value to influence how frequently the GitLab UI polls for updates. |
| [Gitaly timeouts](gitaly_timeouts.md) | Configure Gitaly timeouts. |
diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md
index d38637e2e9e..95748f68a55 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -38,7 +38,7 @@ In [GitLab Premium or higher](https://about.gitlab.com/pricing/), GitLab adminis
To do this:
-1. Uncheck the **Allow owners to manage default branch protection in groups** checkbox.
+1. Uncheck the **Allow owners to manage default branch protection per group** checkbox.
NOTE: **Note:**
GitLab administrators can still update the default branch protection of a group.
diff --git a/doc/user/project/clusters/serverless/aws.md b/doc/user/project/clusters/serverless/aws.md
index 3df57e3a7a5..50cc0ef8d8d 100644
--- a/doc/user/project/clusters/serverless/aws.md
+++ b/doc/user/project/clusters/serverless/aws.md
@@ -150,7 +150,7 @@ endpoints:
Running the following `curl` command should trigger your function.
NOTE: **Note:**
- Your url should be the one retrieved from the GitLab deploy stage log.
+Your URL should be the one retrieved from the GitLab deploy stage log.
```shell
curl https://u768nzby1j.execute-api.us-east-1.amazonaws.com/production/hello
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index 6b8ec3c4abd..0e18b678133 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -93,7 +93,7 @@ Integration with Prometheus requires the following:
#### Getting started
-Installing and configuring Prometheus to monitor applications is fairly straight forward.
+Installing and configuring Prometheus to monitor applications is fairly straightforward.
1. [Install Prometheus](https://prometheus.io/docs/prometheus/latest/installation/)
1. Set up one of the [supported monitoring targets](prometheus_library/index.md)
@@ -146,7 +146,7 @@ one of them will be used:
Once configured, GitLab will attempt to retrieve performance metrics for any
environment which has had a successful deployment.
-GitLab will automatically scan the Prometheus server for metrics from known servers like Kubernetes and NGINX, and attempt to identify individual environment. The supported metrics and scan process is detailed in our [Prometheus Metrics Library documentation](prometheus_library/index.md).
+GitLab will automatically scan the Prometheus server for metrics from known servers like Kubernetes and NGINX, and attempt to identify individual environments. The supported metrics and scan process is detailed in our [Prometheus Metrics Library documentation](prometheus_library/index.md).
You can view the performance dashboard for an environment by [clicking on the monitoring button](../../../ci/environments.md#monitoring-environments).
@@ -170,7 +170,7 @@ A few fields are required:
- **Y-axis label**: Y axis title to display on the dashboard.
- **Unit label**: Query units, for example `req / sec`. Shown next to the value.
-Multiple metrics can be displayed on the same chart if the fields **Name**, **Type**, and **Y-axis label** match between metrics. For example, a metric with **Name** `Requests Rate`, **Type** `Business`, and **Y-axis label** `rec / sec` would display on the same chart as a second metric with the same values. A **Legend label** is suggested if this feature used.
+Multiple metrics can be displayed on the same chart if the fields **Name**, **Type**, and **Y-axis label** match between metrics. For example, a metric with **Name** `Requests Rate`, **Type** `Business`, and **Y-axis label** `rec / sec` would display on the same chart as a second metric with the same values. A **Legend label** is suggested if this feature is used.
#### Query Variables
@@ -279,7 +279,7 @@ If you select another branch, this branch should be merged to your **default** b
Dashboards have several components:
-- Panel groups, which comprise of panels.
+- Panel groups, which consist of panels.
- Panels, which support one or more metrics.
The following tables outline the details of expected properties.
@@ -633,7 +633,7 @@ Note the following properties:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/34779) in GitLab 12.5.
When viewing a custom dashboard of a project, you can view the original
-`.yml` file by clicking on **Edit dashboard** button.
+`.yml` file by clicking on the **Edit dashboard** button.
### Chart Context Menu
@@ -733,7 +733,7 @@ In order for GitLab to associate your alerts with an [environment](../../../ci/e
>- [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/4925) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.11.
>- [From GitLab Ultimate 12.5](https://gitlab.com/gitlab-org/gitlab/issues/13401), when GitLab receives a recovery alert, it will automatically close the associated issue.
-Alerts can be used to trigger actions, like open an issue automatically (enabled by default since `12.1`). To configure the actions:
+Alerts can be used to trigger actions, like opening an issue automatically (enabled by default since `12.1`). To configure the actions:
1. Navigate to your project's **Settings > Operations > Incidents**.
1. Enable the option to create issues.
@@ -752,7 +752,7 @@ Once enabled, an issue will be opened automatically when an alert is triggered w
- Optional list of attached annotations extracted from `annotations/*`
- Alert [GFM](../../markdown.md): GitLab Flavored Markdown from `annotations/gitlab_incident_markdown`
-When GitLab receives a **Recovery Alert**, it will automatically close the associated issue. This action will be recorded as a system message on the issue indicated that it was closed automatically by the GitLab Alert bot.
+When GitLab receives a **Recovery Alert**, it will automatically close the associated issue. This action will be recorded as a system message on the issue indicating that it was closed automatically by the GitLab Alert bot.
To further customize the issue, you can add labels, mentions, or any other supported [quick action](../quick_actions.md) in the selected issue template, which will apply to all incidents. To limit quick actions or other information to only specific types of alerts, use the `annotations/gitlab_incident_markdown` field.
@@ -925,7 +925,7 @@ Prerequisites for embedding from a Grafana instance:
1. In the upper-left corner of the page, select a specific value for each variable required for the queries in the chart.
![Select Query Variables](img/select_query_variables_v12_5.png)
1. In Grafana, click on a panel's title, then click **Share** to open the panel's sharing dialog to the **Link** tab. If you click the _dashboard's_ share panel instead, GitLab will attempt to embed the first supported panel on the dashboard (if available).
-1. If your Prometheus queries use Grafana's custom template variables, ensure that "Template variables" option is toggled to **On**. Of Grafana global template variables, only `$__interval`, `$__from`, and `$__to` are currently supported. Toggle **On** the "Current time range" option to specify the time range of the chart. Otherwise, the default range will be the last 8 hours.
+1. If your Prometheus queries use Grafana's custom template variables, ensure that the "Template variables" option is toggled to **On**. Of Grafana global template variables, only `$__interval`, `$__from`, and `$__to` are currently supported. Toggle **On** the "Current time range" option to specify the time range of the chart. Otherwise, the default range will be the last 8 hours.
![Grafana Sharing Dialog](img/grafana_sharing_dialog_v12_5.png)
1. Click **Copy** to copy the URL to the clipboard.
1. In GitLab, paste the URL into a Markdown field and save. The chart will take a few moments to render.
diff --git a/lib/gitlab/jira_import/base_importer.rb b/lib/gitlab/jira_import/base_importer.rb
index 5381812186d..306736df30f 100644
--- a/lib/gitlab/jira_import/base_importer.rb
+++ b/lib/gitlab/jira_import/base_importer.rb
@@ -3,12 +3,13 @@
module Gitlab
module JiraImport
class BaseImporter
- attr_reader :project, :client, :formatter, :jira_project_key
+ attr_reader :project, :client, :formatter, :jira_project_key, :running_import
def initialize(project)
project.validate_jira_import_settings!
- @jira_project_key = project.latest_jira_import&.jira_project_key
+ @running_import = project.latest_jira_import
+ @jira_project_key = running_import&.jira_project_key
raise Projects::ImportService::Error, _('Unable to find Jira project to import data from.') unless @jira_project_key
diff --git a/lib/gitlab/jira_import/issue_serializer.rb b/lib/gitlab/jira_import/issue_serializer.rb
index 244c9fd637d..9bbee901b14 100644
--- a/lib/gitlab/jira_import/issue_serializer.rb
+++ b/lib/gitlab/jira_import/issue_serializer.rb
@@ -3,11 +3,12 @@
module Gitlab
module JiraImport
class IssueSerializer
- attr_reader :jira_issue, :project, :params, :formatter
+ attr_reader :jira_issue, :project, :import_owner_id, :params, :formatter
- def initialize(project, jira_issue, params = {})
+ def initialize(project, jira_issue, import_owner_id, params = {})
@jira_issue = jira_issue
@project = project
+ @import_owner_id = import_owner_id
@params = params
@formatter = Gitlab::ImportFormatter.new
end
@@ -71,7 +72,7 @@ module Gitlab
end
def reporter
- map_user_id(jira_issue&.reporter&.emailAddress) || project.creator_id
+ map_user_id(jira_issue&.reporter&.emailAddress) || import_owner_id
end
def assignees
diff --git a/lib/gitlab/jira_import/issues_importer.rb b/lib/gitlab/jira_import/issues_importer.rb
index 6543b633ddf..8c18e58d9df 100644
--- a/lib/gitlab/jira_import/issues_importer.rb
+++ b/lib/gitlab/jira_import/issues_importer.rb
@@ -57,7 +57,7 @@ module Gitlab
# For such cases we exit early if issue was already imported.
next if already_imported?(jira_issue.id)
- issue_attrs = IssueSerializer.new(project, jira_issue, { iid: next_iid }).execute
+ issue_attrs = IssueSerializer.new(project, jira_issue, running_import.user_id, { iid: next_iid }).execute
Gitlab::JiraImport::ImportIssueWorker.perform_async(project.id, jira_issue.id, issue_attrs, job_waiter.key)
job_waiter.jobs_remaining += 1
diff --git a/lib/gitlab_danger.rb b/lib/gitlab_danger.rb
index ee0951f18ca..ebfeb2671e2 100644
--- a/lib/gitlab_danger.rb
+++ b/lib/gitlab_danger.rb
@@ -12,6 +12,7 @@ class GitlabDanger
database
commit_messages
telemetry
+ utility_css
].freeze
CI_ONLY_RULES ||= %w[
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 601ff6d9ace..aa22bea0367 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -3357,6 +3357,9 @@ msgstr ""
msgid "Buy GitLab Enterprise Edition"
msgstr ""
+msgid "Buy more Pipeline minutes"
+msgstr ""
+
msgid "By %{user_name}"
msgstr ""
@@ -4152,9 +4155,6 @@ msgstr ""
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
-msgid "Click here"
-msgstr ""
-
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
msgstr ""
@@ -14923,15 +14923,6 @@ msgstr ""
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
-msgid "Pipelines| to purchase more minutes."
-msgstr ""
-
-msgid "Pipelines|%{namespace_name} has exceeded its pipeline minutes quota."
-msgstr ""
-
-msgid "Pipelines|%{namespace_name} has less than %{notification_level}%% of CI minutes available."
-msgstr ""
-
msgid "Pipelines|API"
msgstr ""
@@ -14953,10 +14944,13 @@ msgstr ""
msgid "Pipelines|Get started with Pipelines"
msgstr ""
-msgid "Pipelines|Loading Pipelines"
+msgid "Pipelines|Group %{namespace_name} has %{percentage}%% or less Shared Runner Pipeline minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "Pipelines|Group %{namespace_name} has exceeded its pipeline minutes quota. Unless you buy additional pipeline minutes, no new jobs or pipelines in its projects will run."
msgstr ""
-msgid "Pipelines|Pipelines will not run anymore on shared Runners."
+msgid "Pipelines|Loading Pipelines"
msgstr ""
msgid "Pipelines|Project cache successfully reset."
@@ -24096,6 +24090,9 @@ msgstr ""
msgid "You have declined the invitation to join %{label}."
msgstr ""
+msgid "You have imported from this project %{numberOfPreviousImportsForProject} times before. Each new import will create duplicate issues."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
diff --git a/package.json b/package.json
index 93b9fd5d141..f74e9e32f71 100644
--- a/package.json
+++ b/package.json
@@ -147,7 +147,7 @@
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.8.3",
- "@gitlab/eslint-plugin": "2.2.1",
+ "@gitlab/eslint-plugin": "3.0.0",
"@vue/test-utils": "^1.0.0-beta.30",
"axios-mock-adapter": "^1.15.0",
"babel-jest": "^24.1.0",
diff --git a/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js b/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
index a25aba61516..ff780939026 100644
--- a/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
@@ -7,27 +7,32 @@ import { file } from '../../helpers';
const localVue = createLocalVue();
localVue.use(Vuex);
+const TEST_FILE_PATH = 'test/file/path';
+
describe('IDE commit editor header', () => {
let wrapper;
- let f;
let store;
- const findDiscardModal = () => wrapper.find({ ref: 'discardModal' });
- const findDiscardButton = () => wrapper.find({ ref: 'discardButton' });
-
- beforeEach(() => {
- f = file('file');
- store = createStore();
-
+ const createComponent = (fileProps = {}) => {
wrapper = mount(EditorHeader, {
store,
localVue,
propsData: {
- activeFile: f,
+ activeFile: {
+ ...file(TEST_FILE_PATH),
+ staged: true,
+ ...fileProps,
+ },
},
});
+ };
- jest.spyOn(wrapper.vm, 'discardChanges').mockImplementation();
+ const findDiscardModal = () => wrapper.find({ ref: 'discardModal' });
+ const findDiscardButton = () => wrapper.find({ ref: 'discardButton' });
+
+ beforeEach(() => {
+ store = createStore();
+ jest.spyOn(store, 'dispatch').mockImplementation();
});
afterEach(() => {
@@ -35,29 +40,38 @@ describe('IDE commit editor header', () => {
wrapper = null;
});
- it('renders button to discard', () => {
- expect(wrapper.vm.$el.querySelectorAll('.btn')).toHaveLength(1);
+ it.each`
+ fileProps | shouldExist
+ ${{ staged: false, changed: false }} | ${false}
+ ${{ staged: true, changed: false }} | ${true}
+ ${{ staged: false, changed: true }} | ${true}
+ ${{ staged: true, changed: true }} | ${true}
+ `('with $fileProps, show discard button is $shouldExist', ({ fileProps, shouldExist }) => {
+ createComponent(fileProps);
+
+ expect(findDiscardButton().exists()).toBe(shouldExist);
});
describe('discard button', () => {
- let modal;
-
beforeEach(() => {
- modal = findDiscardModal();
+ createComponent();
+ const modal = findDiscardModal();
jest.spyOn(modal.vm, 'show');
findDiscardButton().trigger('click');
});
it('opens a dialog confirming discard', () => {
- expect(modal.vm.show).toHaveBeenCalled();
+ expect(findDiscardModal().vm.show).toHaveBeenCalled();
});
it('calls discardFileChanges if dialog result is confirmed', () => {
- modal.vm.$emit('ok');
+ expect(store.dispatch).not.toHaveBeenCalled();
+
+ findDiscardModal().vm.$emit('ok');
- expect(wrapper.vm.discardChanges).toHaveBeenCalledWith(f.path);
+ expect(store.dispatch).toHaveBeenCalledWith('discardFileChanges', TEST_FILE_PATH);
});
});
});
diff --git a/spec/frontend/jira_import/components/jira_import_app_spec.js b/spec/frontend/jira_import/components/jira_import_app_spec.js
index 70713ca3cd7..0040e71c192 100644
--- a/spec/frontend/jira_import/components/jira_import_app_spec.js
+++ b/spec/frontend/jira_import/components/jira_import_app_spec.js
@@ -1,5 +1,5 @@
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import JiraImportApp from '~/jira_import/components/jira_import_app.vue';
import JiraImportForm from '~/jira_import/components/jira_import_form.vue';
@@ -11,12 +11,16 @@ import { IMPORT_STATE } from '~/jira_import/utils';
const mountComponent = ({
isJiraConfigured = true,
errorMessage = '',
- showAlert = true,
+ selectedProject = 'MTG',
+ showAlert = false,
status = IMPORT_STATE.NONE,
loading = false,
mutate = jest.fn(() => Promise.resolve()),
-} = {}) =>
- shallowMount(JiraImportApp, {
+ mountType,
+} = {}) => {
+ const mountFunction = mountType === 'mount' ? mount : shallowMount;
+
+ return mountFunction(JiraImportApp, {
propsData: {
isJiraConfigured,
inProgressIllustration: 'in-progress-illustration.svg',
@@ -34,15 +38,32 @@ const mountComponent = ({
return {
errorMessage,
showAlert,
+ selectedProject,
jiraImportDetails: {
status,
- import: {
- jiraProjectKey: 'MTG',
- scheduledAt: '2020-04-08T12:17:25+00:00',
- scheduledBy: {
- name: 'Jane Doe',
+ imports: [
+ {
+ jiraProjectKey: 'MTG',
+ scheduledAt: '2020-04-08T10:11:12+00:00',
+ scheduledBy: {
+ name: 'John Doe',
+ },
},
- },
+ {
+ jiraProjectKey: 'MSJP',
+ scheduledAt: '2020-04-09T13:14:15+00:00',
+ scheduledBy: {
+ name: 'Jimmy Doe',
+ },
+ },
+ {
+ jiraProjectKey: 'MTG',
+ scheduledAt: '2020-04-09T16:17:18+00:00',
+ scheduledBy: {
+ name: 'Jane Doe',
+ },
+ },
+ ],
},
};
},
@@ -53,6 +74,7 @@ const mountComponent = ({
},
},
});
+};
describe('JiraImportApp', () => {
let wrapper;
@@ -160,6 +182,64 @@ describe('JiraImportApp', () => {
});
});
+ describe('import in progress screen', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({ status: IMPORT_STATE.SCHEDULED });
+ });
+
+ it('shows the illustration', () => {
+ expect(getProgressComponent().props('illustration')).toBe('in-progress-illustration.svg');
+ });
+
+ it('shows the name of the most recent import initiator', () => {
+ expect(getProgressComponent().props('importInitiator')).toBe('Jane Doe');
+ });
+
+ it('shows the name of the most recent imported project', () => {
+ expect(getProgressComponent().props('importProject')).toBe('MTG');
+ });
+
+ it('shows the time of the most recent import', () => {
+ expect(getProgressComponent().props('importTime')).toBe('2020-04-09T16:17:18+00:00');
+ });
+
+ it('has the path to the issues page', () => {
+ expect(getProgressComponent().props('issuesPath')).toBe('gitlab-org/gitlab-test/-/issues');
+ });
+ });
+
+ describe('jira import form screen', () => {
+ describe('when selected project has been imported before', () => {
+ it('shows jira-import::MTG-3 label since project MTG has been imported 2 time before', () => {
+ wrapper = mountComponent();
+
+ expect(getFormComponent().props('importLabel')).toBe('jira-import::MTG-3');
+ });
+
+ it('shows warning alert to explain project MTG has been imported 2 times before', () => {
+ wrapper = mountComponent({ mountType: 'mount' });
+
+ expect(getAlert().text()).toBe(
+ 'You have imported from this project 2 times before. Each new import will create duplicate issues.',
+ );
+ });
+ });
+
+ describe('when selected project has not been imported before', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({ selectedProject: 'MJP' });
+ });
+
+ it('shows jira-import::MJP-1 label since project MJP has not been imported before', () => {
+ expect(getFormComponent().props('importLabel')).toBe('jira-import::MJP-1');
+ });
+
+ it('does not show warning alert since project MJP has not been imported before', () => {
+ expect(getAlert().exists()).toBe(false);
+ });
+ });
+ });
+
describe('initiating a Jira import', () => {
it('calls the mutation with the expected arguments', () => {
const mutate = jest.fn(() => Promise.resolve());
@@ -201,6 +281,7 @@ describe('JiraImportApp', () => {
wrapper = mountComponent({
errorMessage: 'There was an error importing the Jira project.',
showAlert: true,
+ selectedProject: null,
});
expect(getAlert().exists()).toBe(true);
diff --git a/spec/frontend/jira_import/components/jira_import_form_spec.js b/spec/frontend/jira_import/components/jira_import_form_spec.js
index 0987eb11693..dea94e7bf1f 100644
--- a/spec/frontend/jira_import/components/jira_import_form_spec.js
+++ b/spec/frontend/jira_import/components/jira_import_form_spec.js
@@ -2,11 +2,15 @@ import { GlAvatar, GlButton, GlFormSelect, GlLabel } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import JiraImportForm from '~/jira_import/components/jira_import_form.vue';
+const importLabel = 'jira-import::MTG-1';
+const value = 'MTG';
+
const mountComponent = ({ mountType } = {}) => {
const mountFunction = mountType === 'mount' ? mount : shallowMount;
return mountFunction(JiraImportForm, {
propsData: {
+ importLabel,
issuesPath: 'gitlab-org/gitlab-test/-/issues',
jiraProjects: [
{
@@ -22,6 +26,7 @@ const mountComponent = ({ mountType } = {}) => {
value: 'MTG',
},
],
+ value,
},
});
};
@@ -29,6 +34,8 @@ const mountComponent = ({ mountType } = {}) => {
describe('JiraImportForm', () => {
let wrapper;
+ const getSelectDropdown = () => wrapper.find(GlFormSelect);
+
const getCancelButton = () => wrapper.findAll(GlButton).at(1);
afterEach(() => {
@@ -40,7 +47,7 @@ describe('JiraImportForm', () => {
it('is shown', () => {
wrapper = mountComponent();
- expect(wrapper.find(GlFormSelect).exists()).toBe(true);
+ expect(wrapper.contains(GlFormSelect)).toBe(true);
});
it('contains a list of Jira projects to select from', () => {
@@ -48,8 +55,7 @@ describe('JiraImportForm', () => {
const optionItems = ['My Jira Project', 'My Second Jira Project', 'Migrate to GitLab'];
- wrapper
- .find(GlFormSelect)
+ getSelectDropdown()
.findAll('option')
.wrappers.forEach((optionEl, index) => {
expect(optionEl.text()).toBe(optionItems[index]);
@@ -63,7 +69,7 @@ describe('JiraImportForm', () => {
});
it('shows a label which will be applied to imported Jira projects', () => {
- expect(wrapper.find(GlLabel).attributes('title')).toBe('jira-import::KEY-1');
+ expect(wrapper.find(GlLabel).props('title')).toBe(importLabel);
});
it('shows information to the user', () => {
@@ -77,7 +83,7 @@ describe('JiraImportForm', () => {
});
it('shows an avatar for the Reporter', () => {
- expect(wrapper.find(GlAvatar).exists()).toBe(true);
+ expect(wrapper.contains(GlAvatar)).toBe(true);
});
it('shows jira.issue.description.content for the Description', () => {
@@ -111,16 +117,19 @@ describe('JiraImportForm', () => {
});
});
- it('emits an "initiateJiraImport" event with the selected dropdown value when submitted', () => {
- const selectedOption = 'MTG';
+ it('emits an "input" event when the input select value changes', () => {
+ wrapper = mountComponent({ mountType: 'mount' });
+
+ getSelectDropdown().vm.$emit('change', value);
+ expect(wrapper.emitted('input')[0]).toEqual([value]);
+ });
+
+ it('emits an "initiateJiraImport" event with the selected dropdown value when submitted', () => {
wrapper = mountComponent();
- wrapper.setData({
- selectedOption,
- });
wrapper.find('form').trigger('submit');
- expect(wrapper.emitted('initiateJiraImport')[0]).toEqual([selectedOption]);
+ expect(wrapper.emitted('initiateJiraImport')[0]).toEqual([value]);
});
});
diff --git a/spec/frontend/jira_import/components/jira_import_progress_spec.js b/spec/frontend/jira_import/components/jira_import_progress_spec.js
index ace497295c0..3ccf14554e1 100644
--- a/spec/frontend/jira_import/components/jira_import_progress_spec.js
+++ b/spec/frontend/jira_import/components/jira_import_progress_spec.js
@@ -9,7 +9,7 @@ const issuesPath = 'gitlab-org/gitlab-test/-/issues';
describe('JiraImportProgress', () => {
let wrapper;
- const getGlEmptyStateAttribute = attribute => wrapper.find(GlEmptyState).attributes(attribute);
+ const getGlEmptyStateProp = attribute => wrapper.find(GlEmptyState).props(attribute);
const getParagraphText = () => wrapper.find('p').text();
@@ -37,21 +37,21 @@ describe('JiraImportProgress', () => {
});
it('contains illustration', () => {
- expect(getGlEmptyStateAttribute('svgpath')).toBe(illustration);
+ expect(getGlEmptyStateProp('svgPath')).toBe(illustration);
});
it('contains a title', () => {
const title = 'Import in progress';
- expect(getGlEmptyStateAttribute('title')).toBe(title);
+ expect(getGlEmptyStateProp('title')).toBe(title);
});
it('contains button text', () => {
- expect(getGlEmptyStateAttribute('primarybuttontext')).toBe('View issues');
+ expect(getGlEmptyStateProp('primaryButtonText')).toBe('View issues');
});
it('contains button url', () => {
const expected = `${issuesPath}?search=${importProject}`;
- expect(getGlEmptyStateAttribute('primarybuttonlink')).toBe(expected);
+ expect(getGlEmptyStateProp('primaryButtonLink')).toBe(expected);
});
});
diff --git a/spec/frontend/jira_import/components/jira_import_setup_spec.js b/spec/frontend/jira_import/components/jira_import_setup_spec.js
index 4c8cba70d8a..aa94dc4f503 100644
--- a/spec/frontend/jira_import/components/jira_import_setup_spec.js
+++ b/spec/frontend/jira_import/components/jira_import_setup_spec.js
@@ -8,7 +8,7 @@ const jiraIntegrationPath = 'gitlab-org/gitlab-test/-/services/jira/edit';
describe('JiraImportSetup', () => {
let wrapper;
- const getGlEmptyStateAttribute = attribute => wrapper.find(GlEmptyState).attributes(attribute);
+ const getGlEmptyStateProp = attribute => wrapper.find(GlEmptyState).props(attribute);
beforeEach(() => {
wrapper = shallowMount(JiraImportSetup, {
@@ -25,19 +25,19 @@ describe('JiraImportSetup', () => {
});
it('contains illustration', () => {
- expect(getGlEmptyStateAttribute('svgpath')).toBe(illustration);
+ expect(getGlEmptyStateProp('svgPath')).toBe(illustration);
});
it('contains a description', () => {
const description = 'You will first need to set up Jira Integration to use this feature.';
- expect(getGlEmptyStateAttribute('description')).toBe(description);
+ expect(getGlEmptyStateProp('description')).toBe(description);
});
it('contains button text', () => {
- expect(getGlEmptyStateAttribute('primarybuttontext')).toBe('Set up Jira Integration');
+ expect(getGlEmptyStateProp('primaryButtonText')).toBe('Set up Jira Integration');
});
it('contains button link', () => {
- expect(getGlEmptyStateAttribute('primarybuttonlink')).toBe(jiraIntegrationPath);
+ expect(getGlEmptyStateProp('primaryButtonLink')).toBe(jiraIntegrationPath);
});
});
diff --git a/spec/frontend/labels_select_spec.js b/spec/frontend/labels_select_spec.js
index 5f48bad4970..8b08eb9e124 100644
--- a/spec/frontend/labels_select_spec.js
+++ b/spec/frontend/labels_select_spec.js
@@ -45,7 +45,6 @@ describe('LabelsSelect', () => {
labels: mockLabels,
issueUpdateURL: mockUrl,
enableScopedLabels: true,
- scopedLabelsDocumentationLink: 'docs-link',
}),
);
});
@@ -71,10 +70,6 @@ describe('LabelsSelect', () => {
it('generated label item has a gl-label-text class', () => {
expect($labelEl.find('span').hasClass('gl-label-text')).toEqual(true);
});
-
- it('generated label item template does not have gl-label-icon class', () => {
- expect($labelEl.find('.gl-label-icon')).toHaveLength(0);
- });
});
describe('when scoped label is present', () => {
@@ -87,7 +82,6 @@ describe('LabelsSelect', () => {
labels: mockScopedLabels,
issueUpdateURL: mockUrl,
enableScopedLabels: true,
- scopedLabelsDocumentationLink: 'docs-link',
}),
);
});
@@ -106,14 +100,6 @@ describe('LabelsSelect', () => {
expect($labelEl.find('a').attr('data-html')).toBe('true');
});
- it('generated label item template has question icon', () => {
- expect($labelEl.find('i.fa-question-circle')).toHaveLength(1);
- });
-
- it('generated label item template has gl-label-icon class', () => {
- expect($labelEl.find('.gl-label-icon')).toHaveLength(1);
- });
-
it('generated label item template has correct label styles', () => {
expect($labelEl.find('span.gl-label-text').attr('style')).toBe(
`background-color: ${label.color}; color: ${label.text_color};`,
@@ -141,7 +127,6 @@ describe('LabelsSelect', () => {
labels: mockScopedLabels2,
issueUpdateURL: mockUrl,
enableScopedLabels: true,
- scopedLabelsDocumentationLink: 'docs-link',
}),
);
});
diff --git a/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap b/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap
index 620ed58bde4..2179e7b4ab5 100644
--- a/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap
+++ b/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap
@@ -13,7 +13,7 @@ exports[`AlertWidget Alert firing displays a warning icon and matches snapshot 1
/>
<span
- class="text-truncate gl-pl-1"
+ class="text-truncate gl-pl-1-deprecated-no-really-do-not-use-me"
>
Firing:
alert-label &gt; 42
@@ -35,7 +35,7 @@ exports[`AlertWidget Alert not firing displays a warning icon and matches snapsh
/>
<span
- class="text-truncate gl-pl-1"
+ class="text-truncate gl-pl-1-deprecated-no-really-do-not-use-me"
>
alert-label &gt; 42
</span>
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
index a863cddbaee..e50771385dc 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
@@ -38,7 +38,6 @@ export const mockConfig = {
labelsFetchPath: '/gitlab-org/my-project/-/labels.json',
labelsManagePath: '/gitlab-org/my-project/-/labels',
labelsFilterBasePath: '/gitlab-org/my-project/issues',
- scopedLabelsDocumentationPath: '/help/user/project/labels.md#scoped-labels-premium',
};
export const mockSuggestedColors = {
diff --git a/spec/initializers/action_mailer_hooks_spec.rb b/spec/initializers/action_mailer_hooks_spec.rb
index 20f96f7e16c..03eee09f737 100644
--- a/spec/initializers/action_mailer_hooks_spec.rb
+++ b/spec/initializers/action_mailer_hooks_spec.rb
@@ -6,6 +6,10 @@ describe 'ActionMailer hooks' do
describe 'smime signature interceptor' do
before do
class_spy(ActionMailer::Base).as_stubbed_const
+
+ # rspec-rails calls ActionMailer::Base.deliveries.clear after every test
+ # https://github.com/rspec/rspec-rails/commit/71c12388e2bad78aaeea6443a393ede78341a7a3
+ allow(ActionMailer::Base).to receive_message_chain(:deliveries, :clear)
end
it 'is disabled by default' do
diff --git a/spec/lib/gitlab/jira_import/issue_serializer_spec.rb b/spec/lib/gitlab/jira_import/issue_serializer_spec.rb
index f24a83994f7..592974bf344 100644
--- a/spec/lib/gitlab/jira_import/issue_serializer_spec.rb
+++ b/spec/lib/gitlab/jira_import/issue_serializer_spec.rb
@@ -9,6 +9,7 @@ describe Gitlab::JiraImport::IssueSerializer do
let_it_be(:project_label) { create(:label, project: project, title: 'bug') }
let_it_be(:other_project_label) { create(:label, project: project, title: 'feature') }
let_it_be(:group_label) { create(:group_label, group: group, title: 'dev') }
+ let_it_be(:current_user) { create(:user) }
let(:iid) { 5 }
let(:key) { 'PROJECT-5' }
@@ -51,7 +52,7 @@ describe Gitlab::JiraImport::IssueSerializer do
let(:params) { { iid: iid } }
- subject { described_class.new(project, jira_issue, params).execute }
+ subject { described_class.new(project, jira_issue, current_user.id, params).execute }
let(:expected_description) do
<<~MD
@@ -76,7 +77,7 @@ describe Gitlab::JiraImport::IssueSerializer do
state_id: 1,
updated_at: updated_at,
created_at: created_at,
- author_id: project.creator_id,
+ author_id: current_user.id,
assignee_ids: nil,
label_ids: [project_label.id, group_label.id] + Label.reorder(id: :asc).last(2).pluck(:id)
)
@@ -122,13 +123,13 @@ describe Gitlab::JiraImport::IssueSerializer do
let!(:user) { create(:user, email: 'reporter@example.com') }
it 'defaults the issue author to project creator' do
- expect(subject[:author_id]).to eq(project.creator.id)
+ expect(subject[:author_id]).to eq(current_user.id)
end
end
context 'when reporter does not map to a GitLab user' do
it 'defaults the issue author to project creator' do
- expect(subject[:author_id]).to eq(project.creator.id)
+ expect(subject[:author_id]).to eq(current_user.id)
end
end
@@ -136,7 +137,7 @@ describe Gitlab::JiraImport::IssueSerializer do
let(:reporter) { nil }
it 'defaults the issue author to project creator' do
- expect(subject[:author_id]).to eq(project.creator.id)
+ expect(subject[:author_id]).to eq(current_user.id)
end
end
@@ -144,7 +145,7 @@ describe Gitlab::JiraImport::IssueSerializer do
let(:reporter) { double(name: 'Reporter', emailAddress: nil) }
it 'defaults the issue author to project creator' do
- expect(subject[:author_id]).to eq(project.creator.id)
+ expect(subject[:author_id]).to eq(current_user.id)
end
end
end
diff --git a/spec/lib/gitlab/jira_import/issues_importer_spec.rb b/spec/lib/gitlab/jira_import/issues_importer_spec.rb
index a7cf19a9a5b..6cf06c20e19 100644
--- a/spec/lib/gitlab/jira_import/issues_importer_spec.rb
+++ b/spec/lib/gitlab/jira_import/issues_importer_spec.rb
@@ -6,8 +6,9 @@ describe Gitlab::JiraImport::IssuesImporter do
include JiraServiceHelper
let_it_be(:user) { create(:user) }
+ let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
- let_it_be(:jira_import) { create(:jira_import_state, project: project) }
+ let_it_be(:jira_import) { create(:jira_import_state, project: project, user: current_user) }
let_it_be(:jira_service) { create(:jira_service, project: project) }
subject { described_class.new(project) }
@@ -39,8 +40,16 @@ describe Gitlab::JiraImport::IssuesImporter do
context 'with results returned' do
JiraIssue = Struct.new(:id)
- let_it_be(:jira_issue1) { JiraIssue.new(1) }
- let_it_be(:jira_issue2) { JiraIssue.new(2) }
+ let_it_be(:jira_issues) { [JiraIssue.new(1), JiraIssue.new(2)] }
+
+ def mock_issue_serializer(count)
+ serializer = instance_double(Gitlab::JiraImport::IssueSerializer, execute: { key: 'data' })
+
+ count.times do |i|
+ expect(Gitlab::JiraImport::IssueSerializer).to receive(:new)
+ .with(project, jira_issues[i], current_user.id, { iid: i + 1 }).and_return(serializer)
+ end
+ end
context 'when single page of results is returned' do
before do
@@ -48,13 +57,11 @@ describe Gitlab::JiraImport::IssuesImporter do
end
it 'schedules 2 import jobs' do
- expect(subject).to receive(:fetch_issues).and_return([jira_issue1, jira_issue2])
+ expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issues[0], jira_issues[1]])
expect(Gitlab::JiraImport::ImportIssueWorker).to receive(:perform_async).twice
expect(Gitlab::Cache::Import::Caching).to receive(:set_add).twice.and_call_original
expect(Gitlab::Cache::Import::Caching).to receive(:set_includes?).twice.and_call_original
- allow_next_instance_of(Gitlab::JiraImport::IssueSerializer) do |instance|
- allow(instance).to receive(:execute).and_return({ key: 'data' })
- end
+ mock_issue_serializer(2)
job_waiter = subject.execute
@@ -69,13 +76,11 @@ describe Gitlab::JiraImport::IssuesImporter do
end
it 'schedules 3 import jobs' do
- expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issue1, jira_issue2])
+ expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issues[0], jira_issues[1]])
expect(Gitlab::JiraImport::ImportIssueWorker).to receive(:perform_async).twice.times
expect(Gitlab::Cache::Import::Caching).to receive(:set_add).twice.times.and_call_original
expect(Gitlab::Cache::Import::Caching).to receive(:set_includes?).twice.times.and_call_original
- allow_next_instance_of(Gitlab::JiraImport::IssueSerializer) do |instance|
- allow(instance).to receive(:execute).and_return({ key: 'data' })
- end
+ mock_issue_serializer(2)
job_waiter = subject.execute
@@ -90,13 +95,11 @@ describe Gitlab::JiraImport::IssuesImporter do
end
it 'schedules 2 import jobs' do
- expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issue1, jira_issue1])
+ expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issues[0], jira_issues[0]])
expect(Gitlab::JiraImport::ImportIssueWorker).to receive(:perform_async).once
expect(Gitlab::Cache::Import::Caching).to receive(:set_add).once.and_call_original
expect(Gitlab::Cache::Import::Caching).to receive(:set_includes?).twice.times.and_call_original
- allow_next_instance_of(Gitlab::JiraImport::IssueSerializer) do |instance|
- allow(instance).to receive(:execute).and_return({ key: 'data' })
- end
+ mock_issue_serializer(1)
job_waiter = subject.execute
diff --git a/spec/lib/gitlab_danger_spec.rb b/spec/lib/gitlab_danger_spec.rb
index f4620e54979..8115fbca5e0 100644
--- a/spec/lib/gitlab_danger_spec.rb
+++ b/spec/lib/gitlab_danger_spec.rb
@@ -9,7 +9,7 @@ describe GitlabDanger do
describe '.local_warning_message' do
it 'returns an informational message with rules that can run' do
- expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changes_size, documentation, frozen_string, duplicate_yarn_dependencies, prettier, eslint, karma, database, commit_messages, telemetry')
+ expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changes_size, documentation, frozen_string, duplicate_yarn_dependencies, prettier, eslint, karma, database, commit_messages, telemetry, utility_css')
end
end
diff --git a/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb b/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
index cbeb45b92ff..13448ea759b 100644
--- a/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
+++ b/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
@@ -2,6 +2,7 @@
require 'spec_helper'
require_relative 'shared_processing_service.rb'
+# require_relative 'shared_processing_service_tests_with_yaml.rb'
describe Ci::PipelineProcessing::AtomicProcessingService do
before do
@@ -9,6 +10,9 @@ describe Ci::PipelineProcessing::AtomicProcessingService do
end
it_behaves_like 'Pipeline Processing Service'
+ # TODO: This needs to be enabled. There is a different behavior when using `needs` depending on
+ # a `manual` job. More info: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29405#note_327520605
+ # it_behaves_like 'Pipeline Processing Service Tests With Yaml'
private
diff --git a/spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb b/spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb
index 09b462b7600..d4fb03cf643 100644
--- a/spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb
+++ b/spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb
@@ -2,13 +2,16 @@
require 'spec_helper'
require_relative 'shared_processing_service.rb'
+require_relative 'shared_processing_service_tests_with_yaml.rb'
describe Ci::PipelineProcessing::LegacyProcessingService do
before do
stub_feature_flags(ci_atomic_processing: false)
+ stub_feature_flags(ci_composite_status: false)
end
it_behaves_like 'Pipeline Processing Service'
+ it_behaves_like 'Pipeline Processing Service Tests With Yaml'
private
diff --git a/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb b/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
new file mode 100644
index 00000000000..ec3c10b3bb5
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+shared_context 'Pipeline Processing Service Tests With Yaml' do
+ where(:test_file_path) do
+ Dir.glob(Rails.root.join('spec/services/ci/pipeline_processing/test_cases/*.yml'))
+ end
+
+ with_them do
+ let(:test_file) { YAML.load_file(test_file_path) }
+
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:pipeline) { Ci::CreatePipelineService.new(project, user, ref: 'master').execute(:pipeline) }
+
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(test_file['config']))
+ stub_not_protect_default_branch
+ project.add_developer(user)
+ end
+
+ it 'follows transitions', :sidekiq_inline do
+ expect(pipeline).to be_persisted
+ check_expectation(test_file.dig('init', 'expect'))
+
+ test_file['transitions'].each do |transition|
+ event_on_jobs(transition['event'], transition['jobs'])
+ check_expectation(transition['expect'])
+ end
+ end
+
+ private
+
+ def check_expectation(expectation)
+ expectation.each do |key, value|
+ case key
+ when 'pipeline'
+ expect(pipeline.reload.status).to eq(value)
+ when 'stages'
+ expect(pipeline.stages.pluck(:name, :status).to_h).to eq(value)
+ when 'jobs'
+ expect(pipeline.builds.latest.pluck(:name, :status).to_h).to eq(value)
+ end
+ end
+ end
+
+ def event_on_jobs(event, job_names)
+ builds = pipeline.builds.latest.where(name: job_names).to_a
+ expect(builds.count).to eq(job_names.count) # ensure that we have the same counts
+
+ builds.each { |build| build.public_send("#{event}!") }
+ end
+ end
+end
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_allow_failure_test_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_allow_failure_test_on_failure.yml
new file mode 100644
index 00000000000..cfc456387ff
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_allow_failure_test_on_failure.yml
@@ -0,0 +1,47 @@
+config:
+ build:
+ stage: build
+ allow_failure: true
+ script: exit 1
+
+ test:
+ stage: test
+ when: on_failure
+ script: exit 0
+ needs: [build]
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ needs: [test]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: success
+ stages:
+ build: success
+ test: skipped
+ deploy: skipped
+ jobs:
+ build: failed
+ test: skipped
+ deploy: skipped
+
+# TODO: What is the real expected behavior here?
+# Is `needs` keyword a requirement indicator or just a helper to build dependency tree?
+# How should it behave `when: on_failure` with `needs`?
+# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails.yml
new file mode 100644
index 00000000000..e71ef194c5f
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails.yml
@@ -0,0 +1,39 @@
+config:
+ build:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ script: exit 0
+ needs: [build]
+
+ deploy:
+ stage: deploy
+ script: exit 0
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: failed
+ stages:
+ build: failed
+ test: skipped
+ deploy: skipped
+ jobs:
+ build: failed
+ test: skipped
+ deploy: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test.yml
new file mode 100644
index 00000000000..40a80f6f53b
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test.yml
@@ -0,0 +1,39 @@
+config:
+ build:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ needs: [test]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: failed
+ stages:
+ build: failed
+ test: skipped
+ deploy: skipped
+ jobs:
+ build: failed
+ test: skipped
+ deploy: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test_when_always.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test_when_always.yml
new file mode 100644
index 00000000000..b0904a027f8
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_deploy_needs_test_when_always.yml
@@ -0,0 +1,43 @@
+config:
+ build:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ when: always
+ needs: [test]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: running
+ stages:
+ build: failed
+ test: skipped
+ deploy: pending
+ jobs:
+ build: failed
+ test: skipped
+ deploy: pending
+
+# TODO: `test` is actually skipped, but we run `deploy`. Should we?
+# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds.yml
new file mode 100644
index 00000000000..a133023b12d
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds.yml
@@ -0,0 +1,62 @@
+config:
+ build_1:
+ stage: build
+ script: exit 0
+
+ build_2:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ needs: [build_1, test]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build_1: pending
+ build_2: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: success
+ jobs: [build_1]
+ expect:
+ pipeline: running
+ stages:
+ build: running
+ test: created
+ deploy: created
+ jobs:
+ build_1: success
+ build_2: pending
+ test: created
+ deploy: created
+
+ - event: drop
+ jobs: [build_2]
+ expect:
+ pipeline: running
+ stages:
+ build: failed
+ test: skipped
+ deploy: pending
+ jobs:
+ build_1: success
+ build_2: failed
+ test: skipped
+ deploy: pending
+
+# TODO: should we run deploy?
+# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_always.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_always.yml
new file mode 100644
index 00000000000..4c676761e5c
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_always.yml
@@ -0,0 +1,63 @@
+config:
+ build_1:
+ stage: build
+ script: exit 0
+
+ build_2:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ when: always
+ needs: [build_1, test]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build_1: pending
+ build_2: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: success
+ jobs: [build_1]
+ expect:
+ pipeline: running
+ stages:
+ build: running
+ test: created
+ deploy: created
+ jobs:
+ build_1: success
+ build_2: pending
+ test: created
+ deploy: created
+
+ - event: drop
+ jobs: [build_2]
+ expect:
+ pipeline: running
+ stages:
+ build: failed
+ test: skipped
+ deploy: pending
+ jobs:
+ build_1: success
+ build_2: failed
+ test: skipped
+ deploy: pending
+
+# TODO: what's the actual expected behavior here?
+# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_allow_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_allow_failure.yml
new file mode 100644
index 00000000000..ea7046262c3
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_allow_failure.yml
@@ -0,0 +1,40 @@
+config:
+ build:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ allow_failure: true
+ script: exit 1
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ needs: [test]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: failed
+ stages:
+ build: failed
+ test: skipped
+ deploy: skipped
+ jobs:
+ build: failed
+ test: skipped
+ deploy: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_always.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_always.yml
new file mode 100644
index 00000000000..8860f565cc7
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_always.yml
@@ -0,0 +1,35 @@
+config:
+ build:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ when: always
+ script: exit 0
+ needs: [build]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ jobs:
+ build: pending
+ test: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: running
+ stages:
+ build: failed
+ test: pending
+ jobs:
+ build: failed
+ test: pending
+
+# TODO: Should we run `test`?
+# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_on_failure.yml
new file mode 100644
index 00000000000..3fa5a8034a2
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_test_on_failure.yml
@@ -0,0 +1,35 @@
+config:
+ build:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ when: on_failure
+ script: exit 0
+ needs: [build]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ jobs:
+ build: pending
+ test: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: running
+ stages:
+ build: failed
+ test: pending
+ jobs:
+ build: failed
+ test: pending
+
+# TODO: Should we run `test`?
+# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_succeeds_test_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_succeeds_test_on_failure.yml
new file mode 100644
index 00000000000..700d4440802
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_succeeds_test_on_failure.yml
@@ -0,0 +1,35 @@
+config:
+ build:
+ stage: build
+ script: exit 0
+
+ test:
+ stage: test
+ when: on_failure
+ script: exit 0
+ needs: [build]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ jobs:
+ build: pending
+ test: created
+
+transitions:
+ - event: success
+ jobs: [build]
+ expect:
+ pipeline: success
+ stages:
+ build: success
+ test: skipped
+ jobs:
+ build: success
+ test: skipped
+
+# TODO: Should we run `test`?
+# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure.yml
new file mode 100644
index 00000000000..f324525bd56
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure.yml
@@ -0,0 +1,63 @@
+config:
+ build_1:
+ stage: build
+ script: exit 0
+
+ build_2:
+ stage: build
+ script: exit 0
+
+ test:
+ stage: test
+ script: exit 0
+ when: on_failure
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ needs: [build_1, test]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build_1: pending
+ build_2: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: success
+ jobs: [build_1, build_2]
+ expect:
+ pipeline: running
+ stages:
+ build: success
+ test: skipped
+ deploy: pending
+ jobs:
+ build_1: success
+ build_2: success
+ test: skipped
+ deploy: pending
+
+ - event: success
+ jobs: [deploy]
+ expect:
+ pipeline: success
+ stages:
+ build: success
+ test: skipped
+ deploy: success
+ jobs:
+ build_1: success
+ build_2: success
+ test: skipped
+ deploy: success
+
+# TODO: should we run deploy?
+# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_always.yml b/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_always.yml
new file mode 100644
index 00000000000..9986dbaa215
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_always.yml
@@ -0,0 +1,64 @@
+config:
+ build_1:
+ stage: build
+ script: exit 0
+
+ build_2:
+ stage: build
+ script: exit 0
+
+ test:
+ stage: test
+ script: exit 0
+ when: on_failure
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ when: always
+ needs: [build_1, test]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build_1: pending
+ build_2: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: success
+ jobs: [build_1, build_2]
+ expect:
+ pipeline: running
+ stages:
+ build: success
+ test: skipped
+ deploy: pending
+ jobs:
+ build_1: success
+ build_2: success
+ test: skipped
+ deploy: pending
+
+ - event: success
+ jobs: [deploy]
+ expect:
+ pipeline: success
+ stages:
+ build: success
+ test: skipped
+ deploy: success
+ jobs:
+ build_1: success
+ build_2: success
+ test: skipped
+ deploy: success
+
+# TODO: should we run deploy?
+# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_allow_failure_true.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_allow_failure_true.yml
new file mode 100644
index 00000000000..8d4d9d403f1
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_allow_failure_true.yml
@@ -0,0 +1,43 @@
+config:
+ test:
+ stage: test
+ allow_failure: true
+ script: exit 1
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ needs: [test]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ test: pending
+ deploy: created
+ jobs:
+ test: pending
+ deploy: created
+
+transitions:
+ - event: drop
+ jobs: [test]
+ expect:
+ pipeline: pending
+ stages:
+ test: success
+ deploy: pending
+ jobs:
+ test: failed
+ deploy: pending
+
+ - event: success
+ jobs: [deploy]
+ expect:
+ pipeline: success
+ stages:
+ test: success
+ deploy: success
+ jobs:
+ test: failed
+ deploy: success
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml
new file mode 100644
index 00000000000..1a1412f2a11
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml
@@ -0,0 +1,66 @@
+config:
+ test:
+ stage: test
+ when: manual
+ allow_failure: false
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ needs: [test]
+
+init:
+ expect:
+ pipeline: manual
+ stages:
+ test: manual
+ deploy: created
+ jobs:
+ test: manual
+ deploy: created
+
+transitions:
+ - event: enqueue
+ jobs: [test]
+ expect:
+ pipeline: manual
+ stages:
+ test: manual
+ deploy: created
+ jobs:
+ test: pending
+ deploy: created
+
+ - event: run
+ jobs: [test]
+ expect:
+ pipeline: running
+ stages:
+ test: running
+ deploy: created
+ jobs:
+ test: running
+ deploy: created
+
+ - event: success
+ jobs: [test]
+ expect:
+ pipeline: running
+ stages:
+ test: success
+ deploy: pending
+ jobs:
+ test: success
+ deploy: pending
+
+ - event: success
+ jobs: [deploy]
+ expect:
+ pipeline: success
+ stages:
+ test: success
+ deploy: success
+ jobs:
+ test: success
+ deploy: success
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml
new file mode 100644
index 00000000000..39545617926
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml
@@ -0,0 +1,58 @@
+config:
+ test:
+ stage: test
+ when: manual
+ allow_failure: true
+ script: exit 1
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ needs: [test]
+
+init:
+ expect:
+ pipeline: created
+ stages:
+ test: skipped
+ deploy: created
+ jobs:
+ test: manual
+ deploy: created
+
+transitions:
+ - event: enqueue
+ jobs: [test]
+ expect:
+ pipeline: pending
+ stages:
+ test: running
+ deploy: created
+ jobs:
+ test: pending
+ deploy: created
+
+ - event: run
+ jobs: [test]
+ expect:
+ pipeline: running
+ stages:
+ test: running
+ deploy: created
+ jobs:
+ test: running
+ deploy: created
+
+ - event: drop
+ jobs: [test]
+ expect:
+ pipeline: running
+ stages:
+ test: success
+ deploy: pending
+ jobs:
+ test: failed
+ deploy: pending
+
+# TOOD: should we run deploy?
+# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_always.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_always.yml
new file mode 100644
index 00000000000..ba0a20f49a7
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_always.yml
@@ -0,0 +1,27 @@
+config:
+ test:
+ stage: test
+ when: manual
+ allow_failure: true
+ script: exit 1
+
+ deploy:
+ stage: deploy
+ when: always
+ script: exit 0
+ needs: [test]
+
+init:
+ expect:
+ pipeline: created
+ stages:
+ test: skipped
+ deploy: created
+ jobs:
+ test: manual
+ deploy: created
+
+transitions: []
+
+# TODO: should we run `deploy`?
+# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml
new file mode 100644
index 00000000000..0c6a5a7e364
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml
@@ -0,0 +1,48 @@
+config:
+ test:
+ stage: test
+ when: manual
+ allow_failure: true
+ script: exit 1
+
+ deploy:
+ stage: deploy
+ when: on_failure
+ script: exit 0
+ needs: [test]
+
+init:
+ expect:
+ pipeline: created
+ stages:
+ test: skipped
+ deploy: created
+ jobs:
+ test: manual
+ deploy: created
+
+transitions:
+ - event: enqueue
+ jobs: [test]
+ expect:
+ pipeline: pending
+ stages:
+ test: running
+ deploy: created
+ jobs:
+ test: pending
+ deploy: created
+
+ - event: drop
+ jobs: [test]
+ expect:
+ pipeline: success
+ stages:
+ test: success
+ deploy: skipped
+ jobs:
+ test: failed
+ deploy: skipped
+
+# TODO: should we run `deploy`?
+# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_other_test_succeeds.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_other_test_succeeds.yml
new file mode 100644
index 00000000000..34073b92ccc
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_other_test_succeeds.yml
@@ -0,0 +1,42 @@
+config:
+ test1:
+ stage: test
+ script: exit 0
+
+ test2:
+ stage: test
+ when: manual
+ allow_failure: true
+ script: exit 1
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ needs: [test1, test2]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ test: pending
+ deploy: created
+ jobs:
+ test1: pending
+ test2: manual
+ deploy: created
+
+transitions:
+ - event: success
+ jobs: [test1]
+ expect:
+ pipeline: running
+ stages:
+ test: success
+ deploy: created
+ jobs:
+ test1: success
+ test2: manual
+ deploy: created
+
+# TODO: should deploy run?
+# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_failure.yml
new file mode 100644
index 00000000000..5ace621e89c
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_failure.yml
@@ -0,0 +1,66 @@
+config:
+ build:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ when: on_failure
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ needs: [test]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: running
+ stages:
+ build: failed
+ test: pending
+ deploy: created
+ jobs:
+ build: failed
+ test: pending
+ deploy: created
+
+ - event: success
+ jobs: [test]
+ expect:
+ pipeline: running
+ stages:
+ build: failed
+ test: success
+ deploy: pending
+ jobs:
+ build: failed
+ test: success
+ deploy: pending
+
+ - event: success
+ jobs: [deploy]
+ expect:
+ pipeline: failed
+ stages:
+ build: failed
+ test: success
+ deploy: success
+ jobs:
+ build: failed
+ test: success
+ deploy: success
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_success.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_success.yml
new file mode 100644
index 00000000000..19524cfd3e4
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_on_failure_with_success.yml
@@ -0,0 +1,40 @@
+config:
+ build:
+ stage: build
+ script: exit 0
+
+ test:
+ stage: test
+ when: on_failure
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+ needs: [test]
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: success
+ jobs: [build]
+ expect:
+ pipeline: success
+ stages:
+ build: success
+ test: skipped
+ deploy: skipped
+ jobs:
+ build: success
+ test: skipped
+ deploy: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_build_allow_failure_test_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/stage_build_allow_failure_test_on_failure.yml
new file mode 100644
index 00000000000..3e081d4411b
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_build_allow_failure_test_on_failure.yml
@@ -0,0 +1,53 @@
+config:
+ build:
+ stage: build
+ allow_failure: true
+ script: exit 1
+
+ test:
+ stage: test
+ when: on_failure
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: pending
+ stages:
+ build: success
+ test: skipped
+ deploy: pending
+ jobs:
+ build: failed
+ test: skipped
+ deploy: pending
+
+ - event: success
+ jobs: [deploy]
+ expect:
+ pipeline: success
+ stages:
+ build: success
+ test: skipped
+ deploy: success
+ jobs:
+ build: failed
+ test: skipped
+ deploy: success
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_build_fails.yml b/spec/services/ci/pipeline_processing/test_cases/stage_build_fails.yml
new file mode 100644
index 00000000000..0618abf3524
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_build_fails.yml
@@ -0,0 +1,38 @@
+config:
+ build:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: failed
+ stages:
+ build: failed
+ test: skipped
+ deploy: skipped
+ jobs:
+ build: failed
+ test: skipped
+ deploy: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_build_fails_test_allow_failure.yml b/spec/services/ci/pipeline_processing/test_cases/stage_build_fails_test_allow_failure.yml
new file mode 100644
index 00000000000..362ac6e4239
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_build_fails_test_allow_failure.yml
@@ -0,0 +1,39 @@
+config:
+ build:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ allow_failure: true
+ script: exit 1
+
+ deploy:
+ stage: deploy
+ script: exit 0
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: failed
+ stages:
+ build: failed
+ test: skipped
+ deploy: skipped
+ jobs:
+ build: failed
+ test: skipped
+ deploy: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml
new file mode 100644
index 00000000000..d37288b2075
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml
@@ -0,0 +1,65 @@
+config:
+ test:
+ stage: test
+ when: manual
+ allow_failure: false
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+
+init:
+ expect:
+ pipeline: manual
+ stages:
+ test: manual
+ deploy: created
+ jobs:
+ test: manual
+ deploy: created
+
+transitions:
+ - event: enqueue
+ jobs: [test]
+ expect:
+ pipeline: manual
+ stages:
+ test: manual
+ deploy: created
+ jobs:
+ test: pending
+ deploy: created
+
+ - event: run
+ jobs: [test]
+ expect:
+ pipeline: running
+ stages:
+ test: running
+ deploy: created
+ jobs:
+ test: running
+ deploy: created
+
+ - event: success
+ jobs: [test]
+ expect:
+ pipeline: running
+ stages:
+ test: success
+ deploy: pending
+ jobs:
+ test: success
+ deploy: pending
+
+ - event: success
+ jobs: [deploy]
+ expect:
+ pipeline: success
+ stages:
+ test: success
+ deploy: success
+ jobs:
+ test: success
+ deploy: success
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml
new file mode 100644
index 00000000000..bac339cc58d
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml
@@ -0,0 +1,54 @@
+config:
+ test:
+ stage: test
+ when: manual
+ allow_failure: true
+ script: exit 1
+
+ deploy:
+ stage: deploy
+ script: exit 0
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ test: skipped
+ deploy: pending
+ jobs:
+ test: manual
+ deploy: pending
+
+transitions:
+ - event: success
+ jobs: [deploy]
+ expect:
+ pipeline: success
+ stages:
+ test: skipped
+ deploy: success
+ jobs:
+ test: manual
+ deploy: success
+
+ - event: enqueue
+ jobs: [test]
+ expect:
+ pipeline: running
+ stages:
+ test: running
+ deploy: success
+ jobs:
+ test: pending
+ deploy: success
+
+ - event: drop
+ jobs: [test]
+ expect:
+ pipeline: success
+ stages:
+ test: success
+ deploy: success
+ jobs:
+ test: failed
+ deploy: success
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml
new file mode 100644
index 00000000000..ab1b210848a
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml
@@ -0,0 +1,44 @@
+config:
+ test:
+ stage: test
+ when: manual
+ allow_failure: true
+ script: exit 1
+
+ deploy:
+ stage: deploy
+ when: on_failure
+ script: exit 0
+
+init:
+ expect:
+ pipeline: skipped
+ stages:
+ test: skipped
+ deploy: skipped
+ jobs:
+ test: manual
+ deploy: skipped
+
+transitions:
+ - event: enqueue
+ jobs: [test]
+ expect:
+ pipeline: pending
+ stages:
+ test: running
+ deploy: skipped
+ jobs:
+ test: pending
+ deploy: skipped
+
+ - event: drop
+ jobs: [test]
+ expect:
+ pipeline: success
+ stages:
+ test: success
+ deploy: skipped
+ jobs:
+ test: failed
+ deploy: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_failure.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_failure.yml
new file mode 100644
index 00000000000..1751cbb2023
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_failure.yml
@@ -0,0 +1,52 @@
+config:
+ build:
+ stage: build
+ script: exit 1
+
+ test:
+ stage: test
+ when: on_failure
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: drop
+ jobs: [build]
+ expect:
+ pipeline: running
+ stages:
+ build: failed
+ test: pending
+ deploy: created
+ jobs:
+ build: failed
+ test: pending
+ deploy: created
+
+ - event: success
+ jobs: [test]
+ expect:
+ pipeline: failed
+ stages:
+ build: failed
+ test: success
+ deploy: skipped
+ jobs:
+ build: failed
+ test: success
+ deploy: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_success.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_success.yml
new file mode 100644
index 00000000000..15afe1ce8e1
--- /dev/null
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_on_failure_with_success.yml
@@ -0,0 +1,52 @@
+config:
+ build:
+ stage: build
+ script: exit 0
+
+ test:
+ stage: test
+ when: on_failure
+ script: exit 0
+
+ deploy:
+ stage: deploy
+ script: exit 0
+
+init:
+ expect:
+ pipeline: pending
+ stages:
+ build: pending
+ test: created
+ deploy: created
+ jobs:
+ build: pending
+ test: created
+ deploy: created
+
+transitions:
+ - event: success
+ jobs: [build]
+ expect:
+ pipeline: running
+ stages:
+ build: success
+ test: skipped
+ deploy: pending
+ jobs:
+ build: success
+ test: skipped
+ deploy: pending
+
+ - event: success
+ jobs: [deploy]
+ expect:
+ pipeline: success
+ stages:
+ build: success
+ test: skipped
+ deploy: success
+ jobs:
+ build: success
+ test: skipped
+ deploy: success
diff --git a/spec/workers/project_export_worker_spec.rb b/spec/workers/project_export_worker_spec.rb
index 373e7f32530..6adf9a1335f 100644
--- a/spec/workers/project_export_worker_spec.rb
+++ b/spec/workers/project_export_worker_spec.rb
@@ -17,14 +17,32 @@ describe ProjectExportWorker do
context 'when it succeeds' do
it 'calls the ExportService' do
- expect_any_instance_of(::Projects::ImportExport::ExportService).to receive(:execute)
+ expect_next_instance_of(::Projects::ImportExport::ExportService) do |service|
+ expect(service).to receive(:execute)
+ end
subject.perform(user.id, project.id, { 'klass' => 'Gitlab::ImportExport::AfterExportStrategies::DownloadNotificationStrategy' })
end
+ context 'with measurement options provided' do
+ it 'calls the ExportService with measurement options' do
+ measurement_options = { measurement_enabled: true }
+ params = {}
+ after_export_strategy = { 'klass' => 'Gitlab::ImportExport::AfterExportStrategies::DownloadNotificationStrategy' }
+
+ expect_next_instance_of(::Projects::ImportExport::ExportService) do |service|
+ expect(service).to receive(:execute).with(instance_of(Gitlab::ImportExport::AfterExportStrategies::DownloadNotificationStrategy), measurement_options)
+ end
+
+ subject.perform(user.id, project.id, after_export_strategy, params, measurement_options)
+ end
+ end
+
context 'export job' do
before do
- allow_any_instance_of(::Projects::ImportExport::ExportService).to receive(:execute)
+ allow_next_instance_of(::Projects::ImportExport::ExportService) do |service|
+ allow(service).to receive(:execute)
+ end
end
it 'creates an export job record for the project' do
diff --git a/yarn.lock b/yarn.lock
index e72ed7442c2..7e6a576f322 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -766,10 +766,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/at.js/-/at.js-1.5.5.tgz#5f6bfe6baaef360daa9b038fa78798d7a6a916b4"
integrity sha512-282Dn3SPVsUHVDhMsXgfnv+Rzog0uxecjttxGRQvxh25es1+xvkGQFsvJfkSKJ3X1kHVkSjKf+Tt5Rra+Jhp9g==
-"@gitlab/eslint-plugin@2.2.1":
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-2.2.1.tgz#7033030787981ded5ae24f4051109d069c98fcc0"
- integrity sha512-OM0gU2wfUeFZU5MP4Qaj1QHeJwpi9Ps35dRo8V1BP1lFskn2nDl6dEINAgqpdpjRV33LJ5/TZLfcGIswad0UtQ==
+"@gitlab/eslint-plugin@3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-3.0.0.tgz#1bf361af2e7d293cc10637d182b655328e0a9014"
+ integrity sha512-7mwJEO63GNfiSk2Jtvk0TlH2OZPCJ45lHd0s7c1+oNPUy18rquyYu0Iv/mtpwOcfnx8R2fSl0aD+d0lWDuHUNQ==
dependencies:
babel-eslint "^10.0.3"
eslint-config-airbnb-base "^14.0.0"
@@ -777,6 +777,7 @@
eslint-plugin-babel "^5.3.0"
eslint-plugin-filenames "^1.3.2"
eslint-plugin-import "^2.20.1"
+ eslint-plugin-jest "^23.8.2"
eslint-plugin-promise "^4.2.1"
eslint-plugin-vue "^6.2.1"
vue-eslint-parser "^7.0.0"
@@ -1140,6 +1141,11 @@
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-lib-report" "*"
+"@types/json-schema@^7.0.3":
+ version "7.0.4"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
+ integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==
+
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@@ -1222,6 +1228,29 @@
resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d"
integrity sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg==
+"@typescript-eslint/experimental-utils@^2.5.0":
+ version "2.30.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.30.0.tgz#9845e868c01f3aed66472c561d4b6bac44809dd0"
+ integrity sha512-L3/tS9t+hAHksy8xuorhOzhdefN0ERPDWmR9CclsIGOUqGKy6tqc/P+SoXeJRye5gazkuPO0cK9MQRnolykzkA==
+ dependencies:
+ "@types/json-schema" "^7.0.3"
+ "@typescript-eslint/typescript-estree" "2.30.0"
+ eslint-scope "^5.0.0"
+ eslint-utils "^2.0.0"
+
+"@typescript-eslint/typescript-estree@2.30.0":
+ version "2.30.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.30.0.tgz#1b8e848b55144270255ffbfe4c63291f8f766615"
+ integrity sha512-nI5WOechrA0qAhnr+DzqwmqHsx7Ulr/+0H7bWCcClDhhWkSyZR5BmTvnBEyONwJCTWHfc5PAQExX24VD26IAVw==
+ dependencies:
+ debug "^4.1.1"
+ eslint-visitor-keys "^1.1.0"
+ glob "^7.1.6"
+ is-glob "^4.0.1"
+ lodash "^4.17.15"
+ semver "^6.3.0"
+ tsutils "^3.17.1"
+
"@vue/component-compiler-utils@^2.4.0":
version "2.6.0"
resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-2.6.0.tgz#aa46d2a6f7647440b0b8932434d22f12371e543b"
@@ -4358,6 +4387,13 @@ eslint-plugin-jest@^22.3.0:
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.3.0.tgz#a10f10dedfc92def774ec9bb5bfbd2fb8e1c96d2"
integrity sha512-P1mYVRNlOEoO5T9yTqOfucjOYf1ktmJ26NjwjH8sxpCFQa6IhBGr5TpKl3hcAAT29hOsRJVuMWmTsHoUVo9FoA==
+eslint-plugin-jest@^23.8.2:
+ version "23.8.2"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.8.2.tgz#6f28b41c67ef635f803ebd9e168f6b73858eb8d4"
+ integrity sha512-xwbnvOsotSV27MtAe7s8uGWOori0nUsrXh2f1EnpmXua8sDfY6VZhHAhHg2sqK7HBNycRQExF074XSZ7DvfoFg==
+ dependencies:
+ "@typescript-eslint/experimental-utils" "^2.5.0"
+
eslint-plugin-no-jquery@^2.3.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.3.1.tgz#1c364cb863a38cc1570c8020155b6004cca62178"
@@ -4405,6 +4441,13 @@ eslint-utils@^1.4.3:
dependencies:
eslint-visitor-keys "^1.1.0"
+eslint-utils@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd"
+ integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==
+ dependencies:
+ eslint-visitor-keys "^1.1.0"
+
eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
@@ -11321,10 +11364,17 @@ ts-jest@24.0.0, ts-jest@^23.10.5:
semver "^5.5"
yargs-parser "10.x"
-tslib@^1.9.0, tslib@^1.9.3:
- version "1.9.3"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
- integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
+tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
+ integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==
+
+tsutils@^3.17.1:
+ version "3.17.1"
+ resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
+ integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==
+ dependencies:
+ tslib "^1.8.1"
tty-browserify@0.0.0:
version "0.0.0"