summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.rubocop.yml6
-rw-r--r--Gemfile5
-rw-r--r--Gemfile.lock129
-rw-r--r--app/assets/javascripts/editor/editor_lite.js68
-rw-r--r--app/assets/javascripts/editor/utils.js11
-rw-r--r--app/assets/javascripts/ide/lib/editor.js9
-rw-r--r--app/assets/javascripts/vue_shared/components/changed_file_icon.vue18
-rw-r--r--app/assets/stylesheets/pages/tree.scss4
-rw-r--r--app/controllers/application_controller.rb2
-rw-r--r--app/controllers/concerns/membership_actions.rb4
-rw-r--r--app/controllers/concerns/send_file_upload.rb16
-rw-r--r--app/controllers/projects/releases_controller.rb17
-rw-r--r--app/helpers/markup_helper.rb2
-rw-r--r--app/models/commit_status.rb4
-rw-r--r--app/models/concerns/issuable.rb4
-rw-r--r--app/models/concerns/mirror_authentication.rb2
-rw-r--r--app/models/merge_request.rb2
-rw-r--r--app/models/notification_setting.rb5
-rw-r--r--app/presenters/project_presenter.rb2
-rw-r--r--app/serializers/concerns/user_status_tooltip.rb2
-rw-r--r--app/services/concerns/spam_check_methods.rb2
-rw-r--r--app/services/metrics/dashboard/clone_dashboard_service.rb26
-rw-r--r--app/services/projects/detect_repository_languages_service.rb2
-rw-r--r--app/services/projects/move_access_service.rb2
-rw-r--r--app/services/projects/transfer_service.rb6
-rw-r--r--app/services/spam/spam_check_service.rb68
-rw-r--r--app/services/spam_check_service.rb66
-rw-r--r--app/uploaders/object_storage.rb2
-rw-r--r--app/views/projects/_home_panel.html.haml7
-rw-r--r--app/views/projects/buttons/_clone.html.haml7
-rw-r--r--app/views/projects/empty.html.haml7
-rw-r--r--app/views/projects/network/show.json.erb2
-rw-r--r--app/views/projects/releases/show.html.haml4
-rw-r--r--app/views/projects/tree/_tree_header.html.haml6
-rw-r--r--app/views/shared/_mobile_clone_panel.html.haml2
-rw-r--r--app/workers/mail_scheduler/notification_service_worker.rb41
-rwxr-xr-xbin/setup12
-rw-r--r--changelogs/unreleased/197973-staged-and-unstaged-modification-tooltip-for-file-with-staged-chan.yml5
-rw-r--r--changelogs/unreleased/31034-upgrade-to-rails-6.yml5
-rw-r--r--changelogs/unreleased/39505-extend-the-ability-to-clone-a-dashboard-so-it-would-copy-the-custom.yml6
-rw-r--r--changelogs/unreleased/gt-move-clone-button-to-the-tree-controls-area.yml5
-rw-r--r--config/application.rb4
-rw-r--r--config/environment.rb5
-rw-r--r--config/environments/development.rb4
-rw-r--r--config/initializers/active_record_data_types.rb11
-rw-r--r--config/initializers/active_record_preloader.rb2
-rw-r--r--config/initializers/active_record_query_cache.rb3
-rw-r--r--config/initializers/config_initializers_active_record_locking.rb2
-rw-r--r--config/initializers/content_security_policy.rb1
-rw-r--r--config/initializers/cookies_serializer.rb1
-rw-r--r--config/routes/project.rb2
-rw-r--r--db/schema.rb10
-rw-r--r--doc/development/packages.md2
-rw-r--r--lib/api/helpers.rb4
-rw-r--r--lib/gitlab/action_view_output/context.rb41
-rw-r--r--lib/gitlab/ci/config/external/file/template.rb2
-rw-r--r--lib/gitlab/content_disposition.rb54
-rw-r--r--lib/gitlab/database.rb7
-rw-r--r--lib/gitlab/database/migration_helpers.rb6
-rw-r--r--lib/gitlab/patch/active_record_query_cache.rb39
-rw-r--r--lib/gitlab/query_limiting/middleware.rb4
-rw-r--r--locale/ar_SA/gitlab.po3
-rw-r--r--locale/bg/gitlab.po3
-rw-r--r--locale/bn_BD/gitlab.po3
-rw-r--r--locale/bn_IN/gitlab.po3
-rw-r--r--locale/ca_ES/gitlab.po3
-rw-r--r--locale/cs_CZ/gitlab.po3
-rw-r--r--locale/cy_GB/gitlab.po3
-rw-r--r--locale/da_DK/gitlab.po3
-rw-r--r--locale/de/gitlab.po3
-rw-r--r--locale/el_GR/gitlab.po3
-rw-r--r--locale/eo/gitlab.po3
-rw-r--r--locale/es/gitlab.po3
-rw-r--r--locale/et_EE/gitlab.po3
-rw-r--r--locale/fa_IR/gitlab.po3
-rw-r--r--locale/fil_PH/gitlab.po3
-rw-r--r--locale/fr/gitlab.po3
-rw-r--r--locale/gitlab.pot9
-rw-r--r--locale/gl_ES/gitlab.po3
-rw-r--r--locale/he_IL/gitlab.po3
-rw-r--r--locale/hi_IN/gitlab.po3
-rw-r--r--locale/hr_HR/gitlab.po3
-rw-r--r--locale/hu_HU/gitlab.po3
-rw-r--r--locale/id_ID/gitlab.po3
-rw-r--r--locale/it/gitlab.po3
-rw-r--r--locale/ja/gitlab.po3
-rw-r--r--locale/ka_GE/gitlab.po3
-rw-r--r--locale/ko/gitlab.po3
-rw-r--r--locale/ku_TR/gitlab.po3
-rw-r--r--locale/ml_IN/gitlab.po3
-rw-r--r--locale/mn_MN/gitlab.po3
-rw-r--r--locale/nb_NO/gitlab.po3
-rw-r--r--locale/nl_NL/gitlab.po3
-rw-r--r--locale/pa_IN/gitlab.po3
-rw-r--r--locale/pl_PL/gitlab.po3
-rw-r--r--locale/pt_BR/gitlab.po3
-rw-r--r--locale/pt_PT/gitlab.po3
-rw-r--r--locale/ro_RO/gitlab.po3
-rw-r--r--locale/ru/gitlab.po3
-rw-r--r--locale/sk_SK/gitlab.po3
-rw-r--r--locale/sq_AL/gitlab.po3
-rw-r--r--locale/sr_CS/gitlab.po3
-rw-r--r--locale/sr_SP/gitlab.po3
-rw-r--r--locale/sv_SE/gitlab.po3
-rw-r--r--locale/sw_KE/gitlab.po3
-rw-r--r--locale/tr_TR/gitlab.po3
-rw-r--r--locale/uk/gitlab.po3
-rw-r--r--locale/ur_PK/gitlab.po3
-rw-r--r--locale/uz_UZ/gitlab.po3
-rw-r--r--locale/vi_VN/gitlab.po3
-rw-r--r--locale/zh_CN/gitlab.po3
-rw-r--r--locale/zh_HK/gitlab.po3
-rw-r--r--locale/zh_TW/gitlab.po3
-rw-r--r--rubocop/cop/include_action_view_context.rb26
-rw-r--r--rubocop/rubocop.rb1
-rw-r--r--spec/config/application_spec.rb2
-rw-r--r--spec/controllers/concerns/metrics_dashboard_spec.rb2
-rw-r--r--spec/controllers/concerns/send_file_upload_spec.rb24
-rw-r--r--spec/controllers/projects/artifacts_controller_spec.rb12
-rw-r--r--spec/controllers/projects/releases_controller_spec.rb46
-rw-r--r--spec/controllers/uploads_controller_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb4
-rw-r--r--spec/features/projects/artifacts/user_downloads_artifacts_spec.rb2
-rw-r--r--spec/features/projects/jobs_spec.rb2
-rw-r--r--spec/frontend/vue_shared/components/changed_file_icon_spec.js12
-rw-r--r--spec/javascripts/editor/editor_lite_spec.js111
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb2
-rw-r--r--spec/lib/gitlab/query_limiting/middleware_spec.rb4
-rw-r--r--spec/models/merge_request_spec.rb6
-rw-r--r--spec/presenters/project_presenter_spec.rb2
-rw-r--r--spec/requests/api/issues/post_projects_issues_spec.rb2
-rw-r--r--spec/requests/api/issues/put_projects_issues_spec.rb2
-rw-r--r--spec/rubocop/cop/include_action_view_context_spec.rb45
-rw-r--r--spec/services/akismet_service_spec.rb1
-rw-r--r--spec/services/issues/create_service_spec.rb2
-rw-r--r--spec/services/metrics/dashboard/clone_dashboard_service_spec.rb27
-rw-r--r--spec/services/projects/transfer_service_spec.rb38
-rw-r--r--spec/services/spam/spam_check_service_spec.rb (renamed from spec/services/spam_check_service_spec.rb)2
-rw-r--r--spec/support/helpers/javascript_fixtures_helpers.rb2
-rw-r--r--spec/support/helpers/migrations_helpers.rb2
-rw-r--r--spec/support/helpers/stub_configuration.rb1
-rw-r--r--spec/support/shared_examples/controllers/repository_lfs_file_load_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb35
143 files changed, 665 insertions, 719 deletions
diff --git a/.rubocop.yml b/.rubocop.yml
index 46419e69e7e..1e34dc2480b 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -235,12 +235,6 @@ RSpec/FactoriesInMigrationSpecs:
- 'spec/lib/ee/gitlab/background_migration/**/*.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/**/*.rb'
-Cop/IncludeActionViewContext:
- Enabled: true
- Exclude:
- - 'spec/**/*'
- - 'ee/spec/**/*'
-
Cop/IncludeSidekiqWorker:
Enabled: true
Exclude:
diff --git a/Gemfile b/Gemfile
index b8e7ba12b56..e816e1a1fcd 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,6 @@
source 'https://rubygems.org'
-gem 'rails', '5.2.3'
+gem 'rails', '6.0.2'
gem 'bootsnap', '~> 1.4'
@@ -305,7 +305,7 @@ gem 'gitlab-labkit', '0.9.1'
# I18n
gem 'ruby_parser', '~> 3.8', require: false
-gem 'rails-i18n', '~> 5.1'
+gem 'rails-i18n', '~> 6.0'
gem 'gettext_i18n_rails', '~> 1.8.0'
gem 'gettext_i18n_rails_js', '~> 1.3'
gem 'gettext', '~> 3.2.2', require: false, group: :development
@@ -332,6 +332,7 @@ group :metrics do
end
group :development do
+ gem 'listen', '~> 3.0'
gem 'brakeman', '~> 4.2', require: false
gem 'danger', '~> 6.0', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index f7bc7441741..c52150cc675 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -6,50 +6,64 @@ GEM
ace-rails-ap (4.1.2)
acme-client (2.0.5)
faraday (~> 0.9, >= 0.9.1)
- actioncable (5.2.3)
- actionpack (= 5.2.3)
+ actioncable (6.0.2)
+ actionpack (= 6.0.2)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailer (5.2.3)
- actionpack (= 5.2.3)
- actionview (= 5.2.3)
- activejob (= 5.2.3)
+ actionmailbox (6.0.2)
+ actionpack (= 6.0.2)
+ activejob (= 6.0.2)
+ activerecord (= 6.0.2)
+ activestorage (= 6.0.2)
+ activesupport (= 6.0.2)
+ mail (>= 2.7.1)
+ actionmailer (6.0.2)
+ actionpack (= 6.0.2)
+ actionview (= 6.0.2)
+ activejob (= 6.0.2)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (5.2.3)
- actionview (= 5.2.3)
- activesupport (= 5.2.3)
+ actionpack (6.0.2)
+ actionview (= 6.0.2)
+ activesupport (= 6.0.2)
rack (~> 2.0)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (5.2.3)
- activesupport (= 5.2.3)
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
+ actiontext (6.0.2)
+ actionpack (= 6.0.2)
+ activerecord (= 6.0.2)
+ activestorage (= 6.0.2)
+ activesupport (= 6.0.2)
+ nokogiri (>= 1.8.5)
+ actionview (6.0.2)
+ activesupport (= 6.0.2)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
- rails-html-sanitizer (~> 1.0, >= 1.0.3)
- activejob (5.2.3)
- activesupport (= 5.2.3)
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
+ activejob (6.0.2)
+ activesupport (= 6.0.2)
globalid (>= 0.3.6)
- activemodel (5.2.3)
- activesupport (= 5.2.3)
- activerecord (5.2.3)
- activemodel (= 5.2.3)
- activesupport (= 5.2.3)
- arel (>= 9.0)
+ activemodel (6.0.2)
+ activesupport (= 6.0.2)
+ activerecord (6.0.2)
+ activemodel (= 6.0.2)
+ activesupport (= 6.0.2)
activerecord-explain-analyze (0.1.0)
activerecord (>= 4)
pg
- activestorage (5.2.3)
- actionpack (= 5.2.3)
- activerecord (= 5.2.3)
+ activestorage (6.0.2)
+ actionpack (= 6.0.2)
+ activejob (= 6.0.2)
+ activerecord (= 6.0.2)
marcel (~> 0.3.1)
- activesupport (5.2.3)
+ activesupport (6.0.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
+ zeitwerk (~> 2.2)
acts-as-taggable-on (6.5.0)
activerecord (>= 5.0, < 6.1)
adamantium (0.2.0)
@@ -62,7 +76,6 @@ GEM
apollo_upload_server (2.0.0.beta.3)
graphql (>= 1.8)
rails (>= 4.2)
- arel (9.0.0)
asana (0.9.3)
faraday (~> 0.9)
faraday_middleware (~> 0.9)
@@ -198,13 +211,14 @@ GEM
declarative-option (0.1.0)
default_value_for (3.3.0)
activerecord (>= 3.2.0, < 6.1)
- derailed_benchmarks (1.3.5)
+ derailed_benchmarks (1.4.2)
benchmark-ips (~> 2)
get_process_mem (~> 0)
heapy (~> 0)
memory_profiler (~> 0)
rack (>= 1)
- rake (> 10, < 13)
+ rake (> 10, < 14)
+ ruby-statistics (>= 2.1)
thor (~> 0.19)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
@@ -348,7 +362,8 @@ GEM
gemoji (3.0.1)
gemojione (3.3.0)
json
- get_process_mem (0.2.3)
+ get_process_mem (0.2.5)
+ ffi (~> 1.0)
gettext (3.2.9)
locale (>= 2.0.5)
text (>= 1.3.0)
@@ -434,8 +449,9 @@ GEM
activesupport
grape (~> 1.0)
rake (~> 12)
- grape_logging (1.7.0)
+ grape_logging (1.8.3)
grape
+ rack
graphiql-rails (1.4.10)
railties
sprockets-rails
@@ -510,7 +526,7 @@ GEM
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
- i18n (1.7.1)
+ i18n (1.7.0)
concurrent-ruby (~> 1.0)
i18n_data (0.8.0)
icalendar (2.4.1)
@@ -609,12 +625,12 @@ GEM
memoist (0.16.0)
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
- memory_profiler (0.9.13)
+ memory_profiler (0.9.14)
method_source (0.9.2)
mime-types (3.2.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2019.0331)
- mimemagic (0.3.2)
+ mimemagic (0.3.3)
mini_magick (4.9.5)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
@@ -787,18 +803,20 @@ GEM
rack-test (1.1.0)
rack (>= 1.0, < 3)
rack-timeout (0.5.1)
- rails (5.2.3)
- actioncable (= 5.2.3)
- actionmailer (= 5.2.3)
- actionpack (= 5.2.3)
- actionview (= 5.2.3)
- activejob (= 5.2.3)
- activemodel (= 5.2.3)
- activerecord (= 5.2.3)
- activestorage (= 5.2.3)
- activesupport (= 5.2.3)
+ rails (6.0.2)
+ actioncable (= 6.0.2)
+ actionmailbox (= 6.0.2)
+ actionmailer (= 6.0.2)
+ actionpack (= 6.0.2)
+ actiontext (= 6.0.2)
+ actionview (= 6.0.2)
+ activejob (= 6.0.2)
+ activemodel (= 6.0.2)
+ activerecord (= 6.0.2)
+ activestorage (= 6.0.2)
+ activesupport (= 6.0.2)
bundler (>= 1.3.0)
- railties (= 5.2.3)
+ railties (= 6.0.2)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.4)
actionpack (>= 5.0.1.x)
@@ -809,15 +827,15 @@ GEM
nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
- rails-i18n (5.1.1)
+ rails-i18n (6.0.0)
i18n (>= 0.7, < 2)
- railties (>= 5.0, < 6)
- railties (5.2.3)
- actionpack (= 5.2.3)
- activesupport (= 5.2.3)
+ railties (>= 6.0.0, < 7)
+ railties (6.0.2)
+ actionpack (= 6.0.2)
+ activesupport (= 6.0.2)
method_source
rake (>= 0.8.7)
- thor (>= 0.19.0, < 2.0)
+ thor (>= 0.20.3, < 2.0)
rainbow (3.0.0)
raindrops (0.19.0)
rake (12.3.3)
@@ -937,6 +955,7 @@ GEM
ruby-progressbar (1.10.1)
ruby-saml (1.7.2)
nokogiri (>= 1.5.10)
+ ruby-statistics (2.1.1)
ruby_dep (1.5.0)
ruby_parser (3.13.1)
sexp_processor (~> 4.9)
@@ -1111,9 +1130,9 @@ GEM
hashdiff
webpack-rails (0.9.11)
railties (>= 3.2.0)
- websocket-driver (0.7.0)
+ websocket-driver (0.7.1)
websocket-extensions (>= 0.1.0)
- websocket-extensions (0.1.3)
+ websocket-extensions (0.1.4)
wikicloth (0.8.1)
builder
expression_parser
@@ -1122,6 +1141,7 @@ GEM
xml-simple (1.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
+ zeitwerk (2.2.2)
PLATFORMS
ruby
@@ -1259,6 +1279,7 @@ DEPENDENCIES
license_finder (~> 5.4)
licensee (~> 8.9)
liquid (~> 4.0)
+ listen (~> 3.0)
lograge (~> 0.5)
loofah (~> 2.2)
lru_redux
@@ -1309,9 +1330,9 @@ DEPENDENCIES
rack-oauth2 (~> 1.9.3)
rack-proxy (~> 0.6.0)
rack-timeout
- rails (= 5.2.3)
+ rails (= 6.0.2)
rails-controller-testing
- rails-i18n (~> 5.1)
+ rails-i18n (~> 6.0)
rainbow (~> 3.0)
raindrops (~> 0.18)
rblineprof (~> 0.3.6)
diff --git a/app/assets/javascripts/editor/editor_lite.js b/app/assets/javascripts/editor/editor_lite.js
new file mode 100644
index 00000000000..bdfbcf71267
--- /dev/null
+++ b/app/assets/javascripts/editor/editor_lite.js
@@ -0,0 +1,68 @@
+import { editor as monacoEditor, languages as monacoLanguages, Uri } from 'monaco-editor';
+import gitlabTheme from '~/ide/lib/themes/gl_theme';
+import { defaultEditorOptions } from '~/ide/lib/editor_options';
+import { clearDomElement } from './utils';
+
+export default class Editor {
+ constructor(options = {}) {
+ this.editorEl = null;
+ this.blobContent = '';
+ this.blobPath = '';
+ this.instance = null;
+ this.model = null;
+ this.options = {
+ ...defaultEditorOptions,
+ ...options,
+ };
+
+ Editor.setupMonacoTheme();
+ }
+
+ static setupMonacoTheme() {
+ monacoEditor.defineTheme(gitlabTheme.themeName, gitlabTheme.monacoTheme);
+ monacoEditor.setTheme('gitlab');
+ }
+
+ createInstance({ el = undefined, blobPath = '', blobContent = '' } = {}) {
+ if (!el) return;
+ this.editorEl = el;
+ this.blobContent = blobContent;
+ this.blobPath = blobPath;
+
+ clearDomElement(this.editorEl);
+
+ this.model = monacoEditor.createModel(
+ this.blobContent,
+ undefined,
+ new Uri('gitlab', false, this.blobPath),
+ );
+
+ monacoEditor.onDidCreateEditor(this.renderEditor.bind(this));
+
+ this.instance = monacoEditor.create(this.editorEl, this.options);
+ this.instance.setModel(this.model);
+ }
+
+ dispose() {
+ return this.instance && this.instance.dispose();
+ }
+
+ renderEditor() {
+ delete this.editorEl.dataset.editorLoading;
+ }
+
+ updateModelLanguage(path) {
+ if (path === this.blobPath) return;
+ this.blobPath = path;
+ const ext = `.${path.split('.').pop()}`;
+ const language = monacoLanguages
+ .getLanguages()
+ .find(lang => lang.extensions.indexOf(ext) !== -1);
+ const id = language ? language.id : 'plaintext';
+ monacoEditor.setModelLanguage(this.model, id);
+ }
+
+ getValue() {
+ return this.model.getValue();
+ }
+}
diff --git a/app/assets/javascripts/editor/utils.js b/app/assets/javascripts/editor/utils.js
new file mode 100644
index 00000000000..d8b6396b671
--- /dev/null
+++ b/app/assets/javascripts/editor/utils.js
@@ -0,0 +1,11 @@
+export const clearDomElement = el => {
+ if (!el || !el.firstChild) return;
+
+ while (el.firstChild) {
+ el.removeChild(el.firstChild);
+ }
+};
+
+export default () => ({
+ clearDomElement,
+});
diff --git a/app/assets/javascripts/ide/lib/editor.js b/app/assets/javascripts/ide/lib/editor.js
index d1056ea6b98..a0f689065aa 100644
--- a/app/assets/javascripts/ide/lib/editor.js
+++ b/app/assets/javascripts/ide/lib/editor.js
@@ -8,20 +8,13 @@ import ModelManager from './common/model_manager';
import editorOptions, { defaultEditorOptions } from './editor_options';
import gitlabTheme from './themes/gl_theme';
import keymap from './keymap.json';
+import { clearDomElement } from '~/editor/utils';
function setupMonacoTheme() {
monacoEditor.defineTheme(gitlabTheme.themeName, gitlabTheme.monacoTheme);
monacoEditor.setTheme('gitlab');
}
-export const clearDomElement = el => {
- if (!el || !el.firstChild) return;
-
- while (el.firstChild) {
- el.removeChild(el.firstChild);
- }
-};
-
export default class Editor {
static create(options = {}) {
if (!this.editorInstance) {
diff --git a/app/assets/javascripts/vue_shared/components/changed_file_icon.vue b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
index 75c3c544c77..9ec99ac93d7 100644
--- a/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
@@ -41,7 +41,7 @@ export default {
changedIcon() {
// False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26
// eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings
- const suffix = !this.file.changed && this.file.staged && this.showStagedIcon ? '-solid' : '';
+ const suffix = this.file.staged && this.showStagedIcon ? '-solid' : '';
return `${getCommitIconMap(this.file).icon}${suffix}`;
},
@@ -49,25 +49,19 @@ export default {
return `${this.changedIcon} float-left d-block`;
},
tooltipTitle() {
- if (!this.showTooltip) return undefined;
+ if (!this.showTooltip || !this.file.changed) return undefined;
const type = this.file.tempFile ? 'addition' : 'modification';
- if (this.file.changed && !this.file.staged) {
- return sprintf(__('Unstaged %{type}'), {
- type,
- });
- } else if (!this.file.changed && this.file.staged) {
+ if (this.file.staged) {
return sprintf(__('Staged %{type}'), {
type,
});
- } else if (this.file.changed && this.file.staged) {
- return sprintf(__('Unstaged and staged %{type}'), {
- type,
- });
}
- return undefined;
+ return sprintf(__('Unstaged %{type}'), {
+ type,
+ });
},
showIcon() {
return (
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index 79ad0bd7735..c14ae8a3711 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -21,10 +21,6 @@
margin-left: 8px;
}
- .btn-group {
- margin-left: 10px;
- }
-
.control {
float: left;
margin-left: 10px;
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index c6d91308123..789bccf268a 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -120,7 +120,7 @@ class ApplicationController < ActionController::Base
def render(*args)
super.tap do
# Set a header for custom error pages to prevent them from being intercepted by gitlab-workhorse
- if (400..599).cover?(response.status) && workhorse_excluded_content_types.include?(response.content_type)
+ if (400..599).cover?(response.status) && workhorse_excluded_content_types.include?(response.media_type)
response.headers['X-GitLab-Custom-Error'] = '1'
end
end
diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb
index 993f091b0e6..1cf9046e30f 100644
--- a/app/controllers/concerns/membership_actions.rb
+++ b/app/controllers/concerns/membership_actions.rb
@@ -21,9 +21,9 @@ module MembershipActions
member = Members::UpdateService
.new(current_user, update_params)
.execute(member)
- .present(current_user: current_user)
- present_members([member])
+ member = present_members([member]).first
+
respond_to do |format|
format.js { render 'shared/members/update', locals: { member: member } }
end
diff --git a/app/controllers/concerns/send_file_upload.rb b/app/controllers/concerns/send_file_upload.rb
index 28e4cece548..2f5dc09be4a 100644
--- a/app/controllers/concerns/send_file_upload.rb
+++ b/app/controllers/concerns/send_file_upload.rb
@@ -3,7 +3,7 @@
module SendFileUpload
def send_upload(file_upload, send_params: {}, redirect_params: {}, attachment: nil, proxy: false, disposition: 'attachment')
if attachment
- response_disposition = ::Gitlab::ContentDisposition.format(disposition: disposition, filename: attachment)
+ response_disposition = ActionDispatch::Http::ContentDisposition.format(disposition: disposition, filename: attachment)
# Response-Content-Type will not override an existing Content-Type in
# Google Cloud Storage, so the metadata needs to be cleared on GCS for
@@ -15,7 +15,7 @@ module SendFileUpload
# cross-origin JavaScript protection.
send_params[:content_type] = 'text/plain' if File.extname(attachment) == '.js'
- send_params.merge!(filename: attachment, disposition: utf8_encoded_disposition(disposition, attachment))
+ send_params.merge!(filename: attachment, disposition: disposition)
end
if file_upload.file_storage?
@@ -28,18 +28,6 @@ module SendFileUpload
end
end
- # Since Rails 5 doesn't properly support support non-ASCII filenames,
- # we have to add our own to ensure RFC 5987 compliance. However, Rails
- # 5 automatically appends `filename#{filename}` here:
- # https://github.com/rails/rails/blob/v5.0.7/actionpack/lib/action_controller/metal/data_streaming.rb#L137
- # Rails 6 will have https://github.com/rails/rails/pull/33829, so we
- # can get rid of this special case handling when we upgrade.
- def utf8_encoded_disposition(disposition, filename)
- content = ::Gitlab::ContentDisposition.new(disposition: disposition, filename: filename)
-
- "#{disposition}; #{content.utf8_filename}"
- end
-
def guess_content_type(filename)
types = MIME::Types.type_for(filename)
diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb
index 08a57a9b146..7ad841d645d 100644
--- a/app/controllers/projects/releases_controller.rb
+++ b/app/controllers/projects/releases_controller.rb
@@ -3,11 +3,12 @@
class Projects::ReleasesController < Projects::ApplicationController
# Authorize
before_action :require_non_empty_project, except: [:index]
- before_action :release, only: %i[edit update]
+ before_action :release, only: %i[edit show update]
before_action :authorize_read_release!
before_action do
push_frontend_feature_flag(:release_issue_summary, project)
push_frontend_feature_flag(:release_evidence_collection, project, default_enabled: true)
+ push_frontend_feature_flag(:release_show_page, project)
end
before_action :authorize_update_release!, only: %i[edit update]
before_action :authorize_read_release_evidence!, only: [:evidence]
@@ -29,6 +30,16 @@ class Projects::ReleasesController < Projects::ApplicationController
end
end
+ def show
+ return render_404 unless Feature.enabled?(:release_show_page, project)
+
+ respond_to do |format|
+ format.html do
+ render :show
+ end
+ end
+ end
+
protected
def releases
@@ -37,7 +48,9 @@ class Projects::ReleasesController < Projects::ApplicationController
def edit
respond_to do |format|
- format.html { render 'edit' }
+ format.html do
+ render :edit
+ end
end
end
diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb
index e24d6a0e8db..e42ea3861b8 100644
--- a/app/helpers/markup_helper.rb
+++ b/app/helpers/markup_helper.rb
@@ -4,7 +4,7 @@ require 'nokogiri'
module MarkupHelper
include ActionView::Helpers::TextHelper
- include ::Gitlab::ActionViewOutput::Context
+ include ActionView::Context
def plain?(filename)
Gitlab::MarkupHelper.plain?(filename)
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index f9101609f89..5a917588a33 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -200,6 +200,10 @@ class CommitStatus < ApplicationRecord
update_all('processed=TRUE, lock_version=COALESCE(lock_version,0)+1')
end
+ def self.locking_enabled?
+ false
+ end
+
def locking_enabled?
will_save_change_to_status?
end
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 653dc9c0b47..a6961df1b51 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -130,6 +130,10 @@ module Issuable
strip_attributes :title
+ def self.locking_enabled?
+ false
+ end
+
# We want to use optimistic lock for cases when only title or description are involved
# http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html
def locking_enabled?
diff --git a/app/models/concerns/mirror_authentication.rb b/app/models/concerns/mirror_authentication.rb
index 948094221e5..4dbf4dcec77 100644
--- a/app/models/concerns/mirror_authentication.rb
+++ b/app/models/concerns/mirror_authentication.rb
@@ -37,6 +37,8 @@ module MirrorAuthentication
end
define_method("#{name}=") do |value|
+ credentials_will_change!
+
self.credentials ||= {}
# Removal of the password, username, etc, generally causes an update of
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 3174a3269b4..62f34ae6525 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -712,7 +712,7 @@ class MergeRequest < ApplicationRecord
end
def validate_branch_name(attr)
- return unless changes_include?(attr)
+ return unless will_save_change_to_attribute?(attr)
branch = read_attribute(attr)
diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb
index 2b3443f24d7..1447f822513 100644
--- a/app/models/notification_setting.rb
+++ b/app/models/notification_setting.rb
@@ -21,7 +21,10 @@ class NotificationSetting < ApplicationRecord
# pending delete).
#
scope :for_projects, -> do
- includes(:project).references(:projects).where(source_type: 'Project').where.not(projects: { id: nil, pending_delete: true })
+ includes(:project).references(:projects)
+ .where(source_type: 'Project')
+ .where.not(projects: { id: nil })
+ .where.not(projects: { pending_delete: true })
end
EMAIL_EVENTS = [
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 8c24d07675a..42c707908e6 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -208,7 +208,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
AnchorData.new(false,
statistic_icon + _('New file'),
project_new_blob_path(project, default_branch || 'master'),
- 'success')
+ 'missing')
end
end
diff --git a/app/serializers/concerns/user_status_tooltip.rb b/app/serializers/concerns/user_status_tooltip.rb
index a81e377691e..633b117d392 100644
--- a/app/serializers/concerns/user_status_tooltip.rb
+++ b/app/serializers/concerns/user_status_tooltip.rb
@@ -3,7 +3,7 @@
module UserStatusTooltip
extend ActiveSupport::Concern
include ActionView::Helpers::TagHelper
- include ::Gitlab::ActionViewOutput::Context
+ include ActionView::Context
include EmojiHelper
include UsersHelper
diff --git a/app/services/concerns/spam_check_methods.rb b/app/services/concerns/spam_check_methods.rb
index 5eb663c97ff..695bdf92b49 100644
--- a/app/services/concerns/spam_check_methods.rb
+++ b/app/services/concerns/spam_check_methods.rb
@@ -23,7 +23,7 @@ module SpamCheckMethods
# attribute values.
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def spam_check(spammable, user)
- SpamCheckService.new(
+ Spam::SpamCheckService.new(
spammable: spammable,
request: @request
).execute(
diff --git a/app/services/metrics/dashboard/clone_dashboard_service.rb b/app/services/metrics/dashboard/clone_dashboard_service.rb
index b2ec44cb814..990dc462432 100644
--- a/app/services/metrics/dashboard/clone_dashboard_service.rb
+++ b/app/services/metrics/dashboard/clone_dashboard_service.rb
@@ -8,8 +8,18 @@ module Metrics
ALLOWED_FILE_TYPE = '.yml'
USER_DASHBOARDS_DIR = ::Metrics::Dashboard::ProjectDashboardService::DASHBOARD_ROOT
- def self.allowed_dashboard_templates
- @allowed_dashboard_templates ||= Set[::Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH].freeze
+ class << self
+ def allowed_dashboard_templates
+ @allowed_dashboard_templates ||= Set[::Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH].freeze
+ end
+
+ def sequences
+ @sequences ||= {
+ ::Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH => [::Gitlab::Metrics::Dashboard::Stages::CommonMetricsInserter,
+ ::Gitlab::Metrics::Dashboard::Stages::ProjectMetricsInserter,
+ ::Gitlab::Metrics::Dashboard::Stages::Sorter].freeze
+ }.freeze
+ end
end
def execute
@@ -92,7 +102,9 @@ module Metrics
end
def new_dashboard_content
- File.read(Rails.root.join(dashboard_template))
+ ::Gitlab::Metrics::Dashboard::Processor
+ .new(project, raw_dashboard, sequence, {})
+ .process.deep_stringify_keys.to_yaml
end
def repository
@@ -106,6 +118,14 @@ module Metrics
result
end
end
+
+ def raw_dashboard
+ YAML.safe_load(File.read(Rails.root.join(dashboard_template)))
+ end
+
+ def sequence
+ self.class.sequences[dashboard_template]
+ end
end
end
end
diff --git a/app/services/projects/detect_repository_languages_service.rb b/app/services/projects/detect_repository_languages_service.rb
index d3680637217..942cd8162e4 100644
--- a/app/services/projects/detect_repository_languages_service.rb
+++ b/app/services/projects/detect_repository_languages_service.rb
@@ -12,7 +12,7 @@ module Projects
matching_programming_languages = ensure_programming_languages(detection)
RepositoryLanguage.transaction do
- project.repository_languages.where(programming_language_id: detection.deletions).delete_all
+ RepositoryLanguage.where(project_id: project.id, programming_language_id: detection.deletions).delete_all
detection.updates.each do |update|
RepositoryLanguage
diff --git a/app/services/projects/move_access_service.rb b/app/services/projects/move_access_service.rb
index 8e2c3ad2f69..cddc544170f 100644
--- a/app/services/projects/move_access_service.rb
+++ b/app/services/projects/move_access_service.rb
@@ -20,6 +20,8 @@ module Projects
::Projects::MoveProjectAuthorizationsService.new(@project, @current_user)
.execute(source_project, remove_remaining_elements: remove_remaining_elements)
+ @project.save(touch: false)
+
success
end
end
diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb
index 718416a03d4..309eab59463 100644
--- a/app/services/projects/transfer_service.rb
+++ b/app/services/projects/transfer_service.rb
@@ -13,8 +13,6 @@ module Projects
include Gitlab::ShellAdapter
TransferError = Class.new(StandardError)
- attr_reader :new_namespace
-
def execute(new_namespace)
@new_namespace = new_namespace
@@ -39,6 +37,8 @@ module Projects
private
+ attr_reader :old_path, :new_path, :new_namespace
+
# rubocop: disable CodeReuse/ActiveRecord
def transfer(project)
@old_path = project.full_path
@@ -132,6 +132,8 @@ module Projects
end
def rollback_folder_move
+ return if project.hashed_storage?(:repository)
+
move_repo_folder(@new_path, @old_path)
move_repo_folder("#{@new_path}.wiki", "#{@old_path}.wiki")
end
diff --git a/app/services/spam/spam_check_service.rb b/app/services/spam/spam_check_service.rb
new file mode 100644
index 00000000000..d19ef03976f
--- /dev/null
+++ b/app/services/spam/spam_check_service.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module Spam
+ class SpamCheckService
+ include AkismetMethods
+
+ attr_accessor :spammable, :request, :options
+ attr_reader :spam_log
+
+ def initialize(spammable:, request:)
+ @spammable = spammable
+ @request = request
+ @options = {}
+
+ if @request
+ @options[:ip_address] = @request.env['action_dispatch.remote_ip'].to_s
+ @options[:user_agent] = @request.env['HTTP_USER_AGENT']
+ @options[:referrer] = @request.env['HTTP_REFERRER']
+ else
+ @options[:ip_address] = @spammable.ip_address
+ @options[:user_agent] = @spammable.user_agent
+ end
+ end
+
+ def execute(api: false, recaptcha_verified:, spam_log_id:, user_id:)
+ if recaptcha_verified
+ # If it's a request which is already verified through recaptcha,
+ # update the spam log accordingly.
+ SpamLog.verify_recaptcha!(user_id: user_id, id: spam_log_id)
+ else
+ # Otherwise, it goes to Akismet for spam check.
+ # If so, it assigns spammable object as "spam" and creates a SpamLog record.
+ possible_spam = check(api)
+ spammable.spam = possible_spam unless spammable.allow_possible_spam?
+ spammable.spam_log = spam_log
+ end
+ end
+
+ private
+
+ def check(api)
+ return unless request
+ return unless check_for_spam?
+ return unless akismet.spam?
+
+ create_spam_log(api)
+ true
+ end
+
+ def check_for_spam?
+ spammable.check_for_spam?
+ end
+
+ def create_spam_log(api)
+ @spam_log = SpamLog.create!(
+ {
+ user_id: spammable.author_id,
+ title: spammable.spam_title,
+ description: spammable.spam_description,
+ source_ip: options[:ip_address],
+ user_agent: options[:user_agent],
+ noteable_type: spammable.class.to_s,
+ via_api: api
+ }
+ )
+ end
+ end
+end
diff --git a/app/services/spam_check_service.rb b/app/services/spam_check_service.rb
deleted file mode 100644
index e1f5efabcaf..00000000000
--- a/app/services/spam_check_service.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-class SpamCheckService
- include AkismetMethods
-
- attr_accessor :spammable, :request, :options
- attr_reader :spam_log
-
- def initialize(spammable:, request:)
- @spammable = spammable
- @request = request
- @options = {}
-
- if @request
- @options[:ip_address] = @request.env['action_dispatch.remote_ip'].to_s
- @options[:user_agent] = @request.env['HTTP_USER_AGENT']
- @options[:referrer] = @request.env['HTTP_REFERRER']
- else
- @options[:ip_address] = @spammable.ip_address
- @options[:user_agent] = @spammable.user_agent
- end
- end
-
- def execute(api: false, recaptcha_verified:, spam_log_id:, user_id:)
- if recaptcha_verified
- # If it's a request which is already verified through recaptcha,
- # update the spam log accordingly.
- SpamLog.verify_recaptcha!(user_id: user_id, id: spam_log_id)
- else
- # Otherwise, it goes to Akismet for spam check.
- # If so, it assigns spammable object as "spam" and creates a SpamLog record.
- possible_spam = check(api)
- spammable.spam = possible_spam unless spammable.allow_possible_spam?
- spammable.spam_log = spam_log
- end
- end
-
- private
-
- def check(api)
- return unless request
- return unless check_for_spam?
- return unless akismet.spam?
-
- create_spam_log(api)
- true
- end
-
- def check_for_spam?
- spammable.check_for_spam?
- end
-
- def create_spam_log(api)
- @spam_log = SpamLog.create!(
- {
- user_id: spammable.author_id,
- title: spammable.spam_title,
- description: spammable.spam_description,
- source_ip: options[:ip_address],
- user_agent: options[:user_agent],
- noteable_type: spammable.class.to_s,
- via_api: api
- }
- )
- end
-end
diff --git a/app/uploaders/object_storage.rb b/app/uploaders/object_storage.rb
index 36bde629f9c..450ebb00b49 100644
--- a/app/uploaders/object_storage.rb
+++ b/app/uploaders/object_storage.rb
@@ -125,7 +125,7 @@ module ObjectStorage
included do
include AfterCommitQueue
- after_save on: [:create, :update] do
+ after_save do
background_upload(changed_mounts)
end
end
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index daedc52f298..7796db5ba63 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -49,13 +49,6 @@
= render 'projects/buttons/star'
= render 'projects/buttons/fork'
- - if can?(current_user, :download_code, @project)
- .project-clone-holder.d-inline-flex.d-md-none.btn-block
- = render "shared/mobile_clone_panel"
-
- .project-clone-holder.d-none.d-md-inline-flex
- = render "projects/buttons/clone"
-
- if can?(current_user, :download_code, @project)
%nav.project-stats
.nav-links.quick-links
diff --git a/app/views/projects/buttons/_clone.html.haml b/app/views/projects/buttons/_clone.html.haml
index ed22573b23e..7507be52f44 100644
--- a/app/views/projects/buttons/_clone.html.haml
+++ b/app/views/projects/buttons/_clone.html.haml
@@ -1,11 +1,12 @@
- project = project || @project
+- dropdown_class = local_assigns.fetch(:dropdown_class, '')
-.git-clone-holder.js-git-clone-holder.input-group
- %a#clone-dropdown.input-group-text.btn.btn-primary.btn-xs.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
+.git-clone-holder.js-git-clone-holder
+ %a#clone-dropdown.btn.btn-primary.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
%span.append-right-4.js-clone-dropdown-label
= _('Clone')
= sprite_icon("arrow-down", css_class: "icon")
- %ul.p-3.dropdown-menu.dropdown-menu-right.dropdown-menu-large.dropdown-menu-selectable.clone-options-dropdown.qa-clone-options
+ %ul.p-3.dropdown-menu.dropdown-menu-large.dropdown-menu-selectable.clone-options-dropdown.qa-clone-options{ class: dropdown_class }
- if ssh_enabled?
%li
%label.label-bold
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index a9b6b397968..9e06358beba 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -11,9 +11,14 @@
- if @project.can_current_user_push_code?
%p.append-bottom-0
- = _('You can create files directly in GitLab using one of the following options.')
+ = _('You can get started by cloning the repository or start adding files to it with one of the following options.')
.project-buttons.qa-quick-actions
+ .project-clone-holder.d-block.d-md-none.mt-2.mr-2
+ = render "shared/mobile_clone_panel"
+
+ .project-clone-holder.d-none.d-md-inline-block.mt-2.mr-2.float-left
+ = render "projects/buttons/clone"
= render 'stat_anchor_list', anchors: @project.empty_repo_statistics_buttons
- if can?(current_user, :push_code, @project)
diff --git a/app/views/projects/network/show.json.erb b/app/views/projects/network/show.json.erb
index a0e82e891ff..a146d137c55 100644
--- a/app/views/projects/network/show.json.erb
+++ b/app/views/projects/network/show.json.erb
@@ -1,4 +1,4 @@
-<% self.formats = ["html"] %>
+<% self.formats = [:html] %>
<%= raw(
{
diff --git a/app/views/projects/releases/show.html.haml b/app/views/projects/releases/show.html.haml
new file mode 100644
index 00000000000..188262fb34c
--- /dev/null
+++ b/app/views/projects/releases/show.html.haml
@@ -0,0 +1,4 @@
+- add_to_breadcrumbs _("Releases"), project_releases_path(@project)
+- page_title @release.name
+
+#js-show-release-page{ data: { project_id: @project.id, tag_name: @release.tag } }
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
index 2d987744dfd..52a11642f32 100644
--- a/app/views/projects/tree/_tree_header.html.haml
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -101,3 +101,9 @@
= render "projects/buttons/xcode_link"
= render 'projects/buttons/download', project: @project, ref: @ref
+
+ .project-clone-holder.d-block.d-md-none.mt-sm-2.mt-md-0>
+ = render "shared/mobile_clone_panel"
+
+ .project-clone-holder.d-none.d-md-inline-block>
+ = render "projects/buttons/clone", dropdown_class: 'dropdown-menu-right'
diff --git a/app/views/shared/_mobile_clone_panel.html.haml b/app/views/shared/_mobile_clone_panel.html.haml
index 2887acf7cd7..df2ed5cfd97 100644
--- a/app/views/shared/_mobile_clone_panel.html.haml
+++ b/app/views/shared/_mobile_clone_panel.html.haml
@@ -4,7 +4,7 @@
.btn-group.mobile-git-clone.js-mobile-git-clone.btn-block
= clipboard_button(button_text: default_clone_label, text: default_url_to_repo(project), hide_button_icon: true, class: "btn-primary flex-fill bold justify-content-center input-group-text clone-dropdown-btn js-clone-dropdown-label")
- %button.btn.btn-primary.dropdown-toggle.js-dropdown-toggle.flex-grow-0.d-flex-center{ type: "button", data: { toggle: "dropdown" } }
+ %button.btn.btn-primary.dropdown-toggle.js-dropdown-toggle.flex-grow-0.d-flex-center.w-auto.ml-0{ type: "button", data: { toggle: "dropdown" } }
= sprite_icon("arrow-down", css_class: "dropdown-btn-icon icon")
%ul.dropdown-menu.dropdown-menu-selectable.dropdown-menu-right.clone-options-dropdown{ data: { dropdown: true } }
- if ssh_enabled?
diff --git a/app/workers/mail_scheduler/notification_service_worker.rb b/app/workers/mail_scheduler/notification_service_worker.rb
index 4130ce25878..ec659e39b24 100644
--- a/app/workers/mail_scheduler/notification_service_worker.rb
+++ b/app/workers/mail_scheduler/notification_service_worker.rb
@@ -26,49 +26,26 @@ module MailScheduler
end
def self.perform_async(*args)
- super(*Arguments.serialize(args))
+ super(*ActiveJob::Arguments.serialize(args))
end
private
- # If an argument is in the ActiveJob::Arguments::TYPE_WHITELIST list,
+ # This is copied over from https://github.com/rails/rails/blob/v6.0.1/activejob/lib/active_job/arguments.rb#L50
+ # because it is declared as a private constant
+ PERMITTED_TYPES = [NilClass, String, Integer, Float, BigDecimal, TrueClass, FalseClass].freeze
+
+ private_constant :PERMITTED_TYPES
+
+ # If an argument is in the PERMITTED_TYPES list,
# it means the argument cannot be deserialized.
# Which means there's something wrong with our code.
def check_arguments!(args)
args.each do |arg|
- if arg.class.in?(ActiveJob::Arguments::TYPE_WHITELIST)
+ if arg.class.in?(PERMITTED_TYPES)
raise(ArgumentError, "Argument `#{arg}` cannot be deserialized because of its type")
end
end
end
-
- # Permit ActionController::Parameters for serializable Hash
- #
- # Port of
- # https://github.com/rails/rails/commit/945fdd76925c9f615bf016717c4c8db2b2955357#diff-fc90ec41ef75be8b2259526fe1a8b663
- module Arguments
- include ActiveJob::Arguments
- extend self
-
- private
-
- def serialize_argument(argument)
- case argument
- when -> (arg) { arg.respond_to?(:permitted?) }
- serialize_hash(argument.to_h).tap do |result|
- result[WITH_INDIFFERENT_ACCESS_KEY] = serialize_argument(true)
- end
- else
- super
- end
- end
- end
-
- # Make sure we remove this patch starting with Rails 6.0.
- if Rails.version.start_with?('6.0')
- raise <<~MSG
- Please remove the patch `Arguments` module and use `ActiveJob::Arguments` again.
- MSG
- end
end
end
diff --git a/bin/setup b/bin/setup
index 94fd4d79775..5853b5ea875 100755
--- a/bin/setup
+++ b/bin/setup
@@ -1,6 +1,5 @@
#!/usr/bin/env ruby
require 'fileutils'
-include FileUtils
# path to your application root.
APP_ROOT = File.expand_path('..', __dir__)
@@ -9,24 +8,25 @@ def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==")
end
-chdir APP_ROOT do
- # This script is a starting point to setup your application.
+FileUtils.chdir APP_ROOT do
+ # This script is a way to setup or update your development environment automatically.
+ # This script is idempotent, so that you can run it at anytime and get an expectable outcome.
# Add necessary setup steps to this file.
puts '== Installing dependencies =='
system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install')
- # Install JavaScript dependencies if using Yarn
+ # Install JavaScript dependencies
# system('bin/yarn')
# puts "\n== Copying sample files =="
# unless File.exist?('config/database.yml')
- # cp 'config/database.yml.sample', 'config/database.yml'
+ # FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
# end
puts "\n== Preparing database =="
- system! 'bin/rails db:setup'
+ system! 'bin/rails db:prepare'
puts "\n== Removing old logs and tempfiles =="
system! 'bin/rails log:clear tmp:clear'
diff --git a/changelogs/unreleased/197973-staged-and-unstaged-modification-tooltip-for-file-with-staged-chan.yml b/changelogs/unreleased/197973-staged-and-unstaged-modification-tooltip-for-file-with-staged-chan.yml
new file mode 100644
index 00000000000..3b0a8d335ff
--- /dev/null
+++ b/changelogs/unreleased/197973-staged-and-unstaged-modification-tooltip-for-file-with-staged-chan.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unstaged and staged modification tooltip
+merge_request: 23847
+author:
+type: fixed
diff --git a/changelogs/unreleased/31034-upgrade-to-rails-6.yml b/changelogs/unreleased/31034-upgrade-to-rails-6.yml
new file mode 100644
index 00000000000..e1f6958d43a
--- /dev/null
+++ b/changelogs/unreleased/31034-upgrade-to-rails-6.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade to Rails 6
+merge_request: 19891
+author:
+type: other
diff --git a/changelogs/unreleased/39505-extend-the-ability-to-clone-a-dashboard-so-it-would-copy-the-custom.yml b/changelogs/unreleased/39505-extend-the-ability-to-clone-a-dashboard-so-it-would-copy-the-custom.yml
new file mode 100644
index 00000000000..256cef1115f
--- /dev/null
+++ b/changelogs/unreleased/39505-extend-the-ability-to-clone-a-dashboard-so-it-would-copy-the-custom.yml
@@ -0,0 +1,6 @@
+---
+title: Extends 'Duplicate dashboard' feature, by including custom metrics added to
+ GitLab-defined dashboards.
+merge_request: 21923
+author:
+type: added
diff --git a/changelogs/unreleased/gt-move-clone-button-to-the-tree-controls-area.yml b/changelogs/unreleased/gt-move-clone-button-to-the-tree-controls-area.yml
new file mode 100644
index 00000000000..ba6efd070ed
--- /dev/null
+++ b/changelogs/unreleased/gt-move-clone-button-to-the-tree-controls-area.yml
@@ -0,0 +1,5 @@
+---
+title: Move the clone button to the tree controls area
+merge_request: 17752
+author: Ablay Keldibek
+type: changed
diff --git a/config/application.rb b/config/application.rb
index 304cd72e806..e8cc35aed2a 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -1,7 +1,9 @@
require_relative 'boot'
-# Based on https://github.com/rails/rails/blob/v5.2.3/railties/lib/rails/all.rb
+# Based on https://github.com/rails/rails/blob/v6.0.1/railties/lib/rails/all.rb
# Only load the railties we need instead of loading everything
+require 'rails'
+
require 'active_record/railtie'
require 'action_controller/railtie'
require 'action_view/railtie'
diff --git a/config/environment.rb b/config/environment.rb
index 7e55c7803d3..426333bb469 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -1,6 +1,5 @@
-# Load the rails application
-
+# Load the Rails application.
require_relative 'application'
-# Initialize the rails application
+# Initialize the Rails application.
Rails.application.initialize!
diff --git a/config/environments/development.rb b/config/environments/development.rb
index dc804197fef..960892a1dc2 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -50,4 +50,8 @@ Rails.application.configure do
# BetterErrors live shell (REPL) on every stack frame
BetterErrors::Middleware.allow_ip!("127.0.0.1/0")
+
+ # Use an evented file watcher to asynchronously detect changes in source code,
+ # routes, locales, etc. This feature depends on the listen gem.
+ config.file_watcher = ActiveSupport::EventedFileUpdateChecker
end
diff --git a/config/initializers/active_record_data_types.rb b/config/initializers/active_record_data_types.rb
index 2b3f58330e3..3fa999e9908 100644
--- a/config/initializers/active_record_data_types.rb
+++ b/config/initializers/active_record_data_types.rb
@@ -24,10 +24,11 @@ module RegisterDateTimeWithTimeZone
def initialize_type_map(mapping = type_map)
super mapping
- mapping.register_type 'timestamptz' do |_, _, sql_type|
- precision = extract_precision(sql_type)
- ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID::DateTimeWithTimeZone.new(precision: precision)
- end
+ register_class_with_precision(
+ mapping,
+ 'timestamptz',
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID::DateTimeWithTimeZone
+ )
end
end
@@ -46,3 +47,5 @@ end
if (ActiveRecord::Base.connection.active? rescue false)
ActiveRecord::Base.connection.send :reload_type_map
end
+
+ActiveRecord::Base.time_zone_aware_types += [:datetime_with_timezone]
diff --git a/config/initializers/active_record_preloader.rb b/config/initializers/active_record_preloader.rb
index a293909149e..d585ecda307 100644
--- a/config/initializers/active_record_preloader.rb
+++ b/config/initializers/active_record_preloader.rb
@@ -6,7 +6,7 @@ module ActiveRecord
self
end
- def self.run(preloader)
+ def self.run
end
def self.preloaded_records
diff --git a/config/initializers/active_record_query_cache.rb b/config/initializers/active_record_query_cache.rb
deleted file mode 100644
index 61505a1edd3..00000000000
--- a/config/initializers/active_record_query_cache.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-# frozen_string_literal: true
-
-ActiveRecord::ConnectionAdapters::ConnectionPool.prepend Gitlab::Patch::ActiveRecordQueryCache
diff --git a/config/initializers/config_initializers_active_record_locking.rb b/config/initializers/config_initializers_active_record_locking.rb
index 915247826e9..9f9908283c6 100644
--- a/config/initializers/config_initializers_active_record_locking.rb
+++ b/config/initializers/config_initializers_active_record_locking.rb
@@ -26,7 +26,7 @@ module ActiveRecord
locking_column => possible_previous_lock_value,
self.class.primary_key => id_in_database
).update_all(
- attributes_with_values_for_update(attribute_names)
+ attributes_with_values(attribute_names)
)
if affected_rows != 1
diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb
index 608d0401a96..c19fb65017f 100644
--- a/config/initializers/content_security_policy.rb
+++ b/config/initializers/content_security_policy.rb
@@ -12,4 +12,5 @@ if csp_settings['enabled']
Rails.application.config.content_security_policy_report_only = csp_settings['report_only']
Rails.application.config.content_security_policy_nonce_generator = ->(request) { SecureRandom.base64(16) }
+ Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
end
diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb
index 54516e3f23d..a04d5044f4e 100644
--- a/config/initializers/cookies_serializer.rb
+++ b/config/initializers/cookies_serializer.rb
@@ -1,3 +1,4 @@
# Be sure to restart your server when you modify this file.
+Rails.application.config.action_dispatch.use_cookies_with_metadata = false
Rails.application.config.action_dispatch.cookies_serializer = :hybrid
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 68568db1326..352184ed746 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -166,7 +166,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
- resources :releases, only: [:index, :edit], param: :tag, constraints: { tag: %r{[^/]+} } do
+ resources :releases, only: [:index, :show, :edit], param: :tag, constraints: { tag: %r{[^/]+} } do
member do
get :evidence
end
diff --git a/db/schema.rb b/db/schema.rb
index 88c456322dd..cb27967e69c 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -2,11 +2,11 @@
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
-# Note that this schema.rb definition is the authoritative source for your
-# database schema. If you need to create the application database on another
-# system, you should be using db:schema:load, not running all the migrations
-# from scratch. The latter is a flawed and unsustainable approach (the more migrations
-# you'll amass, the slower it'll run and the greater likelihood for issues).
+# This file is the source Rails uses to define your schema when running `rails
+# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
+# be faster and is potentially less error prone than running all of your
+# migrations from scratch. Old migrations may fail to apply correctly if those
+# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.
diff --git a/doc/development/packages.md b/doc/development/packages.md
index 8722bb1e710..c433864600f 100644
--- a/doc/development/packages.md
+++ b/doc/development/packages.md
@@ -7,7 +7,7 @@ See already supported package types in [Packages documentation](../administratio
Since GitLab packages' UI is pretty generic, it is possible to add basic new
package system support with solely backend changes. This guide is superficial and does
not cover the way the code should be written. However, you can find a good example
-by looking at existing merge requests with Maven and NPM support:
+by looking at merge requests with Maven and NPM support:
- [NPM registry support](https://gitlab.com/gitlab-org/gitlab/merge_requests/8673).
- [Conan repository](https://gitlab.com/gitlab-org/gitlab/issues/8248).
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index aa6071e6099..688b1cc6f17 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -434,7 +434,7 @@ module API
def present_disk_file!(path, filename, content_type = 'application/octet-stream')
filename ||= File.basename(path)
- header['Content-Disposition'] = ::Gitlab::ContentDisposition.format(disposition: 'attachment', filename: filename)
+ header['Content-Disposition'] = ActionDispatch::Http::ContentDisposition.format(disposition: 'attachment', filename: filename)
header['Content-Transfer-Encoding'] = 'binary'
content_type content_type
@@ -542,7 +542,7 @@ module API
def send_git_blob(repository, blob)
env['api.format'] = :txt
content_type 'text/plain'
- header['Content-Disposition'] = ::Gitlab::ContentDisposition.format(disposition: 'inline', filename: blob.name)
+ header['Content-Disposition'] = ActionDispatch::Http::ContentDisposition.format(disposition: 'inline', filename: blob.name)
# Let Workhorse examine the content and determine the better content disposition
header[Gitlab::Workhorse::DETECT_HEADER] = "true"
diff --git a/lib/gitlab/action_view_output/context.rb b/lib/gitlab/action_view_output/context.rb
deleted file mode 100644
index 9fbc9811636..00000000000
--- a/lib/gitlab/action_view_output/context.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-# This file was simplified from https://raw.githubusercontent.com/rails/rails/195f39804a7a4a0034f25e8704220e03d95a752a/actionview/lib/action_view/context.rb.
-#
-# It is only needed by modules that need to call ActionView helper
-# methods (e.g. those in
-# https://github.com/rails/rails/tree/c4d3e202e10ae627b3b9c34498afb45450652421/actionview/lib/action_view/helpers)
-# to generate tags outside of a Rails controller (e.g. API, Sidekiq,
-# etc.).
-#
-# In Rails 5, ActionView::Context automatically includes CompiledTemplates.
-# This means that any module that includes ActionView::Context is now a descendant
-# of CompiledTemplates.
-#
-# When a partial is rendered for the first time, it runs
-# Module#module_eval, which will evaluate a string source that defines a
-# new method. For example:
-#
-# def _app_views_profiles_show_html_haml___1285955918103175884_70307801785400(local_assigns, output_buffer)
-# "hello world"
-# end
-#
-# When a new method is defined, the Ruby interpreter clears the method
-# cache for all descendants, and all methods for those modules will have
-# to be redefined. This can lead to a significant performance penalty.
-#
-# Rails 6 fixes this behavior by moving out the `include
-# CompiledTemplates` into ActionView::Base so that including `ActionView::Context`
-# doesn't quietly affect other modules in this way.
-
-if Rails::VERSION::STRING.start_with?('6')
- raise 'This module is no longer needed in Rails 6. Use ActionView::Context instead.'
-end
-
-module Gitlab
- module ActionViewOutput
- module Context
- attr_accessor :output_buffer, :view_flow
- end
- end
-end
diff --git a/lib/gitlab/ci/config/external/file/template.rb b/lib/gitlab/ci/config/external/file/template.rb
index db56f6a9b00..c4b4a7a0a73 100644
--- a/lib/gitlab/ci/config/external/file/template.rb
+++ b/lib/gitlab/ci/config/external/file/template.rb
@@ -33,7 +33,7 @@ module Gitlab
def template_name
return unless template_name_valid?
- location.first(-SUFFIX.length)
+ location.delete_suffix(SUFFIX)
end
def template_name_valid?
diff --git a/lib/gitlab/content_disposition.rb b/lib/gitlab/content_disposition.rb
deleted file mode 100644
index ff6154a5b26..00000000000
--- a/lib/gitlab/content_disposition.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-# This ports ActionDispatch::Http::ContentDisposition (https://github.com/rails/rails/pull/33829,
-# which will be available in Rails 6.
-module Gitlab
- class ContentDisposition # :nodoc:
- # Make sure we remove this patch starting with Rails 6.0.
- if Rails.version.start_with?('6.0')
- raise <<~MSG
- Please remove this file and use `ActionDispatch::Http::ContentDisposition` instead.
- MSG
- end
-
- def self.format(disposition:, filename:)
- new(disposition: disposition, filename: filename).to_s
- end
-
- attr_reader :disposition, :filename
-
- def initialize(disposition:, filename:)
- @disposition = disposition
- @filename = filename
- end
-
- # rubocop:disable Style/VariableInterpolation
- TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!#$+.^_`|~-]/.freeze
-
- def ascii_filename
- 'filename="' + percent_escape(::I18n.transliterate(filename), TRADITIONAL_ESCAPED_CHAR) + '"'
- end
-
- RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!#$&+.^_`|~-]/.freeze
- # rubocop:enable Style/VariableInterpolation
-
- def utf8_filename
- "filename*=UTF-8''" + percent_escape(filename, RFC_5987_ESCAPED_CHAR)
- end
-
- def to_s
- if filename
- "#{disposition}; #{ascii_filename}; #{utf8_filename}"
- else
- "#{disposition}"
- end
- end
-
- private
-
- def percent_escape(string, pattern)
- string.gsub(pattern) do |char|
- char.bytes.map { |byte| "%%%02X" % byte }.join
- end
- end
- end
-end
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index 82ec740ade1..a614e68703c 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -204,15 +204,16 @@ module Gitlab
# pool_size - The size of the DB pool.
# host - An optional host name to use instead of the default one.
def self.create_connection_pool(pool_size, host = nil, port = nil)
- # See activerecord-4.2.7.1/lib/active_record/connection_adapters/connection_specification.rb
env = Rails.env
- original_config = ActiveRecord::Base.configurations
+ original_config = ActiveRecord::Base.configurations.to_h
env_config = original_config[env].merge('pool' => pool_size)
env_config['host'] = host if host
env_config['port'] = port if port
- config = original_config.merge(env => env_config)
+ config = ActiveRecord::DatabaseConfigurations.new(
+ original_config.merge(env => env_config)
+ )
spec =
ActiveRecord::
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index b53e01e6ff2..3b6684b861c 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -382,7 +382,7 @@ module Gitlab
count_arel = table.project(Arel.star.count.as('count'))
count_arel = yield table, count_arel if block_given?
- total = exec_query(count_arel.to_sql).to_hash.first['count'].to_i
+ total = exec_query(count_arel.to_sql).to_a.first['count'].to_i
return if total == 0
@@ -399,7 +399,7 @@ module Gitlab
start_arel = table.project(table[:id]).order(table[:id].asc).take(1)
start_arel = yield table, start_arel if block_given?
- start_id = exec_query(start_arel.to_sql).to_hash.first['id'].to_i
+ start_id = exec_query(start_arel.to_sql).to_a.first['id'].to_i
loop do
stop_arel = table.project(table[:id])
@@ -409,7 +409,7 @@ module Gitlab
.skip(batch_size)
stop_arel = yield table, stop_arel if block_given?
- stop_row = exec_query(stop_arel.to_sql).to_hash.first
+ stop_row = exec_query(stop_arel.to_sql).to_a.first
update_arel = Arel::UpdateManager.new
.table(table)
diff --git a/lib/gitlab/patch/active_record_query_cache.rb b/lib/gitlab/patch/active_record_query_cache.rb
deleted file mode 100644
index d6b649cdea7..00000000000
--- a/lib/gitlab/patch/active_record_query_cache.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-# Fixes a bug where the query cache isn't aware of the shared
-# ActiveRecord connection used in tests
-# https://github.com/rails/rails/issues/36587
-
-# To be removed with https://gitlab.com/gitlab-org/gitlab-foss/issues/64413
-
-module Gitlab
- module Patch
- module ActiveRecordQueryCache
- # rubocop:disable Gitlab/ModuleWithInstanceVariables
- def enable_query_cache!
- @query_cache_enabled[connection_cache_key(current_thread)] = true
- connection.enable_query_cache! if active_connection?
- end
-
- def disable_query_cache!
- @query_cache_enabled.delete connection_cache_key(current_thread)
- connection.disable_query_cache! if active_connection?
- end
-
- def query_cache_enabled
- @query_cache_enabled[connection_cache_key(current_thread)]
- end
-
- def active_connection?
- @thread_cached_conns[connection_cache_key(current_thread)]
- end
-
- private
-
- def current_thread
- @lock_thread || Thread.current
- end
- # rubocop:enable Gitlab/ModuleWithInstanceVariables
- end
- end
-end
diff --git a/lib/gitlab/query_limiting/middleware.rb b/lib/gitlab/query_limiting/middleware.rb
index f6ffbfe2645..714fe42884a 100644
--- a/lib/gitlab/query_limiting/middleware.rb
+++ b/lib/gitlab/query_limiting/middleware.rb
@@ -37,10 +37,10 @@ module Gitlab
controller = env[CONTROLLER_KEY]
action = "#{controller.class.name}##{controller.action_name}"
- if controller.content_type == 'text/html'
+ if controller.media_type == 'text/html'
action
else
- "#{action} (#{controller.content_type})"
+ "#{action} (#{controller.media_type})"
end
end
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index 55bee3a2dc7..6d369b69a37 100644
--- a/locale/ar_SA/gitlab.po
+++ b/locale/ar_SA/gitlab.po
@@ -20432,9 +20432,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index 8643995d451..0b3ee37cbc6 100644
--- a/locale/bg/gitlab.po
+++ b/locale/bg/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr "Без звезда"
diff --git a/locale/bn_BD/gitlab.po b/locale/bn_BD/gitlab.po
index 883057b9f9d..3807e1da453 100644
--- a/locale/bn_BD/gitlab.po
+++ b/locale/bn_BD/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/bn_IN/gitlab.po b/locale/bn_IN/gitlab.po
index e530dec967f..5703e27cb8b 100644
--- a/locale/bn_IN/gitlab.po
+++ b/locale/bn_IN/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index 9eeba969661..7f509f06f52 100644
--- a/locale/ca_ES/gitlab.po
+++ b/locale/ca_ES/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index 7c424b45001..60dfcbbeb53 100644
--- a/locale/cs_CZ/gitlab.po
+++ b/locale/cs_CZ/gitlab.po
@@ -20226,9 +20226,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index c4c9680ed06..73d1f97c9ef 100644
--- a/locale/cy_GB/gitlab.po
+++ b/locale/cy_GB/gitlab.po
@@ -20432,9 +20432,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index 338d82e86a8..24777c04104 100644
--- a/locale/da_DK/gitlab.po
+++ b/locale/da_DK/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index d1f013f3317..2ca8f20d2c2 100644
--- a/locale/de/gitlab.po
+++ b/locale/de/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr "Nicht vorgemerkt"
msgid "Unstaged %{type}"
msgstr "Nicht vorgemerkt %{type}"
-msgid "Unstaged and staged %{type}"
-msgstr "Nicht vorgemerkt und vorgemerkt %{type}"
-
msgid "Unstar"
msgstr "Entfavorisieren"
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index b52569855aa..204c779fba0 100644
--- a/locale/el_GR/gitlab.po
+++ b/locale/el_GR/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index 294b41a3ba7..82cc7c0116d 100644
--- a/locale/eo/gitlab.po
+++ b/locale/eo/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr "Malsteligi"
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index 9d8779cc77c..2614f39949c 100644
--- a/locale/es/gitlab.po
+++ b/locale/es/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr "No Destacar"
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index cbd55440d7d..56689d244b9 100644
--- a/locale/et_EE/gitlab.po
+++ b/locale/et_EE/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/fa_IR/gitlab.po b/locale/fa_IR/gitlab.po
index c5e260edfc7..52fa0da2fe2 100644
--- a/locale/fa_IR/gitlab.po
+++ b/locale/fa_IR/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index f6a85b42e75..e94bd85b66a 100644
--- a/locale/fil_PH/gitlab.po
+++ b/locale/fil_PH/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index ec1bc4410bc..c03096687b1 100644
--- a/locale/fr/gitlab.po
+++ b/locale/fr/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr "Désindexé"
msgid "Unstaged %{type}"
msgstr "Désindexation de %{type}"
-msgid "Unstaged and staged %{type}"
-msgstr "%{type} non-indéxés et indexés"
-
msgid "Unstar"
msgstr "Supprimer des favoris"
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index d988fcd6dff..52f9231dffa 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -20259,9 +20259,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
@@ -21553,9 +21550,6 @@ msgstr ""
msgid "You can create a new one or check them in your Personal Access Tokens settings %{pat_link}"
msgstr ""
-msgid "You can create files directly in GitLab using one of the following options."
-msgstr ""
-
msgid "You can create new ones at your %{pat_link_start}Personal Access Tokens%{pat_link_end} settings"
msgstr ""
@@ -21571,6 +21565,9 @@ msgstr ""
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
msgstr ""
+msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
+msgstr ""
+
msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index c195b59f053..10f3351bf68 100644
--- a/locale/gl_ES/gitlab.po
+++ b/locale/gl_ES/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index f66b860ccbf..5485117f27b 100644
--- a/locale/he_IL/gitlab.po
+++ b/locale/he_IL/gitlab.po
@@ -20226,9 +20226,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
index 34714faeb8a..df702aa71b6 100644
--- a/locale/hi_IN/gitlab.po
+++ b/locale/hi_IN/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
index 6f11504b6d4..34e04e736c0 100644
--- a/locale/hr_HR/gitlab.po
+++ b/locale/hr_HR/gitlab.po
@@ -20123,9 +20123,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index 1479fc5dcc2..7eff6234233 100644
--- a/locale/hu_HU/gitlab.po
+++ b/locale/hu_HU/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index 4f7d8501121..37ed84e05c9 100644
--- a/locale/id_ID/gitlab.po
+++ b/locale/id_ID/gitlab.po
@@ -19917,9 +19917,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index 3ae19b312f5..04061fbd995 100644
--- a/locale/it/gitlab.po
+++ b/locale/it/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr "Unstaged"
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index 8455088e6e2..60da219ecdf 100644
--- a/locale/ja/gitlab.po
+++ b/locale/ja/gitlab.po
@@ -19917,9 +19917,6 @@ msgstr "ステージを取り消し"
msgid "Unstaged %{type}"
msgstr "ステージを取り消し %{type}"
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr "スターを外す"
diff --git a/locale/ka_GE/gitlab.po b/locale/ka_GE/gitlab.po
index fea8c3eee58..6df25e07f22 100644
--- a/locale/ka_GE/gitlab.po
+++ b/locale/ka_GE/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index e15b0917490..16aa0ab358a 100644
--- a/locale/ko/gitlab.po
+++ b/locale/ko/gitlab.po
@@ -19917,9 +19917,6 @@ msgstr "스테이징 안됨"
msgid "Unstaged %{type}"
msgstr "%{type} 스테이징 취소"
-msgid "Unstaged and staged %{type}"
-msgstr "스테이징 취소, 그리고 %{type} 스테이징"
-
msgid "Unstar"
msgstr "별표 제거"
diff --git a/locale/ku_TR/gitlab.po b/locale/ku_TR/gitlab.po
index a0fd9e8c7f5..0f27e379c58 100644
--- a/locale/ku_TR/gitlab.po
+++ b/locale/ku_TR/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/ml_IN/gitlab.po b/locale/ml_IN/gitlab.po
index c073b1b257b..12a67356bf3 100644
--- a/locale/ml_IN/gitlab.po
+++ b/locale/ml_IN/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index f167dc7072c..45fec0a64ad 100644
--- a/locale/mn_MN/gitlab.po
+++ b/locale/mn_MN/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index 6a147fc6363..a7d1bc4b0c1 100644
--- a/locale/nb_NO/gitlab.po
+++ b/locale/nb_NO/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index 55e3d2df9f9..ca5873c98fe 100644
--- a/locale/nl_NL/gitlab.po
+++ b/locale/nl_NL/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
index ed2b511c66d..04ee1ebc008 100644
--- a/locale/pa_IN/gitlab.po
+++ b/locale/pa_IN/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index dec90aa1adc..b74c006780f 100644
--- a/locale/pl_PL/gitlab.po
+++ b/locale/pl_PL/gitlab.po
@@ -20226,9 +20226,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index 8ec714b5ee2..55ff541e69c 100644
--- a/locale/pt_BR/gitlab.po
+++ b/locale/pt_BR/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr "Fora da lista de commit"
msgid "Unstaged %{type}"
msgstr "%{type} fora da lista para commit"
-msgid "Unstaged and staged %{type}"
-msgstr "%{type} dentro e fora da lista para commit"
-
msgid "Unstar"
msgstr "Desmarcar como favorito"
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index 213a84dc9f7..5b22442d85c 100644
--- a/locale/pt_PT/gitlab.po
+++ b/locale/pt_PT/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index fa8ec51ab73..413ec40148f 100644
--- a/locale/ro_RO/gitlab.po
+++ b/locale/ro_RO/gitlab.po
@@ -20123,9 +20123,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index 0314348e949..9b0fa19f34c 100644
--- a/locale/ru/gitlab.po
+++ b/locale/ru/gitlab.po
@@ -20226,9 +20226,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr "Убрать из избранного"
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index 4f2eab215dd..53beb67f773 100644
--- a/locale/sk_SK/gitlab.po
+++ b/locale/sk_SK/gitlab.po
@@ -20226,9 +20226,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index a1947bd3429..b11e76c17bb 100644
--- a/locale/sq_AL/gitlab.po
+++ b/locale/sq_AL/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index a632fb4133b..b517d1e7072 100644
--- a/locale/sr_CS/gitlab.po
+++ b/locale/sr_CS/gitlab.po
@@ -20123,9 +20123,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index 7955ce986e2..99def38e91c 100644
--- a/locale/sr_SP/gitlab.po
+++ b/locale/sr_SP/gitlab.po
@@ -20123,9 +20123,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
index f589ee8979d..39297cc5f37 100644
--- a/locale/sv_SE/gitlab.po
+++ b/locale/sv_SE/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
index 194d07187c7..708d10009b1 100644
--- a/locale/sw_KE/gitlab.po
+++ b/locale/sw_KE/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index c2913b7d9e7..3e3b9df23d7 100644
--- a/locale/tr_TR/gitlab.po
+++ b/locale/tr_TR/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr "Yıldızı kaldır"
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index cb6c4de1e03..9f39744dfe0 100644
--- a/locale/uk/gitlab.po
+++ b/locale/uk/gitlab.po
@@ -20226,9 +20226,6 @@ msgstr "Неіндексовано"
msgid "Unstaged %{type}"
msgstr "Неіндексовані %{type}"
-msgid "Unstaged and staged %{type}"
-msgstr "Неіндексовані та проіндексовані %{type}"
-
msgid "Unstar"
msgstr "Видалити із обраних"
diff --git a/locale/ur_PK/gitlab.po b/locale/ur_PK/gitlab.po
index 52d11fe362e..c93bd7c16ff 100644
--- a/locale/ur_PK/gitlab.po
+++ b/locale/ur_PK/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/uz_UZ/gitlab.po b/locale/uz_UZ/gitlab.po
index b05679363d7..d0bdb90172e 100644
--- a/locale/uz_UZ/gitlab.po
+++ b/locale/uz_UZ/gitlab.po
@@ -20020,9 +20020,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/vi_VN/gitlab.po b/locale/vi_VN/gitlab.po
index 4e1e5056830..4d0d950f50b 100644
--- a/locale/vi_VN/gitlab.po
+++ b/locale/vi_VN/gitlab.po
@@ -19917,9 +19917,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index a07659ed383..7b93e650862 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -19917,9 +19917,6 @@ msgstr "未暂存"
msgid "Unstaged %{type}"
msgstr "未暂存的 %{type}"
-msgid "Unstaged and staged %{type}"
-msgstr "已暂存和未暂存的 %{type}"
-
msgid "Unstar"
msgstr "取消星标"
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index a40386c1c90..6053a974db0 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -19917,9 +19917,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr "取消星標"
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index 09494baf020..6d2ddbea1d9 100644
--- a/locale/zh_TW/gitlab.po
+++ b/locale/zh_TW/gitlab.po
@@ -19917,9 +19917,6 @@ msgstr ""
msgid "Unstaged %{type}"
msgstr ""
-msgid "Unstaged and staged %{type}"
-msgstr ""
-
msgid "Unstar"
msgstr ""
diff --git a/rubocop/cop/include_action_view_context.rb b/rubocop/cop/include_action_view_context.rb
deleted file mode 100644
index 52c84a711c9..00000000000
--- a/rubocop/cop/include_action_view_context.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module RuboCop
- module Cop
- # Cop that makes sure workers include `::Gitlab::ActionViewOutput::Context`, not `ActionView::Context`.
- class IncludeActionViewContext < RuboCop::Cop::Cop
- MSG = 'Include `::Gitlab::ActionViewOutput::Context`, not `ActionView::Context`, for Rails 5.'.freeze
-
- def_node_matcher :includes_action_view_context?, <<~PATTERN
- (send nil? :include (const (const nil? :ActionView) :Context))
- PATTERN
-
- def on_send(node)
- return unless includes_action_view_context?(node)
-
- add_offense(node.arguments.first, location: :expression)
- end
-
- def autocorrect(node)
- lambda do |corrector|
- corrector.replace(node.source_range, '::Gitlab::ActionViewOutput::Context')
- end
- end
- end
- end
-end
diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb
index 1479dc3384a..d39683c271f 100644
--- a/rubocop/rubocop.rb
+++ b/rubocop/rubocop.rb
@@ -5,7 +5,6 @@ require_relative 'cop/gitlab/httparty'
require_relative 'cop/gitlab/finder_with_find_by'
require_relative 'cop/gitlab/union'
require_relative 'cop/gitlab/rails_logger'
-require_relative 'cop/include_action_view_context'
require_relative 'cop/include_sidekiq_worker'
require_relative 'cop/safe_params'
require_relative 'cop/active_record_association_reload'
diff --git a/spec/config/application_spec.rb b/spec/config/application_spec.rb
index 01ed81964c3..994cea4c84f 100644
--- a/spec/config/application_spec.rb
+++ b/spec/config/application_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
describe Gitlab::Application do # rubocop:disable RSpec/FilePath
using RSpec::Parameterized::TableSyntax
- FILTERED_PARAM = ActionDispatch::Http::ParameterFilter::FILTERED
+ FILTERED_PARAM = ActiveSupport::ParameterFilter::FILTERED
context 'when parameters are logged' do
describe 'rails does not leak confidential parameters' do
diff --git a/spec/controllers/concerns/metrics_dashboard_spec.rb b/spec/controllers/concerns/metrics_dashboard_spec.rb
index 6ab02057412..466021d6ecd 100644
--- a/spec/controllers/concerns/metrics_dashboard_spec.rb
+++ b/spec/controllers/concerns/metrics_dashboard_spec.rb
@@ -23,7 +23,7 @@ describe MetricsDashboard do
routes.draw { get "metrics_dashboard" => "anonymous#metrics_dashboard" }
response = get :metrics_dashboard, format: :json
- JSON.parse(response.parsed_body)
+ response.parsed_body
end
context 'when no parameters are provided' do
diff --git a/spec/controllers/concerns/send_file_upload_spec.rb b/spec/controllers/concerns/send_file_upload_spec.rb
index 4110be721ad..3cfb7b5a488 100644
--- a/spec/controllers/concerns/send_file_upload_spec.rb
+++ b/spec/controllers/concerns/send_file_upload_spec.rb
@@ -59,11 +59,9 @@ describe SendFileUpload do
let(:params) { { disposition: 'inline', attachment: filename } }
it 'sends a file with inline disposition' do
- # Notice the filename= is omitted from the disposition; this is because
- # Rails 5 will append this header in send_file
expected_params = {
filename: 'test.png',
- disposition: "inline; filename*=UTF-8''test.png"
+ disposition: 'inline'
}
expect(controller).to receive(:send_file).with(uploader.path, expected_params)
@@ -76,34 +74,16 @@ describe SendFileUpload do
let(:params) { { attachment: filename } }
it 'sends a file with content-type of text/plain' do
- # Notice the filename= is omitted from the disposition; this is because
- # Rails 5 will append this header in send_file
expected_params = {
content_type: 'text/plain',
filename: 'test.js',
- disposition: "attachment; filename*=UTF-8''test.js"
+ disposition: 'attachment'
}
expect(controller).to receive(:send_file).with(uploader.path, expected_params)
subject
end
- context 'with non-ASCII encoded filename' do
- let(:filename) { 'テスト.txt' }
-
- # Notice the filename= is omitted from the disposition; this is because
- # Rails 5 will append this header in send_file
- it 'sends content-disposition for non-ASCII encoded filenames' do
- expected_params = {
- filename: filename,
- disposition: "attachment; filename*=UTF-8''%E3%83%86%E3%82%B9%E3%83%88.txt"
- }
- expect(controller).to receive(:send_file).with(uploader.path, expected_params)
-
- subject
- end
- end
-
context 'with a proxied file in object storage' do
before do
stub_uploads_object_storage(uploader: uploader_class)
diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb
index 7aaaa363faa..c59983d5138 100644
--- a/spec/controllers/projects/artifacts_controller_spec.rb
+++ b/spec/controllers/projects/artifacts_controller_spec.rb
@@ -138,14 +138,14 @@ describe Projects::ArtifactsController do
let(:filename) { job.artifacts_file.filename }
it 'sends the artifacts file' do
- # Notice the filename= is omitted from the disposition; this is because
- # Rails 5 will append this header in send_file
expect(controller).to receive(:send_file)
.with(
job.artifacts_file.file.path,
- hash_including(disposition: %Q(attachment; filename*=UTF-8''#{filename}))).and_call_original
+ hash_including(disposition: 'attachment', filename: filename)).and_call_original
download_artifact
+
+ expect(response.headers['Content-Disposition']).to eq(%Q(attachment; filename="#{filename}"; filename*=UTF-8''#{filename}))
end
end
@@ -170,13 +170,13 @@ describe Projects::ArtifactsController do
end
it 'sends the codequality report' do
- # Notice the filename= is omitted from the disposition; this is because
- # Rails 5 will append this header in send_file
expect(controller).to receive(:send_file)
.with(job.job_artifacts_codequality.file.path,
- hash_including(disposition: %Q(attachment; filename*=UTF-8''#{filename}))).and_call_original
+ hash_including(disposition: 'attachment', filename: filename)).and_call_original
download_artifact(file_type: file_type)
+
+ expect(response.headers['Content-Disposition']).to eq(%Q(attachment; filename="#{filename}"; filename*=UTF-8''#{filename}))
end
end
diff --git a/spec/controllers/projects/releases_controller_spec.rb b/spec/controllers/projects/releases_controller_spec.rb
index 6abb58e1aa6..a03fabad2de 100644
--- a/spec/controllers/projects/releases_controller_spec.rb
+++ b/spec/controllers/projects/releases_controller_spec.rb
@@ -127,13 +127,13 @@ describe Projects::ReleasesController do
sign_in(user)
end
- let!(:release) { create(:release, project: project) }
+ let(:release) { create(:release, project: project) }
let(:tag) { CGI.escape(release.tag) }
it_behaves_like 'successful request'
context 'when tag name contains slash' do
- let!(:release) { create(:release, project: project, tag: 'awesome/v1.0') }
+ let(:release) { create(:release, project: project, tag: 'awesome/v1.0') }
let(:tag) { CGI.escape(release.tag) }
it_behaves_like 'successful request'
@@ -145,7 +145,6 @@ describe Projects::ReleasesController do
end
context 'when release does not exist' do
- let!(:release) { }
let(:tag) { 'non-existent-tag' }
it_behaves_like 'not found'
@@ -158,6 +157,47 @@ describe Projects::ReleasesController do
end
end
+ describe 'GET #show' do
+ subject do
+ get :show, params: { namespace_id: project.namespace, project_id: project, tag: tag }
+ end
+
+ before do
+ sign_in(user)
+ end
+
+ let(:release) { create(:release, project: project) }
+ let(:tag) { CGI.escape(release.tag) }
+
+ it_behaves_like 'successful request'
+
+ context 'when tag name contains slash' do
+ let(:release) { create(:release, project: project, tag: 'awesome/v1.0') }
+ let(:tag) { CGI.escape(release.tag) }
+
+ it_behaves_like 'successful request'
+
+ it 'is accesible at a URL encoded path' do
+ expect(project_release_path(project, release))
+ .to eq("/#{project.namespace.path}/#{project.name}/-/releases/awesome%252Fv1.0")
+ end
+ end
+
+ context 'when feature flag `release_show_page` is disabled' do
+ before do
+ stub_feature_flags(release_show_page: false)
+ end
+
+ it_behaves_like 'not found'
+ end
+
+ context 'when release does not exist' do
+ let(:tag) { 'non-existent-tag' }
+
+ it_behaves_like 'not found'
+ end
+ end
+
describe 'GET #evidence' do
let_it_be(:tag_name) { "v1.1.0-evidence" }
let!(:release) { create(:release, :with_evidence, project: project, tag: tag_name) }
diff --git a/spec/controllers/uploads_controller_spec.rb b/spec/controllers/uploads_controller_spec.rb
index 69e2c085659..f42d0560e80 100644
--- a/spec/controllers/uploads_controller_spec.rb
+++ b/spec/controllers/uploads_controller_spec.rb
@@ -649,7 +649,7 @@ describe UploadsController do
get :show, params: { model: 'appearance', mounted_as: 'favicon', id: appearance.id, filename: 'dk.png' }
expect(response).to have_gitlab_http_status(:ok)
- expect(response.header['Content-Disposition']).to end_with 'filename="dk.png"'
+ expect(response.header['Content-Disposition']).to include('filename="dk.png"')
end
end
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index 17754400b91..d12843d7150 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -604,7 +604,7 @@ describe 'Merge request > User sees merge widget', :js do
click_button 'addTest'
expect(page).to have_content('6.66')
- expect(page).to have_content(sample_java_failed_message.gsub!(/\s+/, ' ').strip)
+ expect(page).to have_content(sample_java_failed_message.gsub(/\s+/, ' ').strip)
end
end
end
@@ -649,7 +649,7 @@ describe 'Merge request > User sees merge widget', :js do
click_button 'Test#sum when a is 1 and b is 3 returns summary'
expect(page).to have_content('2.22')
- expect(page).to have_content(sample_rspec_failed_message.gsub!(/\s+/, ' ').strip)
+ expect(page).to have_content(sample_rspec_failed_message.gsub(/\s+/, ' ').strip)
end
end
end
diff --git a/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb b/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb
index 254ebfb839a..fb70076fcf1 100644
--- a/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb
+++ b/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb
@@ -9,7 +9,7 @@ describe "User downloads artifacts" do
shared_examples "downloading" do
it "downloads the zip" do
- expect(page.response_headers["Content-Disposition"]).to eq(%Q{attachment; filename*=UTF-8''#{job.artifacts_file.filename}; filename="#{job.artifacts_file.filename}"})
+ expect(page.response_headers['Content-Disposition']).to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}})
expect(page.response_headers['Content-Transfer-Encoding']).to eq("binary")
expect(page.response_headers['Content-Type']).to eq("application/zip")
expect(page.source.b).to eq(job.artifacts_file.file.read.b)
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index f9ff076a416..a17793bc6d6 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -346,7 +346,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
artifact_request = requests.find { |req| req.url.match(%r{artifacts/download}) }
- expect(artifact_request.response_headers["Content-Disposition"]).to eq(%Q{attachment; filename*=UTF-8''#{job.artifacts_file.filename}; filename="#{job.artifacts_file.filename}"})
+ expect(artifact_request.response_headers['Content-Disposition']).to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}})
expect(artifact_request.response_headers['Content-Transfer-Encoding']).to eq("binary")
expect(artifact_request.response_headers['Content-Type']).to eq("image/gif")
expect(artifact_request.body).to eq(job.artifacts_file.file.read.b)
diff --git a/spec/frontend/vue_shared/components/changed_file_icon_spec.js b/spec/frontend/vue_shared/components/changed_file_icon_spec.js
index 5d2aec6734f..8258eb8204c 100644
--- a/spec/frontend/vue_shared/components/changed_file_icon_spec.js
+++ b/spec/frontend/vue_shared/components/changed_file_icon_spec.js
@@ -3,8 +3,7 @@ import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
import Icon from '~/vue_shared/components/icon.vue';
const changedFile = () => ({ changed: true });
-const stagedFile = () => ({ changed: false, staged: true });
-const changedAndStagedFile = () => ({ changed: true, staged: true });
+const stagedFile = () => ({ changed: true, staged: true });
const newFile = () => ({ changed: true, tempFile: true });
const unchangedFile = () => ({ changed: false, tempFile: false, staged: false, deleted: false });
@@ -55,11 +54,10 @@ describe('Changed file icon', () => {
});
describe.each`
- file | iconName | tooltipText | desc
- ${changedFile()} | ${'file-modified'} | ${'Unstaged modification'} | ${'with file changed'}
- ${stagedFile()} | ${'file-modified-solid'} | ${'Staged modification'} | ${'with file staged'}
- ${changedAndStagedFile()} | ${'file-modified'} | ${'Unstaged and staged modification'} | ${'with file changed and staged'}
- ${newFile()} | ${'file-addition'} | ${'Unstaged addition'} | ${'with file new'}
+ file | iconName | tooltipText | desc
+ ${changedFile()} | ${'file-modified'} | ${'Unstaged modification'} | ${'with file changed'}
+ ${stagedFile()} | ${'file-modified-solid'} | ${'Staged modification'} | ${'with file staged'}
+ ${newFile()} | ${'file-addition'} | ${'Unstaged addition'} | ${'with file new'}
`('$desc', ({ file, iconName, tooltipText }) => {
beforeEach(() => {
factory({ file });
diff --git a/spec/javascripts/editor/editor_lite_spec.js b/spec/javascripts/editor/editor_lite_spec.js
new file mode 100644
index 00000000000..154daccf82d
--- /dev/null
+++ b/spec/javascripts/editor/editor_lite_spec.js
@@ -0,0 +1,111 @@
+import { editor as monacoEditor, Uri } from 'monaco-editor';
+import Editor from '~/editor/editor_lite';
+
+describe('Base editor', () => {
+ let editorEl;
+ let editor;
+ const blobContent = 'Foo Bar';
+ const blobPath = 'test.md';
+ const uri = new Uri('gitlab', false, blobPath);
+ const fakeModel = { foo: 'bar' };
+
+ beforeEach(() => {
+ setFixtures('<div id="editor" data-editor-loading></div>');
+ editorEl = document.getElementById('editor');
+ editor = new Editor();
+ });
+
+ afterEach(() => {
+ editor.dispose();
+ editorEl.remove();
+ });
+
+ it('initializes Editor with basic properties', () => {
+ expect(editor).toBeDefined();
+ expect(editor.editorEl).toBe(null);
+ expect(editor.blobContent).toEqual('');
+ expect(editor.blobPath).toEqual('');
+ });
+
+ it('removes `editor-loading` data attribute from the target DOM element', () => {
+ editor.createInstance({ el: editorEl });
+
+ expect(editorEl.dataset.editorLoading).toBeUndefined();
+ });
+
+ describe('instance of the Editor', () => {
+ let modelSpy;
+ let instanceSpy;
+ let setModel;
+ let dispose;
+
+ beforeEach(() => {
+ setModel = jasmine.createSpy();
+ dispose = jasmine.createSpy();
+ modelSpy = spyOn(monacoEditor, 'createModel').and.returnValue(fakeModel);
+ instanceSpy = spyOn(monacoEditor, 'create').and.returnValue({
+ setModel,
+ dispose,
+ });
+ });
+
+ it('does nothing if no dom element is supplied', () => {
+ editor.createInstance();
+
+ expect(editor.editorEl).toBe(null);
+ expect(editor.blobContent).toEqual('');
+ expect(editor.blobPath).toEqual('');
+
+ expect(modelSpy).not.toHaveBeenCalled();
+ expect(instanceSpy).not.toHaveBeenCalled();
+ expect(setModel).not.toHaveBeenCalled();
+ });
+
+ it('creates model to be supplied to Monaco editor', () => {
+ editor.createInstance({ el: editorEl, blobPath, blobContent });
+
+ expect(modelSpy).toHaveBeenCalledWith(blobContent, undefined, uri);
+ expect(setModel).toHaveBeenCalledWith(fakeModel);
+ });
+
+ it('initializes the instance on a supplied DOM node', () => {
+ editor.createInstance({ el: editorEl });
+
+ expect(editor.editorEl).not.toBe(null);
+ expect(instanceSpy).toHaveBeenCalledWith(editorEl, jasmine.anything());
+ });
+ });
+
+ describe('implementation', () => {
+ beforeEach(() => {
+ editor.createInstance({ el: editorEl, blobPath, blobContent });
+ });
+
+ afterEach(() => {
+ editor.model.dispose();
+ });
+
+ it('correctly proxies value from the model', () => {
+ expect(editor.getValue()).toEqual(blobContent);
+ });
+
+ it('is capable of changing the language of the model', () => {
+ const blobRenamedPath = 'test.js';
+
+ expect(editor.model.getLanguageIdentifier().language).toEqual('markdown');
+ editor.updateModelLanguage(blobRenamedPath);
+
+ expect(editor.model.getLanguageIdentifier().language).toEqual('javascript');
+ });
+
+ it('falls back to plaintext if there is no language associated with an extension', () => {
+ const blobRenamedPath = 'test.myext';
+ const spy = spyOn(console, 'error');
+
+ editor.updateModelLanguage(blobRenamedPath);
+
+ expect(spy).not.toHaveBeenCalled();
+ expect(editor.model.getLanguageIdentifier().language).toEqual('plaintext');
+ });
+ });
+});
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index 3797e794985..7a8e79fecb1 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -1541,7 +1541,7 @@ describe Gitlab::Database::MigrationHelpers do
self.table_name = 'issues'
self.inheritance_column = :_type_disabled
- belongs_to :project
+ belongs_to :project, class_name: "::Project"
has_internal_id :iid,
scope: :project,
diff --git a/spec/lib/gitlab/query_limiting/middleware_spec.rb b/spec/lib/gitlab/query_limiting/middleware_spec.rb
index f996ea38bb9..f397843df54 100644
--- a/spec/lib/gitlab/query_limiting/middleware_spec.rb
+++ b/spec/lib/gitlab/query_limiting/middleware_spec.rb
@@ -26,7 +26,7 @@ describe Gitlab::QueryLimiting::Middleware do
:controller,
action_name: 'show',
class: double(:class, name: 'UsersController'),
- content_type: 'text/html'
+ media_type: 'text/html'
)
}
@@ -39,7 +39,7 @@ describe Gitlab::QueryLimiting::Middleware do
:controller,
action_name: 'show',
class: double(:class, name: 'UsersController'),
- content_type: 'application/json'
+ media_type: 'application/json'
)
}
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 1e8598a457c..470b67afe07 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -302,7 +302,11 @@ describe MergeRequest do
it 'returns empty requests' do
latest_merge_request_diff = merge_request.merge_request_diffs.create
- latest_merge_request_diff.merge_request_diff_commits.where(sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0').delete_all
+
+ MergeRequestDiffCommit.where(
+ merge_request_diff_id: latest_merge_request_diff,
+ sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0'
+ ).delete_all
expect(by_commit_sha).to be_empty
end
diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb
index 620ef3ff21a..26fa3803651 100644
--- a/spec/presenters/project_presenter_spec.rb
+++ b/spec/presenters/project_presenter_spec.rb
@@ -297,7 +297,7 @@ describe ProjectPresenter do
is_link: false,
label: a_string_including("New file"),
link: presenter.project_new_blob_path(project, 'master'),
- class_modifier: 'success'
+ class_modifier: 'missing'
)
end
diff --git a/spec/requests/api/issues/post_projects_issues_spec.rb b/spec/requests/api/issues/post_projects_issues_spec.rb
index bbe0683c275..6597a3ab3ba 100644
--- a/spec/requests/api/issues/post_projects_issues_spec.rb
+++ b/spec/requests/api/issues/post_projects_issues_spec.rb
@@ -389,7 +389,7 @@ describe API::Issues do
end
before do
- expect_next_instance_of(SpamCheckService) do |spam_service|
+ expect_next_instance_of(Spam::SpamCheckService) do |spam_service|
expect(spam_service).to receive_messages(check_for_spam?: true)
end
expect_next_instance_of(AkismetService) do |akismet_service|
diff --git a/spec/requests/api/issues/put_projects_issues_spec.rb b/spec/requests/api/issues/put_projects_issues_spec.rb
index 39ac53899da..e6fec2fa1fc 100644
--- a/spec/requests/api/issues/put_projects_issues_spec.rb
+++ b/spec/requests/api/issues/put_projects_issues_spec.rb
@@ -194,7 +194,7 @@ describe API::Issues do
end
before do
- expect_next_instance_of(SpamCheckService) do |spam_service|
+ expect_next_instance_of(Spam::SpamCheckService) do |spam_service|
expect(spam_service).to receive_messages(check_for_spam?: true)
end
expect_next_instance_of(AkismetService) do |akismet_service|
diff --git a/spec/rubocop/cop/include_action_view_context_spec.rb b/spec/rubocop/cop/include_action_view_context_spec.rb
deleted file mode 100644
index c888555b54f..00000000000
--- a/spec/rubocop/cop/include_action_view_context_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require 'rubocop'
-require 'rubocop/rspec/support'
-
-require_relative '../../../rubocop/cop/include_action_view_context'
-
-describe RuboCop::Cop::IncludeActionViewContext do
- include CopHelper
-
- subject(:cop) { described_class.new }
-
- context 'when `ActionView::Context` is included' do
- let(:source) { 'include ActionView::Context' }
- let(:correct_source) { 'include ::Gitlab::ActionViewOutput::Context' }
-
- it 'registers an offense' do
- inspect_source(source)
-
- aggregate_failures do
- expect(cop.offenses.size).to eq(1)
- expect(cop.offenses.map(&:line)).to eq([1])
- expect(cop.highlights).to eq(['ActionView::Context'])
- end
- end
-
- it 'autocorrects to the right version' do
- autocorrected = autocorrect_source(source)
-
- expect(autocorrected).to eq(correct_source)
- end
- end
-
- context 'when `ActionView::Context` is not included' do
- it 'registers no offense' do
- inspect_source('include Context')
-
- aggregate_failures do
- expect(cop.offenses.size).to eq(0)
- end
- end
- end
-end
diff --git a/spec/services/akismet_service_spec.rb b/spec/services/akismet_service_spec.rb
index 4f1c23b701b..355ff1611a0 100644
--- a/spec/services/akismet_service_spec.rb
+++ b/spec/services/akismet_service_spec.rb
@@ -19,7 +19,6 @@ describe AkismetService do
end
shared_examples 'no activity if Akismet is not enabled' do |method_call|
- # if the method name is `submit`, it requires an argument, so add it
before do
stub_application_setting(akismet_enabled: false)
end
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index bb68a8dcbbb..3246578c743 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -385,7 +385,7 @@ describe Issues::CreateService do
context 'when recaptcha was not verified' do
before do
- expect_next_instance_of(SpamCheckService) do |spam_service|
+ expect_next_instance_of(Spam::SpamCheckService) do |spam_service|
expect(spam_service).to receive_messages(check_for_spam?: true)
end
end
diff --git a/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb b/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb
index 274d594fd68..20583ff77e9 100644
--- a/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb
+++ b/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb
@@ -5,6 +5,8 @@ require 'spec_helper'
describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memory_store_caching do
include MetricsDashboardHelpers
+ STAGES = ::Gitlab::Metrics::Dashboard::Stages
+
set(:user) { create(:user) }
set(:project) { create(:project, :repository) }
set(:environment) { create(:environment, project: project) }
@@ -16,6 +18,7 @@ describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memory_stor
let(:branch) { "dashboard_new_branch" }
let(:dashboard) { 'config/prometheus/common_metrics.yml' }
let(:file_name) { 'custom_dashboard.yml' }
+ let(:file_content_hash) { YAML.safe_load(File.read(dashboard)) }
let(:params) do
{
dashboard: dashboard,
@@ -25,17 +28,6 @@ describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memory_stor
}
end
- let(:dashboard_attrs) do
- {
- commit_message: commit_message,
- branch_name: branch,
- start_branch: project.default_branch,
- encoding: 'text',
- file_path: ".gitlab/dashboards/#{file_name}",
- file_content: File.read(dashboard)
- }
- end
-
context 'user does not have push right to repository' do
it_behaves_like 'misconfigured dashboard service response', :forbidden, %q(You can't commit to this project)
end
@@ -72,11 +64,12 @@ describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memory_stor
start_branch: project.default_branch,
encoding: 'text',
file_path: ".gitlab/dashboards/custom_dashboard.yml",
- file_content: File.read(dashboard)
+ file_content: file_content_hash.to_yaml
}
end
it 'strips target file name to safe value', :aggregate_failures do
+ allow(::Gitlab::Metrics::Dashboard::Processor).to receive(:new).and_return(double(process: file_content_hash))
service_instance = instance_double(::Files::CreateService)
expect(::Files::CreateService).to receive(:new).with(project, user, dashboard_attrs).and_return(service_instance)
expect(service_instance).to receive(:execute).and_return(status: :success)
@@ -86,14 +79,12 @@ describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memory_stor
end
context 'valid parameters' do
- it 'delegates commit creation to Files::CreateService', :aggregate_failures do
- service_instance = instance_double(::Files::CreateService)
- expect(::Files::CreateService).to receive(:new).with(project, user, dashboard_attrs).and_return(service_instance)
- expect(service_instance).to receive(:execute).and_return(status: :success)
-
- service_call
+ before do
+ allow(::Gitlab::Metrics::Dashboard::Processor).to receive(:new).and_return(double(process: file_content_hash))
end
+ it_behaves_like 'valid dashboard cloning process', ::Metrics::Dashboard::SystemDashboardService::DASHBOARD_PATH, [STAGES::CommonMetricsInserter, STAGES::ProjectMetricsInserter, STAGES::Sorter]
+
context 'selected branch already exists' do
let(:branch) { 'existing_branch' }
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index 298867f483b..fe31dafdd03 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -47,11 +47,12 @@ describe Projects::TransferService do
end
end
- it 'disk path has moved' do
+ it 'moves the disk path', :aggregate_failures do
old_path = project.repository.disk_path
old_full_path = project.repository.full_path
transfer_project(project, user, group)
+ project.reload_repository!
expect(project.repository.disk_path).not_to eq(old_path)
expect(project.repository.full_path).not_to eq(old_full_path)
@@ -298,22 +299,41 @@ describe Projects::TransferService do
end
context 'when hashed storage in use' do
- let(:hashed_project) { create(:project, :repository, namespace: user.namespace) }
+ let!(:hashed_project) { create(:project, :repository, namespace: user.namespace) }
+ let!(:old_disk_path) { hashed_project.repository.disk_path }
before do
group.add_owner(user)
end
- it 'does not move the directory' do
- old_path = hashed_project.repository.disk_path
- old_full_path = hashed_project.repository.full_path
+ it 'does not move the disk path', :aggregate_failures do
+ new_full_path = "#{group.full_path}/#{hashed_project.path}"
transfer_project(hashed_project, user, group)
- project.reload
+ hashed_project.reload_repository!
- expect(hashed_project.repository.disk_path).to eq(old_path)
- expect(hashed_project.repository.full_path).to eq(old_full_path)
- expect(hashed_project.disk_path).to eq(old_path)
+ expect(hashed_project.repository).to have_attributes(
+ disk_path: old_disk_path,
+ full_path: new_full_path
+ )
+ expect(hashed_project.disk_path).to eq(old_disk_path)
+ end
+
+ it 'does not move the disk path when the transfer fails', :aggregate_failures do
+ old_full_path = hashed_project.full_path
+
+ expect_next_instance_of(described_class) do |service|
+ allow(service).to receive(:execute_system_hooks).and_raise('foo')
+ end
+ expect { transfer_project(hashed_project, user, group) }.to raise_error('foo')
+
+ hashed_project.reload_repository!
+
+ expect(hashed_project.repository).to have_attributes(
+ disk_path: old_disk_path,
+ full_path: old_full_path
+ )
+ expect(hashed_project.disk_path).to eq(old_disk_path)
end
end
diff --git a/spec/services/spam_check_service_spec.rb b/spec/services/spam/spam_check_service_spec.rb
index a58c8d9cfd8..5e06d14b8bc 100644
--- a/spec/services/spam_check_service_spec.rb
+++ b/spec/services/spam/spam_check_service_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-describe SpamCheckService do
+describe Spam::SpamCheckService do
let(:fake_ip) { '1.2.3.4' }
let(:fake_user_agent) { 'fake-user-agent' }
let(:fake_referrer) { 'fake-http-referrer' }
diff --git a/spec/support/helpers/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb
index fd5ad9451f7..4f11f8c6b24 100644
--- a/spec/support/helpers/javascript_fixtures_helpers.rb
+++ b/spec/support/helpers/javascript_fixtures_helpers.rb
@@ -62,7 +62,7 @@ module JavaScriptFixturesHelpers
fixture = response.body
fixture.force_encoding("utf-8")
- response_mime_type = Mime::Type.lookup(response.content_type)
+ response_mime_type = Mime::Type.lookup(response.media_type)
if response_mime_type.html?
doc = Nokogiri::HTML::DocumentFragment.parse(fixture)
diff --git a/spec/support/helpers/migrations_helpers.rb b/spec/support/helpers/migrations_helpers.rb
index 68f71494771..5eb70f534d8 100644
--- a/spec/support/helpers/migrations_helpers.rb
+++ b/spec/support/helpers/migrations_helpers.rb
@@ -21,7 +21,7 @@ module MigrationsHelpers
end
def migration_context
- ActiveRecord::MigrationContext.new(migrations_paths)
+ ActiveRecord::MigrationContext.new(migrations_paths, ActiveRecord::SchemaMigration)
end
def migrations
diff --git a/spec/support/helpers/stub_configuration.rb b/spec/support/helpers/stub_configuration.rb
index 0dc6e851190..6a832ca97d1 100644
--- a/spec/support/helpers/stub_configuration.rb
+++ b/spec/support/helpers/stub_configuration.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require 'active_support/core_ext/hash/transform_values'
require 'active_support/hash_with_indifferent_access'
require 'active_support/dependencies'
diff --git a/spec/support/shared_examples/controllers/repository_lfs_file_load_shared_examples.rb b/spec/support/shared_examples/controllers/repository_lfs_file_load_shared_examples.rb
index b8967bc8df3..fadf428125a 100644
--- a/spec/support/shared_examples/controllers/repository_lfs_file_load_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/repository_lfs_file_load_shared_examples.rb
@@ -41,13 +41,11 @@ RSpec.shared_examples 'a controller that can serve LFS files' do |options = {}|
it 'serves the file' do
lfs_uploader = LfsObjectUploader.new(lfs_object)
- # Notice the filename= is omitted from the disposition; this is because
- # Rails 5 will append this header in send_file
expect(controller).to receive(:send_file)
.with(
File.join(lfs_uploader.root, lfs_uploader.store_dir, lfs_uploader.filename),
filename: filename,
- disposition: %Q(attachment; filename*=UTF-8''#{filename}))
+ disposition: 'attachment')
subject
diff --git a/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb b/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb
index 66a6c073445..1f229d6b783 100644
--- a/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb
+++ b/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb
@@ -50,3 +50,38 @@ RSpec.shared_examples 'raises error for users with insufficient permissions' do
it_behaves_like 'misconfigured dashboard service response', :unauthorized
end
end
+
+RSpec.shared_examples 'valid dashboard cloning process' do |dashboard_template, sequence|
+ context "dashboard template: #{dashboard_template}" do
+ let(:dashboard) { dashboard_template }
+ let(:dashboard_attrs) do
+ {
+ commit_message: commit_message,
+ branch_name: branch,
+ start_branch: project.default_branch,
+ encoding: 'text',
+ file_path: ".gitlab/dashboards/#{file_name}",
+ file_content: file_content_hash.to_yaml
+ }
+ end
+
+ it 'delegates commit creation to Files::CreateService', :aggregate_failures do
+ service_instance = instance_double(::Files::CreateService)
+ expect(::Files::CreateService).to receive(:new).with(project, user, dashboard_attrs).and_return(service_instance)
+ expect(service_instance).to receive(:execute).and_return(status: :success)
+
+ service_call
+ end
+
+ context 'user has defined custom metrics' do
+ it 'uses external service to includes them into new file content', :aggregate_failures do
+ service_instance = double(::Gitlab::Metrics::Dashboard::Processor)
+ expect(::Gitlab::Metrics::Dashboard::Processor).to receive(:new).with(project, file_content_hash, sequence, {}).and_return(service_instance)
+ expect(service_instance).to receive(:process).and_return(file_content_hash)
+ expect(::Files::CreateService).to receive(:new).with(project, user, dashboard_attrs).and_return(double(execute: { status: :success }))
+
+ service_call
+ end
+ end
+ end
+end