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-01-14 12:08:19 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-01-14 12:08:19 +0300
commit02ab65d49fc94be7c91e511899762236c122977d (patch)
tree4d4bf4ec54a95a0d73e039fa1410ea841156ffb2
parent4411353300cf8219d2b899785bc5103c549ba8cf (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop.yml8
-rw-r--r--app/assets/javascripts/ide/stores/actions.js16
-rw-r--r--app/assets/javascripts/ide/stores/actions/file.js55
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml3
-rw-r--r--changelogs/unreleased/30229-background-migration-pruneorphanedgeoevents-did-you-mean-pruneoldev.yml5
-rw-r--r--changelogs/unreleased/fe-ide-clean-up-discard-duplication.yml5
-rw-r--r--doc/ci/merge_request_pipelines/index.md2
-rw-r--r--doc/ci/quick_start/README.md44
-rw-r--r--doc/ci/yaml/README.md6
-rw-r--r--lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb13
-rw-r--r--lib/gitlab/background_migration/generate_gitlab_subscriptions.rb13
-rw-r--r--lib/gitlab/background_migration/migrate_approver_to_approval_rules.rb15
-rw-r--r--lib/gitlab/background_migration/migrate_approver_to_approval_rules_check_progress.rb13
-rw-r--r--lib/gitlab/background_migration/migrate_approver_to_approval_rules_in_batch.rb13
-rw-r--r--lib/gitlab/background_migration/move_epic_issues_after_epics.rb13
-rw-r--r--lib/gitlab/background_migration/populate_any_approval_rule_for_merge_requests.rb14
-rw-r--r--lib/gitlab/background_migration/populate_any_approval_rule_for_projects.rb14
-rw-r--r--lib/gitlab/background_migration/prune_orphaned_geo_events.rb17
-rw-r--r--lib/gitlab/background_migration/update_authorized_keys_file_since.rb13
-rw-r--r--lib/gitlab/background_migration/update_vulnerability_confidence.rb13
-rw-r--r--lib/gitlab/ci/config/entry/includes.rb9
-rw-r--r--lib/gitlab/email/attachment_uploader.rb4
-rw-r--r--lib/gitlab/email/handler/reply_processing.rb9
-rw-r--r--locale/gitlab.pot21
-rw-r--r--spec/frontend/ide/stores/actions/file_spec.js146
-rw-r--r--spec/javascripts/ide/stores/actions_spec.js84
-rw-r--r--spec/lib/gitlab/email/attachment_uploader_spec.rb2
-rw-r--r--spec/lib/gitlab/email/handler/create_note_handler_spec.rb13
-rw-r--r--yarn.lock39
29 files changed, 367 insertions, 255 deletions
diff --git a/.rubocop.yml b/.rubocop.yml
index 91c7aa53fb7..b65f9e8aff1 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -155,11 +155,10 @@ Rails/ApplicationRecord:
# as they need to be as decoupled from application code as possible
- db/**/*.rb
- lib/gitlab/background_migration/**/*.rb
+ - ee/lib/ee/gitlab/background_migration/**/*.rb
- lib/gitlab/database/**/*.rb
- spec/**/*.rb
- ee/db/**/*.rb
- - ee/lib/gitlab/background_migration/**/*.rb
- - ee/lib/ee/gitlab/background_migration/**/*.rb
- ee/spec/**/*.rb
# GitLab ###################################################################
@@ -233,7 +232,8 @@ RSpec/FactoriesInMigrationSpecs:
- 'spec/migrations/**/*.rb'
- 'ee/spec/migrations/**/*.rb'
- 'spec/lib/gitlab/background_migration/**/*.rb'
- - 'ee/spec/lib/gitlab/background_migration/**/*.rb'
+ - 'spec/lib/ee/gitlab/background_migration/**/*.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/**/*.rb'
Cop/IncludeActionViewContext:
Enabled: true
@@ -365,4 +365,4 @@ Style/MultilineWhenThen:
Enabled: false
Style/FloatDivision:
- Enabled: false \ No newline at end of file
+ Enabled: false
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index 66a89582da3..7ffb430296b 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -16,21 +16,7 @@ export const redirectToUrl = (self, url) => visitUrl(url);
export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DATA, data);
export const discardAllChanges = ({ state, commit, dispatch }) => {
- state.changedFiles.forEach(file => {
- if (file.tempFile || file.prevPath) dispatch('closeFile', file);
-
- if (file.tempFile) {
- dispatch('deleteEntry', file.path);
- } else if (file.prevPath) {
- dispatch('renameEntry', {
- path: file.path,
- name: file.prevName,
- parentPath: file.prevParentPath,
- });
- } else {
- commit(types.DISCARD_FILE_CHANGES, file.path);
- }
- });
+ state.changedFiles.forEach(file => dispatch('restoreOriginalFile', file.path));
commit(types.REMOVE_ALL_CHANGES_FILES);
};
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
index 99e13e32ba4..1bfee7b6be4 100644
--- a/app/assets/javascripts/ide/stores/actions/file.js
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -191,38 +191,47 @@ export const setFileViewMode = ({ commit }, { file, viewMode }) => {
commit(types.SET_FILE_VIEWMODE, { file, viewMode });
};
-export const discardFileChanges = ({ dispatch, state, commit, getters }, path) => {
+export const restoreOriginalFile = ({ dispatch, state, commit }, path) => {
const file = state.entries[path];
+ const isDestructiveDiscard = file.tempFile || file.prevPath;
if (file.deleted && file.parentPath) {
dispatch('restoreTree', file.parentPath);
}
- if (file.tempFile || file.prevPath) {
+ if (isDestructiveDiscard) {
dispatch('closeFile', file);
+ }
- if (file.tempFile) {
- dispatch('deleteEntry', file.path);
- } else {
- commit(types.DISCARD_FILE_CHANGES, file.path);
- dispatch('renameEntry', {
- path: file.path,
- name: file.prevName,
- parentPath: file.prevParentPath,
- });
- }
+ if (file.tempFile) {
+ dispatch('deleteEntry', file.path);
} else {
- commit(types.DISCARD_FILE_CHANGES, path);
-
- if (getters.activeFile && file.path === getters.activeFile.path) {
- dispatch('updateDelayViewerUpdated', true)
- .then(() => {
- router.push(`/project${file.url}`);
- })
- .catch(e => {
- throw e;
- });
- }
+ commit(types.DISCARD_FILE_CHANGES, file.path);
+ }
+
+ if (file.prevPath) {
+ dispatch('renameEntry', {
+ path: file.path,
+ name: file.prevName,
+ parentPath: file.prevParentPath,
+ });
+ }
+};
+
+export const discardFileChanges = ({ dispatch, state, commit, getters }, path) => {
+ const file = state.entries[path];
+ const isDestructiveDiscard = file.tempFile || file.prevPath;
+
+ dispatch('restoreOriginalFile', path);
+
+ if (!isDestructiveDiscard && file.path === getters.activeFile?.path) {
+ dispatch('updateDelayViewerUpdated', true)
+ .then(() => {
+ router.push(`/project${file.url}`);
+ })
+ .catch(e => {
+ throw e;
+ });
}
commit(types.REMOVE_FILE_FROM_CHANGED, path);
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 50530498f52..c3960ec5026 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -1,5 +1,6 @@
- type = local_assigns.fetch(:type)
- board = local_assigns.fetch(:board, nil)
+- show_sorting_dropdown = local_assigns.fetch(:show_sorting_dropdown, true)
- is_not_boards_modal_or_productivity_analytics = type != :boards_modal && type != :productivity_analytics
- block_css_class = is_not_boards_modal_or_productivity_analytics ? 'row-content-block second-block' : ''
- user_can_admin_list = board && can?(current_user, :admin_list, board.resource_parent)
@@ -169,5 +170,5 @@
- if @project
#js-add-issues-btn.prepend-left-10{ data: { can_admin_list: can?(current_user, :admin_list, @project) } }
#js-toggle-focus-btn
- - elsif is_not_boards_modal_or_productivity_analytics
+ - elsif is_not_boards_modal_or_productivity_analytics && show_sorting_dropdown
= render 'shared/issuable/sort_dropdown'
diff --git a/changelogs/unreleased/30229-background-migration-pruneorphanedgeoevents-did-you-mean-pruneoldev.yml b/changelogs/unreleased/30229-background-migration-pruneorphanedgeoevents-did-you-mean-pruneoldev.yml
new file mode 100644
index 00000000000..8b987c63d96
--- /dev/null
+++ b/changelogs/unreleased/30229-background-migration-pruneorphanedgeoevents-did-you-mean-pruneoldev.yml
@@ -0,0 +1,5 @@
+---
+title: 'Fix: undefined background migration classes for EE-CE downgrades'
+merge_request: 22160
+author:
+type: fixed
diff --git a/changelogs/unreleased/fe-ide-clean-up-discard-duplication.yml b/changelogs/unreleased/fe-ide-clean-up-discard-duplication.yml
new file mode 100644
index 00000000000..ac02673a8ea
--- /dev/null
+++ b/changelogs/unreleased/fe-ide-clean-up-discard-duplication.yml
@@ -0,0 +1,5 @@
+---
+title: Fix discard all to behave like discard single file in Web IDE
+merge_request: 22572
+author:
+type: fixed
diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md
index efb39dd1c55..8c3c17d2ce1 100644
--- a/doc/ci/merge_request_pipelines/index.md
+++ b/doc/ci/merge_request_pipelines/index.md
@@ -161,7 +161,7 @@ test:
only: [merge_requests]
except:
variables:
- $CI_COMMIT_REF_NAME =~ /^docs-/
+ - $CI_COMMIT_REF_NAME =~ /^docs-/
```
## Important notes about merge requests from forked projects
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index 68e977c1c98..55710145a95 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -17,34 +17,29 @@ NOTE: **Note:**
Coming over to GitLab from Jenkins? Check out our [reference](../jenkins/index.md)
for converting your pre-existing pipelines over to our format.
-GitLab offers a [continuous integration][ci] service. If you
-[add a `.gitlab-ci.yml` file][yaml] to the root directory of your repository,
-and configure your GitLab project to use a [Runner], then each commit or
-push triggers your CI [pipeline].
+GitLab offers a [continuous integration](https://about.gitlab.com/product/continuous-integration/) service. For each commit or push to trigger your CI
+[pipeline](../pipelines.md), you must:
-The `.gitlab-ci.yml` file tells the GitLab Runner what to do. By default it runs
-a pipeline with three [stages]: `build`, `test`, and `deploy`. You don't need to
-use all three stages; stages with no jobs are simply ignored.
+- Add a [`.gitlab-ci.yml` file](#creating-a-gitlab-ciyml-file) to your repository's root directory.
+- Ensure your project is configured to use a [Runner](#configuring-a-runner).
-If everything runs OK (no non-zero return values), you'll get a nice green
-checkmark associated with the commit. This makes it
-easy to see whether a commit caused any of the tests to fail before
-you even look at the code.
+The `.gitlab-ci.yml` file tells the GitLab Runner what to do. A simple pipeline commonly has
+three [stages](../yaml/README.md#stages):
-Most projects use GitLab's CI service to run the test suite so that
-developers get immediate feedback if they broke something.
+- `build`
+- `test`
+- `deploy`
-There's a growing trend to use continuous delivery and continuous deployment to
-automatically deploy tested code to staging and production environments.
+You do not need to use all three stages; stages with no jobs are ignored.
-So in brief, the steps needed to have a working CI can be summed up to:
+The pipeline appears under the project's **CI/CD > Pipelines** page. If everything runs OK (no non-zero
+return values), you get a green check mark associated with the commit. This makes it easy to see
+whether a commit caused any of the tests to fail before you even look at the job (test) log. Many projects use
+GitLab's CI service to run the test suite, so developers get immediate feedback if they broke
+something.
-1. Add `.gitlab-ci.yml` to the root directory of your repository
-1. Configure a Runner
-
-From there on, on every push to your Git repository, the Runner will
-automatically start the pipeline and the pipeline will appear under the
-project's **Pipelines** page.
+It's also common to use pipelines to automatically deploy
+tested code to staging and production environments.
---
@@ -237,9 +232,4 @@ CI with various languages.
[runner-install]: https://docs.gitlab.com/runner/install/
[blog-ci]: https://about.gitlab.com/blog/2015/05/06/why-were-replacing-gitlab-ci-jobs-with-gitlab-ci-dot-yml/
[examples]: ../examples/README.md
-[ci]: https://about.gitlab.com/product/continuous-integration/
-[yaml]: ../yaml/README.md
-[runner]: ../runners/README.md
[enabled]: ../enable_or_disable_ci.md
-[stages]: ../yaml/README.md#stages
-[pipeline]: ../pipelines.md
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 5c5dd12969a..e388fdde58a 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -2719,10 +2719,10 @@ can lead to errors during the deployment.
To avoid these errors, the `resource_group` attribute can be used to ensure that
the Runner will not run certain jobs simultaneously.
-When the `resource_group` key is defined in a job in `.gitlab-ci.yml`,
-job runs are mutually exclusive across different pipelines in the same project.
+When the `resource_group` key is defined for a job in `.gitlab-ci.yml`,
+job executions are mutually exclusive across different pipelines for the same project.
If multiple jobs belonging to the same resource group are enqueued simultaneously,
-only one of them will be picked by the Runner, and the other jobs will wait until the
+only one of the jobs will be picked by the Runner, and the other jobs will wait until the
`resource_group` is free.
Here is a simple example:
diff --git a/lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb b/lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb
new file mode 100644
index 00000000000..83d60d2db19
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_version_data_from_gitaly.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class BackfillVersionDataFromGitaly
+ def perform(issue_id)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::BackfillVersionDataFromGitaly.prepend_if_ee('EE::Gitlab::BackgroundMigration::BackfillVersionDataFromGitaly')
diff --git a/lib/gitlab/background_migration/generate_gitlab_subscriptions.rb b/lib/gitlab/background_migration/generate_gitlab_subscriptions.rb
new file mode 100644
index 00000000000..85bcf8558f2
--- /dev/null
+++ b/lib/gitlab/background_migration/generate_gitlab_subscriptions.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class GenerateGitlabSubscriptions
+ def perform(start_id, stop_id)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::GenerateGitlabSubscriptions.prepend_if_ee('EE::Gitlab::BackgroundMigration::GenerateGitlabSubscriptions')
diff --git a/lib/gitlab/background_migration/migrate_approver_to_approval_rules.rb b/lib/gitlab/background_migration/migrate_approver_to_approval_rules.rb
new file mode 100644
index 00000000000..27b984b4531
--- /dev/null
+++ b/lib/gitlab/background_migration/migrate_approver_to_approval_rules.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class MigrateApproverToApprovalRules
+ # @param target_type [String] class of target, either 'MergeRequest' or 'Project'
+ # @param target_id [Integer] id of target
+ def perform(target_type, target_id, sync_code_owner_rule: true)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::MigrateApproverToApprovalRules.prepend_if_ee('EE::Gitlab::BackgroundMigration::MigrateApproverToApprovalRules')
diff --git a/lib/gitlab/background_migration/migrate_approver_to_approval_rules_check_progress.rb b/lib/gitlab/background_migration/migrate_approver_to_approval_rules_check_progress.rb
new file mode 100644
index 00000000000..053b7363286
--- /dev/null
+++ b/lib/gitlab/background_migration/migrate_approver_to_approval_rules_check_progress.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class MigrateApproverToApprovalRulesCheckProgress
+ def perform
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::MigrateApproverToApprovalRulesCheckProgress.prepend_if_ee('EE::Gitlab::BackgroundMigration::MigrateApproverToApprovalRulesCheckProgress')
diff --git a/lib/gitlab/background_migration/migrate_approver_to_approval_rules_in_batch.rb b/lib/gitlab/background_migration/migrate_approver_to_approval_rules_in_batch.rb
new file mode 100644
index 00000000000..130f97b09d7
--- /dev/null
+++ b/lib/gitlab/background_migration/migrate_approver_to_approval_rules_in_batch.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class MigrateApproverToApprovalRulesInBatch
+ def perform(start_id, end_id)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::MigrateApproverToApprovalRulesInBatch.prepend_if_ee('EE::Gitlab::BackgroundMigration::MigrateApproverToApprovalRulesInBatch')
diff --git a/lib/gitlab/background_migration/move_epic_issues_after_epics.rb b/lib/gitlab/background_migration/move_epic_issues_after_epics.rb
new file mode 100644
index 00000000000..dc982e703d1
--- /dev/null
+++ b/lib/gitlab/background_migration/move_epic_issues_after_epics.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class MoveEpicIssuesAfterEpics
+ def perform(start_id, stop_id)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::MoveEpicIssuesAfterEpics.prepend_if_ee('EE::Gitlab::BackgroundMigration::MoveEpicIssuesAfterEpics')
diff --git a/lib/gitlab/background_migration/populate_any_approval_rule_for_merge_requests.rb b/lib/gitlab/background_migration/populate_any_approval_rule_for_merge_requests.rb
new file mode 100644
index 00000000000..c3c0db2495c
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_any_approval_rule_for_merge_requests.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This background migration creates any approver rule records according
+ # to the given merge request IDs range. A _single_ INSERT is issued for the given range.
+ class PopulateAnyApprovalRuleForMergeRequests
+ def perform(from_id, to_id)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::PopulateAnyApprovalRuleForMergeRequests.prepend_if_ee('EE::Gitlab::BackgroundMigration::PopulateAnyApprovalRuleForMergeRequests')
diff --git a/lib/gitlab/background_migration/populate_any_approval_rule_for_projects.rb b/lib/gitlab/background_migration/populate_any_approval_rule_for_projects.rb
new file mode 100644
index 00000000000..2243c7531c0
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_any_approval_rule_for_projects.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This background migration creates any approver rule records according
+ # to the given project IDs range. A _single_ INSERT is issued for the given range.
+ class PopulateAnyApprovalRuleForProjects
+ def perform(from_id, to_id)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::PopulateAnyApprovalRuleForProjects.prepend_if_ee('EE::Gitlab::BackgroundMigration::PopulateAnyApprovalRuleForProjects')
diff --git a/lib/gitlab/background_migration/prune_orphaned_geo_events.rb b/lib/gitlab/background_migration/prune_orphaned_geo_events.rb
new file mode 100644
index 00000000000..8b16db8be35
--- /dev/null
+++ b/lib/gitlab/background_migration/prune_orphaned_geo_events.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+#
+# rubocop:disable Style/Documentation
+
+# This job is added to fix https://gitlab.com/gitlab-org/gitlab/issues/30229
+# It's not used anywhere else.
+# Can be removed in GitLab 13.*
+module Gitlab
+ module BackgroundMigration
+ class PruneOrphanedGeoEvents
+ def perform(table_name)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::PruneOrphanedGeoEvents.prepend_if_ee('EE::Gitlab::BackgroundMigration::PruneOrphanedGeoEvents')
diff --git a/lib/gitlab/background_migration/update_authorized_keys_file_since.rb b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
new file mode 100644
index 00000000000..dd80d4bab1a
--- /dev/null
+++ b/lib/gitlab/background_migration/update_authorized_keys_file_since.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class UpdateAuthorizedKeysFileSince
+ def perform(cutoff_datetime)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::UpdateAuthorizedKeysFileSince.prepend_if_ee('EE::Gitlab::BackgroundMigration::UpdateAuthorizedKeysFileSince')
diff --git a/lib/gitlab/background_migration/update_vulnerability_confidence.rb b/lib/gitlab/background_migration/update_vulnerability_confidence.rb
new file mode 100644
index 00000000000..6ffaa836f3c
--- /dev/null
+++ b/lib/gitlab/background_migration/update_vulnerability_confidence.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class UpdateVulnerabilityConfidence
+ def perform(start_id, stop_id)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::UpdateVulnerabilityConfidence.prepend_if_ee('EE::Gitlab::BackgroundMigration::UpdateVulnerabilityConfidence')
diff --git a/lib/gitlab/ci/config/entry/includes.rb b/lib/gitlab/ci/config/entry/includes.rb
index 43e74dfd628..24d0e27e3a7 100644
--- a/lib/gitlab/ci/config/entry/includes.rb
+++ b/lib/gitlab/ci/config/entry/includes.rb
@@ -12,6 +12,15 @@ module Gitlab
validations do
validates :config, array_or_string: true
+
+ validate do
+ next unless opt(:max_size)
+ next unless config.is_a?(Array)
+
+ if config.size > opt(:max_size)
+ errors.add(:config, "is too long (maximum is #{opt(:max_size)})")
+ end
+ end
end
def self.aspects
diff --git a/lib/gitlab/email/attachment_uploader.rb b/lib/gitlab/email/attachment_uploader.rb
index 3323ce60158..0a14a909e31 100644
--- a/lib/gitlab/email/attachment_uploader.rb
+++ b/lib/gitlab/email/attachment_uploader.rb
@@ -9,7 +9,7 @@ module Gitlab
@message = message
end
- def execute(project)
+ def execute(upload_parent:, uploader_class:)
attachments = []
message.attachments.each do |attachment|
@@ -23,7 +23,7 @@ module Gitlab
content_type: attachment.content_type
}
- uploader = UploadService.new(project, file).execute
+ uploader = UploadService.new(upload_parent, file, uploader_class).execute
attachments << uploader.to_h if uploader
ensure
tmp.close!
diff --git a/lib/gitlab/email/handler/reply_processing.rb b/lib/gitlab/email/handler/reply_processing.rb
index 6b7686cd405..312a9fdfbae 100644
--- a/lib/gitlab/email/handler/reply_processing.rb
+++ b/lib/gitlab/email/handler/reply_processing.rb
@@ -41,13 +41,20 @@ module Gitlab
end
def add_attachments(reply)
- attachments = Email::AttachmentUploader.new(mail).execute(project)
+ attachments = Email::AttachmentUploader.new(mail).execute(upload_params)
reply + attachments.map do |link|
"\n\n#{link[:markdown]}"
end.join
end
+ def upload_params
+ {
+ upload_parent: project,
+ uploader_class: FileUploader
+ }
+ end
+
def validate_permission!(permission)
raise UserNotFoundError unless author
raise UserBlockedError if author.blocked?
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 68077245975..f61290b5687 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -5639,12 +5639,30 @@ msgstr ""
msgid "CycleAnalytics|No stages selected"
msgstr ""
+msgid "CycleAnalytics|Number of tasks"
+msgstr ""
+
+msgid "CycleAnalytics|Showing %{subject} and %{selectedLabelsCount} labels"
+msgstr ""
+
+msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
+msgstr ""
+
+msgid "CycleAnalytics|Showing data for group '%{groupName}' from %{startDate} to %{endDate}"
+msgstr ""
+
msgid "CycleAnalytics|Stages"
msgstr ""
+msgid "CycleAnalytics|Tasks by type"
+msgstr ""
+
msgid "CycleAnalytics|Total days to completion"
msgstr ""
+msgid "CycleAnalytics|Type of work"
+msgstr ""
+
msgid "CycleAnalytics|group dropdown filter"
msgstr ""
@@ -5687,6 +5705,9 @@ msgstr ""
msgid "Data is still calculating..."
msgstr ""
+msgid "Date"
+msgstr ""
+
msgid "Date picker"
msgstr ""
diff --git a/spec/frontend/ide/stores/actions/file_spec.js b/spec/frontend/ide/stores/actions/file_spec.js
index 2d72ae770ab..e7b34aa3e7a 100644
--- a/spec/frontend/ide/stores/actions/file_spec.js
+++ b/spec/frontend/ide/stores/actions/file_spec.js
@@ -619,107 +619,113 @@ describe('IDE store file actions', () => {
});
});
- describe('discardFileChanges', () => {
+ describe('with changed file', () => {
let tmpFile;
beforeEach(() => {
- jest.spyOn(eventHub, '$on').mockImplementation(() => {});
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
-
tmpFile = file('tempFile');
tmpFile.content = 'testing';
tmpFile.raw = ORIGINAL_CONTENT;
store.state.changedFiles.push(tmpFile);
store.state.entries[tmpFile.path] = tmpFile;
-
- jest.spyOn(store, 'dispatch');
});
- it('resets file content', done => {
- store
- .dispatch('discardFileChanges', tmpFile.path)
- .then(() => {
+ describe('restoreOriginalFile', () => {
+ it('resets file content', () =>
+ store.dispatch('restoreOriginalFile', tmpFile.path).then(() => {
expect(tmpFile.content).toBe(ORIGINAL_CONTENT);
+ }));
- done();
- })
- .catch(done.fail);
- });
+ it('closes temp file and deletes it', () => {
+ tmpFile.tempFile = true;
+ tmpFile.opened = true;
+ tmpFile.parentPath = 'parentFile';
+ store.state.entries.parentFile = file('parentFile');
- it('removes file from changedFiles array', done => {
- store
- .dispatch('discardFileChanges', tmpFile.path)
- .then(() => {
- expect(store.state.changedFiles.length).toBe(0);
+ actions.restoreOriginalFile(store, tmpFile.path);
- done();
- })
- .catch(done.fail);
- });
+ expect(store.dispatch).toHaveBeenCalledWith('closeFile', tmpFile);
+ expect(store.dispatch).toHaveBeenCalledWith('deleteEntry', tmpFile.path);
+ });
- it('closes temp file and deletes it', () => {
- tmpFile.tempFile = true;
- tmpFile.opened = true;
- tmpFile.parentPath = 'parentFile';
- store.state.entries.parentFile = file('parentFile');
+ describe('with renamed file', () => {
+ beforeEach(() => {
+ Object.assign(tmpFile, {
+ prevPath: 'parentPath/old_name',
+ prevName: 'old_name',
+ prevParentPath: 'parentPath',
+ });
- actions.discardFileChanges(store, tmpFile.path);
+ store.state.entries.parentPath = file('parentPath');
- expect(store.dispatch).toHaveBeenCalledWith('closeFile', tmpFile);
- expect(store.dispatch).toHaveBeenCalledWith('deleteEntry', tmpFile.path);
- });
+ actions.restoreOriginalFile(store, tmpFile.path);
+ });
- describe('with renamed file', () => {
- beforeEach(() => {
- Object.assign(tmpFile, {
- prevPath: 'parentPath/old_name',
- prevName: 'old_name',
- prevParentPath: 'parentPath',
+ it('renames the file to its original name and closes it if it was open', () => {
+ expect(store.dispatch).toHaveBeenCalledWith('closeFile', tmpFile);
+ expect(store.dispatch).toHaveBeenCalledWith('renameEntry', {
+ path: 'tempFile',
+ name: 'old_name',
+ parentPath: 'parentPath',
+ });
});
- store.state.entries.parentPath = file('parentPath');
+ it('resets file content', () => {
+ expect(tmpFile.content).toBe(ORIGINAL_CONTENT);
+ });
+ });
+ });
- actions.discardFileChanges(store, tmpFile.path);
+ describe('discardFileChanges', () => {
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$on').mockImplementation(() => {});
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
});
- it('renames the file to its original name and closes it if it was open', () => {
- expect(store.dispatch).toHaveBeenCalledWith('closeFile', tmpFile);
- expect(store.dispatch).toHaveBeenCalledWith('renameEntry', {
- path: 'tempFile',
- name: 'old_name',
- parentPath: 'parentPath',
+ describe('with regular file', () => {
+ beforeEach(() => {
+ actions.discardFileChanges(store, tmpFile.path);
});
- });
- it('resets file content', () => {
- expect(tmpFile.content).toBe(ORIGINAL_CONTENT);
- });
- });
+ it('restores original file', () => {
+ expect(store.dispatch).toHaveBeenCalledWith('restoreOriginalFile', tmpFile.path);
+ });
- it('pushes route for active file', done => {
- tmpFile.active = true;
- store.state.openFiles.push(tmpFile);
+ it('removes file from changedFiles array', () => {
+ expect(store.state.changedFiles.length).toBe(0);
+ });
- store
- .dispatch('discardFileChanges', tmpFile.path)
- .then(() => {
- expect(router.push).toHaveBeenCalledWith(`/project${tmpFile.url}`);
+ it('does not push a new route', () => {
+ expect(router.push).not.toHaveBeenCalled();
+ });
- done();
- })
- .catch(done.fail);
- });
+ it('emits eventHub event to dispose cached model', () => {
+ actions.discardFileChanges(store, tmpFile.path);
+
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ `editor.update.model.new.content.${tmpFile.key}`,
+ ORIGINAL_CONTENT,
+ );
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ `editor.update.model.dispose.unstaged-${tmpFile.key}`,
+ ORIGINAL_CONTENT,
+ );
+ });
+ });
- it('emits eventHub event to dispose cached model', done => {
- store
- .dispatch('discardFileChanges', tmpFile.path)
- .then(() => {
- expect(eventHub.$emit).toHaveBeenCalled();
+ describe('with active file', () => {
+ beforeEach(() => {
+ tmpFile.active = true;
+ store.state.openFiles.push(tmpFile);
- done();
- })
- .catch(done.fail);
+ actions.discardFileChanges(store, tmpFile.path);
+ });
+
+ it('pushes route for active file', () => {
+ expect(router.push).toHaveBeenCalledWith(`/project${tmpFile.url}`);
+ });
+ });
});
});
diff --git a/spec/javascripts/ide/stores/actions_spec.js b/spec/javascripts/ide/stores/actions_spec.js
index a9fc3bf65a6..8abd9c38514 100644
--- a/spec/javascripts/ide/stores/actions_spec.js
+++ b/spec/javascripts/ide/stores/actions_spec.js
@@ -61,24 +61,25 @@ describe('Multi-file store actions', () => {
});
describe('discardAllChanges', () => {
- let f;
+ const paths = ['to_discard', 'another_one_to_discard'];
+
beforeEach(() => {
- f = file('discardAll');
- f.changed = true;
+ paths.forEach(path => {
+ const f = file(path);
+ f.changed = true;
- store.state.openFiles.push(f);
- store.state.changedFiles.push(f);
- store.state.entries[f.path] = f;
+ store.state.openFiles.push(f);
+ store.state.changedFiles.push(f);
+ store.state.entries[f.path] = f;
+ });
});
- it('discards changes in file', done => {
- store
- .dispatch('discardAllChanges')
- .then(() => {
- expect(store.state.openFiles.changed).toBeFalsy();
- })
- .then(done)
- .catch(done.fail);
+ it('discards all changes in file', () => {
+ const expectedCalls = paths.map(path => ['restoreOriginalFile', path]);
+
+ discardAllChanges(store);
+
+ expect(store.dispatch.calls.allArgs()).toEqual(jasmine.arrayContaining(expectedCalls));
});
it('removes all files from changedFiles state', done => {
@@ -86,64 +87,11 @@ describe('Multi-file store actions', () => {
.dispatch('discardAllChanges')
.then(() => {
expect(store.state.changedFiles.length).toBe(0);
- expect(store.state.openFiles.length).toBe(1);
+ expect(store.state.openFiles.length).toBe(2);
})
.then(done)
.catch(done.fail);
});
-
- it('closes the temp file and deletes it if it was open', done => {
- f.tempFile = true;
-
- testAction(
- discardAllChanges,
- undefined,
- store.state,
- [{ type: types.REMOVE_ALL_CHANGES_FILES }],
- [
- { type: 'closeFile', payload: jasmine.objectContaining({ path: 'discardAll' }) },
- { type: 'deleteEntry', payload: 'discardAll' },
- ],
- done,
- );
- });
-
- it('renames the file to its original name and closes it if it was open', done => {
- Object.assign(f, {
- prevPath: 'parent/path/old_name',
- prevName: 'old_name',
- prevParentPath: 'parent/path',
- });
-
- testAction(
- discardAllChanges,
- undefined,
- store.state,
- [{ type: types.REMOVE_ALL_CHANGES_FILES }],
- [
- { type: 'closeFile', payload: jasmine.objectContaining({ path: 'discardAll' }) },
- {
- type: 'renameEntry',
- payload: { path: 'discardAll', name: 'old_name', parentPath: 'parent/path' },
- },
- ],
- done,
- );
- });
-
- it('discards file changes on all other files', done => {
- testAction(
- discardAllChanges,
- undefined,
- store.state,
- [
- { type: types.DISCARD_FILE_CHANGES, payload: 'discardAll' },
- { type: types.REMOVE_ALL_CHANGES_FILES },
- ],
- [],
- done,
- );
- });
});
describe('closeAllFiles', () => {
diff --git a/spec/lib/gitlab/email/attachment_uploader_spec.rb b/spec/lib/gitlab/email/attachment_uploader_spec.rb
index d66a746284d..c69b2f1eabc 100644
--- a/spec/lib/gitlab/email/attachment_uploader_spec.rb
+++ b/spec/lib/gitlab/email/attachment_uploader_spec.rb
@@ -9,7 +9,7 @@ describe Gitlab::Email::AttachmentUploader do
let(:message) { Mail::Message.new(message_raw) }
it "uploads all attachments and returns their links" do
- links = described_class.new(message).execute(project)
+ links = described_class.new(message).execute(upload_parent: project, uploader_class: FileUploader)
link = links.first
expect(link).not_to be_nil
diff --git a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
index 50e473c459e..909a7618df4 100644
--- a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
@@ -181,10 +181,21 @@ describe Gitlab::Email::Handler::CreateNoteHandler do
it_behaves_like 'a reply to existing comment'
it "adds all attachments" do
+ expect_next_instance_of(Gitlab::Email::AttachmentUploader) do |uploader|
+ expect(uploader).to receive(:execute).with(upload_parent: project, uploader_class: FileUploader).and_return(
+ [
+ {
+ url: "uploads/image.png",
+ alt: "image",
+ markdown: markdown
+ }
+ ]
+ )
+ end
+
receiver.execute
note = noteable.notes.last
-
expect(note.note).to include(markdown)
end
diff --git a/yarn.lock b/yarn.lock
index c7e5e2af1f3..5289e563189 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3461,44 +3461,7 @@ d3-zoom@1:
d3-selection "1"
d3-transition "1"
-d3@^5.12.0, d3@^5.7.0:
- version "5.12.0"
- resolved "https://registry.yarnpkg.com/d3/-/d3-5.12.0.tgz#0ddeac879c28c882317cd439b495290acd59ab61"
- integrity sha512-flYVMoVuhPFHd9zVCe2BxIszUWqBcd5fvQGMNRmSiBrgdnh6Vlruh60RJQTouAK9xPbOB0plxMvBm4MoyODXNg==
- dependencies:
- d3-array "1"
- d3-axis "1"
- d3-brush "1"
- d3-chord "1"
- d3-collection "1"
- d3-color "1"
- d3-contour "1"
- d3-dispatch "1"
- d3-drag "1"
- d3-dsv "1"
- d3-ease "1"
- d3-fetch "1"
- d3-force "1"
- d3-format "1"
- d3-geo "1"
- d3-hierarchy "1"
- d3-interpolate "1"
- d3-path "1"
- d3-polygon "1"
- d3-quadtree "1"
- d3-random "1"
- d3-scale "2"
- d3-scale-chromatic "1"
- d3-selection "1"
- d3-shape "1"
- d3-time "1"
- d3-time-format "2"
- d3-timer "1"
- d3-transition "1"
- d3-voronoi "1"
- d3-zoom "1"
-
-d3@^5.14:
+d3@^5.12.0, d3@^5.14, d3@^5.7.0:
version "5.15.0"
resolved "https://registry.yarnpkg.com/d3/-/d3-5.15.0.tgz#ffd44958e6a3cb8a59a84429c45429b8bca5677a"
integrity sha512-C+E80SL2nLLtmykZ6klwYj5rPqB5nlfN5LdWEAVdWPppqTD8taoJi2PxLZjPeYT8FFRR2yucXq+kBlOnnvZeLg==