summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-10 18:08:17 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-10 18:08:17 +0000
commit219eead23f9feb5da9ec378c451d773aea2dfe61 (patch)
treeeec14421a05ca8eb79f3cc782abe99532bb6070c
parent7c38405be9e79099f399aa429503ea7b463bbf5a (diff)
downloadgitlab-ce-219eead23f9feb5da9ec378c451d773aea2dfe61.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.haml-lint_todo.yml1
-rw-r--r--app/assets/javascripts/error_tracking/components/error_details.vue26
-rw-r--r--app/controllers/import/gitlab_projects_controller.rb30
-rw-r--r--app/helpers/application_helper.rb2
-rw-r--r--app/models/concerns/bulk_insert_safe.rb4
-rw-r--r--app/models/concerns/bulk_insertable_associations.rb9
-rw-r--r--app/services/notification_recipients/build_service.rb10
-rw-r--r--app/views/layouts/_page.html.haml2
-rw-r--r--app/views/layouts/fullscreen.html.haml2
-rw-r--r--app/views/shared/_outdated_browser.html.haml19
-rw-r--r--changelogs/unreleased/118503.yml5
-rw-r--r--changelogs/unreleased/197480-remove-package-file_type.yml5
-rw-r--r--changelogs/unreleased/208674-use-wh-acceleration-for-ui-project-import.yml5
-rw-r--r--changelogs/unreleased/208830-conan-package-reference-fix.yml5
-rw-r--r--changelogs/unreleased/25995-default-relative-links-to-blobs.yml5
-rw-r--r--config/gitlab.yml.example2
-rw-r--r--config/routes/import.rb1
-rw-r--r--db/post_migrate/20200304211738_remove_file_type_from_packages_package_files.rb9
-rw-r--r--db/schema.rb1
-rw-r--r--doc/install/requirements.md7
-rw-r--r--doc/user/admin_area/settings/usage_statistics.md2
-rw-r--r--lib/banzai/filter/repository_link_filter.rb8
-rw-r--r--locale/gitlab.pot15
-rw-r--r--spec/controllers/import/gitlab_projects_controller_spec.rb58
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb2
-rw-r--r--spec/features/projects/tags/user_edits_tags_spec.rb2
-rw-r--r--spec/features/uploads/user_uploads_file_to_note_spec.rb2
-rw-r--r--spec/frontend/diffs/components/commit_item_spec.js4
-rw-r--r--spec/frontend/error_tracking/components/error_details_spec.js81
-rw-r--r--spec/helpers/markup_helper_spec.rb2
-rw-r--r--spec/lib/banzai/filter/repository_link_filter_spec.rb8
-rw-r--r--spec/models/concerns/bulk_insertable_associations_spec.rb8
-rw-r--r--spec/support/capybara.rb26
-rw-r--r--spec/support/helpers/test_env.rb51
-rw-r--r--spec/support/shared_examples/features/wiki_file_attachments_shared_examples.rb2
35 files changed, 359 insertions, 62 deletions
diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml
index 7ee4f639633..dd94d0b494d 100644
--- a/.haml-lint_todo.yml
+++ b/.haml-lint_todo.yml
@@ -305,7 +305,6 @@ linters:
- 'app/views/shared/_milestone_expired.html.haml'
- 'app/views/shared/_no_password.html.haml'
- 'app/views/shared/_no_ssh.html.haml'
- - 'app/views/shared/_outdated_browser.html.haml'
- 'app/views/shared/_ping_consent.html.haml'
- 'app/views/shared/_project_limit.html.haml'
- 'app/views/shared/boards/components/_board.html.haml'
diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue
index 43fa97e4095..6c4f59eb49f 100644
--- a/app/assets/javascripts/error_tracking/components/error_details.vue
+++ b/app/assets/javascripts/error_tracking/components/error_details.vue
@@ -25,6 +25,8 @@ import { severityLevel, severityLevelVariant, errorStatus } from './constants';
import query from '../queries/details.query.graphql';
+const SENTRY_TIMEOUT = 10000;
+
export default {
components: {
GlButton,
@@ -87,6 +89,8 @@ export default {
if (res.data.project?.sentryErrors?.detailedError) {
this.$apollo.queries.error.stopPolling();
this.setStatus(this.error.status);
+ } else {
+ this.onNoApolloResult();
}
},
},
@@ -94,6 +98,8 @@ export default {
data() {
return {
error: null,
+ errorLoading: true,
+ errorPollTimeout: 0,
issueCreationInProgress: false,
isAlertVisible: false,
closedIssueId: null,
@@ -158,8 +164,19 @@ export default {
return this.errorStatus !== errorStatus.RESOLVED ? __('Resolve') : __('Unresolve');
},
},
+ watch: {
+ error(val) {
+ if (val) {
+ this.errorLoading = false;
+ }
+ },
+ },
mounted() {
this.startPollingStacktrace(this.issueStackTracePath);
+ this.errorPollTimeout = Date.now() + SENTRY_TIMEOUT;
+ this.$apollo.queries.error.setOptions({
+ fetchPolicy: 'cache-and-network',
+ });
},
methods: {
...mapActions('details', [
@@ -191,6 +208,13 @@ export default {
}
});
},
+ onNoApolloResult() {
+ if (Date.now() > this.errorPollTimeout) {
+ this.$apollo.queries.error.stopPolling();
+ this.errorLoading = false;
+ createFlash(__('Could not connect to Sentry. Refresh the page to try again.'), 'warning');
+ }
+ },
formatDate(date) {
return `${this.timeFormatted(date)} (${dateFormat(date, 'UTC:yyyy-mm-dd h:MM:ssTT Z')})`;
},
@@ -200,7 +224,7 @@ export default {
<template>
<div>
- <div v-if="$apollo.queries.error.loading" class="py-3">
+ <div v-if="errorLoading" class="py-3">
<gl-loading-icon :size="3" />
</div>
<div v-else-if="error" class="error-details">
diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb
index c9c487cec26..6b8436d766c 100644
--- a/app/controllers/import/gitlab_projects_controller.rb
+++ b/app/controllers/import/gitlab_projects_controller.rb
@@ -1,9 +1,14 @@
# frozen_string_literal: true
class Import::GitlabProjectsController < Import::BaseController
+ include WorkhorseRequest
+
before_action :whitelist_query_limiting, only: [:create]
before_action :verify_gitlab_project_import_enabled
+ skip_before_action :verify_authenticity_token, only: [:authorize]
+ before_action :verify_workhorse_api!, only: [:authorize]
+
def new
@namespace = Namespace.find(project_params[:namespace_id])
return render_404 unless current_user.can?(:create_projects, @namespace)
@@ -28,10 +33,29 @@ class Import::GitlabProjectsController < Import::BaseController
end
end
+ def authorize
+ set_workhorse_internal_api_content_type
+
+ authorized = ImportExportUploader.workhorse_authorize(
+ has_length: false,
+ maximum_size: Gitlab::CurrentSettings.max_attachment_size.megabytes.to_i)
+
+ render json: authorized
+ rescue SocketError
+ render json: _("Error uploading file"), status: :internal_server_error
+ end
+
private
def file_is_valid?
- return false unless project_params[:file] && project_params[:file].respond_to?(:read)
+ # TODO: remove the condition and the private method after the WH version including
+ # https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/470
+ # is released and GITLAB_WORKHORSE_VERSION is updated accordingly.
+ if with_workhorse_upload_acceleration?
+ return false unless project_params[:file].is_a?(::UploadedFile)
+ else
+ return false unless project_params[:file] && project_params[:file].respond_to?(:read)
+ end
filename = project_params[:file].original_filename
@@ -51,4 +75,8 @@ class Import::GitlabProjectsController < Import::BaseController
def whitelist_query_limiting
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42437')
end
+
+ def with_workhorse_upload_acceleration?
+ request.headers[Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER].present?
+ end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 8833b36c42d..83ecc7753b6 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -227,7 +227,7 @@ module ApplicationHelper
end
def outdated_browser?
- browser.ie? && browser.version.to_i < 10
+ browser.ie?
end
def path_to_key(key, admin = false)
diff --git a/app/models/concerns/bulk_insert_safe.rb b/app/models/concerns/bulk_insert_safe.rb
index 0d022418b1a..d8587ea78ec 100644
--- a/app/models/concerns/bulk_insert_safe.rb
+++ b/app/models/concerns/bulk_insert_safe.rb
@@ -111,8 +111,8 @@ module BulkInsertSafe
end
def _bulk_insert_reject_primary_key!(attributes, primary_key)
- if attributes.delete(primary_key)
- raise PrimaryKeySetError, "Primary key set: #{primary_key}:#{attributes[primary_key]}\n" \
+ if existing_pk = attributes.delete(primary_key)
+ raise PrimaryKeySetError, "Primary key set: #{primary_key}:#{existing_pk}\n" \
"Bulk-inserts are only supported for rows that don't already have PK set"
end
end
diff --git a/app/models/concerns/bulk_insertable_associations.rb b/app/models/concerns/bulk_insertable_associations.rb
index 35bdabbcefd..5ee2e8356bd 100644
--- a/app/models/concerns/bulk_insertable_associations.rb
+++ b/app/models/concerns/bulk_insertable_associations.rb
@@ -93,11 +93,14 @@ module BulkInsertableAssociations
end
def _bulk_insert_configure_foreign_key(reflection, items)
- primary_key = self[reflection.active_record_primary_key]
- raise "Classes including `BulkInsertableAssociations` must define a `primary_key`" unless primary_key
+ primary_key_column = reflection.active_record_primary_key
+ raise "Classes including `BulkInsertableAssociations` must define a `primary_key`" unless primary_key_column
+
+ primary_key_value = self[primary_key_column]
+ raise "No value found for primary key `#{primary_key_column}`" unless primary_key_value
items.each do |item|
- item[reflection.foreign_key] = primary_key
+ item[reflection.foreign_key] = primary_key_value
if reflection.type
item[reflection.type] = self.class.polymorphic_name
diff --git a/app/services/notification_recipients/build_service.rb b/app/services/notification_recipients/build_service.rb
index 67f9849aece..df807f11e1b 100644
--- a/app/services/notification_recipients/build_service.rb
+++ b/app/services/notification_recipients/build_service.rb
@@ -14,23 +14,23 @@ module NotificationRecipients
end
def self.build_recipients(*args)
- Builder::Default.new(*args).notification_recipients
+ ::NotificationRecipients::Builder::Default.new(*args).notification_recipients
end
def self.build_new_note_recipients(*args)
- Builder::NewNote.new(*args).notification_recipients
+ ::NotificationRecipients::Builder::NewNote.new(*args).notification_recipients
end
def self.build_merge_request_unmergeable_recipients(*args)
- Builder::MergeRequestUnmergeable.new(*args).notification_recipients
+ ::NotificationRecipients::Builder::MergeRequestUnmergeable.new(*args).notification_recipients
end
def self.build_project_maintainers_recipients(*args)
- Builder::ProjectMaintainers.new(*args).notification_recipients
+ ::NotificationRecipients::Builder::ProjectMaintainers.new(*args).notification_recipients
end
def self.build_new_release_recipients(*args)
- Builder::NewRelease.new(*args).notification_recipients
+ ::NotificationRecipients::Builder::NewRelease.new(*args).notification_recipients
end
end
end
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 2b2ffd6abeb..06e3bca99a1 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -2,9 +2,9 @@
- if defined?(nav) && nav
= render "layouts/nav/sidebar/#{nav}"
.content-wrapper{ class: "#{@content_wrapper_class}" }
- = render 'shared/outdated_browser'
.mobile-overlay
.alert-wrapper
+ = render 'shared/outdated_browser'
= render_if_exists "layouts/header/ee_license_banner"
= render "layouts/broadcast"
= render "layouts/header/read_only_banner"
diff --git a/app/views/layouts/fullscreen.html.haml b/app/views/layouts/fullscreen.html.haml
index 8d0775f6f27..63bb9f8fff5 100644
--- a/app/views/layouts/fullscreen.html.haml
+++ b/app/views/layouts/fullscreen.html.haml
@@ -5,9 +5,9 @@
= render 'peek/bar'
= header_message
= render partial: "layouts/header/default", locals: { project: @project, group: @group }
- = render 'shared/outdated_browser'
.mobile-overlay
.alert-wrapper
+ = render 'shared/outdated_browser'
= render "layouts/broadcast"
= yield :flash_message
= render "layouts/flash"
diff --git a/app/views/shared/_outdated_browser.html.haml b/app/views/shared/_outdated_browser.html.haml
index 8ddb1b2bc99..30255e18f04 100644
--- a/app/views/shared/_outdated_browser.html.haml
+++ b/app/views/shared/_outdated_browser.html.haml
@@ -1,8 +1,15 @@
- if outdated_browser?
- .flash-container
- .flash-alert.text-center
- GitLab may not work properly because you are using an outdated web browser.
+ .gl-alert.gl-alert-danger.outdated-browser{ :role => "alert" }
+ = sprite_icon('error', size: 16, css_class: "gl-alert-icon gl-alert-icon-no-title gl-icon")
+ .gl-alert-body
+ - if browser.ie? && browser.version.to_i == 11
+ - feedback_link_url = 'https://gitlab.com/gitlab-org/gitlab/issues/197987'
+ - feedback_link_start = '<a href="%{url}" class="gl-link" target="_blank" rel="noopener noreferrer">'.html_safe % { url: feedback_link_url }
+ = s_('OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11.')
+ %br
+ = s_('OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels.').html_safe % { feedback_link_start: feedback_link_start, feedback_link_end: '</a>'.html_safe }
+ - else
+ = s_('OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser.')
%br
- Please install a
- = link_to 'supported web browser', help_page_path('install/requirements', anchor: 'supported-web-browsers')
- for a better experience.
+ - browser_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('install/requirements', anchor: 'supported-web-browsers') }
+ = s_('OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience.').html_safe % { browser_link_start: browser_link_start, browser_link_end: '</a>'.html_safe }
diff --git a/changelogs/unreleased/118503.yml b/changelogs/unreleased/118503.yml
new file mode 100644
index 00000000000..3aa2e0399a8
--- /dev/null
+++ b/changelogs/unreleased/118503.yml
@@ -0,0 +1,5 @@
+---
+title: Fix infinite spinner on error detail page
+merge_request: 26188
+author:
+type: fixed
diff --git a/changelogs/unreleased/197480-remove-package-file_type.yml b/changelogs/unreleased/197480-remove-package-file_type.yml
new file mode 100644
index 00000000000..c315a0289f5
--- /dev/null
+++ b/changelogs/unreleased/197480-remove-package-file_type.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unused file_type column from packages_package_files
+merge_request: 26527
+author:
+type: changed
diff --git a/changelogs/unreleased/208674-use-wh-acceleration-for-ui-project-import.yml b/changelogs/unreleased/208674-use-wh-acceleration-for-ui-project-import.yml
new file mode 100644
index 00000000000..118e7efa2fb
--- /dev/null
+++ b/changelogs/unreleased/208674-use-wh-acceleration-for-ui-project-import.yml
@@ -0,0 +1,5 @@
+---
+title: Use Workhorse acceleration for Project Import file upload via UI
+merge_request: 26278
+author:
+type: performance
diff --git a/changelogs/unreleased/208830-conan-package-reference-fix.yml b/changelogs/unreleased/208830-conan-package-reference-fix.yml
new file mode 100644
index 00000000000..9318b5d71f1
--- /dev/null
+++ b/changelogs/unreleased/208830-conan-package-reference-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Fix package file finder for conan packages with a conan_package_reference filter
+merge_request: 26240
+author:
+type: fixed
diff --git a/changelogs/unreleased/25995-default-relative-links-to-blobs.yml b/changelogs/unreleased/25995-default-relative-links-to-blobs.yml
new file mode 100644
index 00000000000..dea0ac22ee3
--- /dev/null
+++ b/changelogs/unreleased/25995-default-relative-links-to-blobs.yml
@@ -0,0 +1,5 @@
+---
+title: Default to generating blob links for missing paths
+merge_request: 26817
+author:
+type: fixed
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 330e5109ed4..ce9df6b6024 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -1226,6 +1226,8 @@ test:
gitaly:
client_path: tmp/tests/gitaly
token: secret
+ workhorse:
+ secret_file: tmp/tests/gitlab_workhorse_secret
backup:
path: tmp/tests/backups
pseudonymizer:
diff --git a/config/routes/import.rb b/config/routes/import.rb
index 9fe2688de1e..57a1fab48e9 100644
--- a/config/routes/import.rb
+++ b/config/routes/import.rb
@@ -60,6 +60,7 @@ namespace :import do
resource :gitlab_project, only: [:create, :new] do
post :create
+ post :authorize
end
resource :manifest, only: [:create, :new], controller: :manifest do
diff --git a/db/post_migrate/20200304211738_remove_file_type_from_packages_package_files.rb b/db/post_migrate/20200304211738_remove_file_type_from_packages_package_files.rb
new file mode 100644
index 00000000000..98bce8845ab
--- /dev/null
+++ b/db/post_migrate/20200304211738_remove_file_type_from_packages_package_files.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class RemoveFileTypeFromPackagesPackageFiles < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ remove_column :packages_package_files, :file_type, :integer
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 40cf50354db..2f1bcddb38f 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -3029,7 +3029,6 @@ ActiveRecord::Schema.define(version: 2020_03_06_170531) do
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.bigint "size"
- t.integer "file_type"
t.integer "file_store"
t.binary "file_md5"
t.binary "file_sha1"
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 052a5d2782a..cfab6352e46 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -236,18 +236,21 @@ For reference, GitLab.com's [auto-scaling shared runner](../user/gitlab_com/inde
## Supported web browsers
+CAUTION: **Caution:** With GitLab 13.0 (May 2020) we are removing official support for Internet Explorer 11.
+With the release of GitLab 13.4 (September 2020) we will remove all code that supports Internet Explorer 11.
+You can provide feedback [on this issue](https://gitlab.com/gitlab-org/gitlab/issues/197987) or via your usual support channels.
+
GitLab supports the following web browsers:
- Firefox
- Chrome/Chromium
- Safari
- Microsoft Edge
-- Internet Explorer 11
+- Internet Explorer 11 (until May 2020)
For the listed web browsers, GitLab supports:
- The current and previous major versions of browsers except Internet Explorer.
-- Only version 11 of Internet Explorer.
- The current minor version of a supported major version.
NOTE: **Note:** We do not support running GitLab with JavaScript disabled in the browser and have no plans of supporting that
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
index 8998a2430f3..f087280f693 100644
--- a/doc/user/admin_area/settings/usage_statistics.md
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -74,6 +74,8 @@ You can view the exact JSON payload in the administration panel. To view the pay
You can see how [the usage ping data maps to different stages of the product](https://gitlab.com/gitlab-data/analytics/blob/master/transform/snowflake-dbt/data/version_usage_stats_to_stage_mappings.csv).
+Usage ping is important to GitLab as we use it to calculate our [Action Monthly Active Users (AMAU)](https://about.gitlab.com/handbook/product/metrics/#action-monthly-active-users-amau) which helps us measure the success of our features.
+
### Request flow example
The following example shows a basic request/response flow between the self-managed GitLab instance, GitLab Version Application,
diff --git a/lib/banzai/filter/repository_link_filter.rb b/lib/banzai/filter/repository_link_filter.rb
index e15201b05cb..24900217560 100644
--- a/lib/banzai/filter/repository_link_filter.rb
+++ b/lib/banzai/filter/repository_link_filter.rb
@@ -131,7 +131,7 @@ module Banzai
path = cleaned_file_path(uri)
nested_path = relative_file_path(uri)
- file_exists?(nested_path) ? nested_path : path
+ path_exists?(nested_path) ? nested_path : path
end
def cleaned_file_path(uri)
@@ -190,12 +190,12 @@ module Banzai
parts.push(path).join('/')
end
- def file_exists?(path)
- path.present? && uri_type(path).present?
+ def path_exists?(path)
+ path.present? && @uri_types[path] != :unknown
end
def uri_type(path)
- @uri_types[path] == :unknown ? "" : @uri_types[path]
+ @uri_types[path] == :unknown ? :blob : @uri_types[path]
end
def current_commit
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index b0960e66ea7..2eaf892d8c1 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -5609,6 +5609,9 @@ msgstr ""
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
+msgid "Could not connect to Sentry. Refresh the page to try again."
+msgstr ""
+
msgid "Could not connect to Web IDE file mirror service."
msgstr ""
@@ -13697,6 +13700,18 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
+msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
+msgstr ""
+
+msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
+msgstr ""
+
+msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
+msgstr ""
+
+msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
+msgstr ""
+
msgid "Overview"
msgstr ""
diff --git a/spec/controllers/import/gitlab_projects_controller_spec.rb b/spec/controllers/import/gitlab_projects_controller_spec.rb
index a9aaefda0f6..0b74e2bbcbf 100644
--- a/spec/controllers/import/gitlab_projects_controller_spec.rb
+++ b/spec/controllers/import/gitlab_projects_controller_spec.rb
@@ -39,4 +39,62 @@ describe Import::GitlabProjectsController do
it_behaves_like 'project import rate limiter'
end
+
+ describe 'POST authorize' do
+ let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
+
+ before do
+ request.headers['GitLab-Workhorse'] = '1.0'
+ request.headers[Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER] = workhorse_token
+ end
+
+ it 'authorizes importing project with workhorse header' do
+ post :authorize, format: :json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
+ end
+
+ it 'rejects requests that bypassed gitlab-workhorse or have invalid header' do
+ request.headers[Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER] = 'INVALID_HEADER'
+
+ expect { post :authorize, format: :json }.to raise_error(JWT::DecodeError)
+ end
+
+ context 'when using remote storage' do
+ context 'when direct upload is enabled' do
+ before do
+ stub_uploads_object_storage(ImportExportUploader, enabled: true, direct_upload: true)
+ end
+
+ it 'responds with status 200, location of file remote store and object details' do
+ post :authorize, format: :json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
+ expect(json_response).not_to have_key('TempPath')
+ expect(json_response['RemoteObject']).to have_key('ID')
+ expect(json_response['RemoteObject']).to have_key('GetURL')
+ expect(json_response['RemoteObject']).to have_key('StoreURL')
+ expect(json_response['RemoteObject']).to have_key('DeleteURL')
+ expect(json_response['RemoteObject']).to have_key('MultipartUpload')
+ end
+ end
+
+ context 'when direct upload is disabled' do
+ before do
+ stub_uploads_object_storage(ImportExportUploader, enabled: true, direct_upload: false)
+ end
+
+ it 'handles as a local file' do
+ post :authorize, format: :json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
+ expect(json_response['TempPath']).to eq(ImportExportUploader.workhorse_local_upload_path)
+ expect(json_response['RemoteObject']).to be_nil
+ end
+ end
+ end
+ end
end
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index b0a2a734877..efcaa8247df 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -156,7 +156,7 @@ describe "User creates issue" do
expect(page.find_field("issue_description").value).not_to match /\n\n$/
end
- it "cancels a file upload correctly" do
+ it "cancels a file upload correctly", :capybara_ignore_server_errors do
slow_requests do
dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
diff --git a/spec/features/projects/tags/user_edits_tags_spec.rb b/spec/features/projects/tags/user_edits_tags_spec.rb
index b1cb7685f63..6388875a619 100644
--- a/spec/features/projects/tags/user_edits_tags_spec.rb
+++ b/spec/features/projects/tags/user_edits_tags_spec.rb
@@ -68,7 +68,7 @@ describe 'Project > Tags', :js do
end
end
- it 'shows "Attaching a file" message on uploading 1 file', :js do
+ it 'shows "Attaching a file" message on uploading 1 file', :js, :capybara_ignore_server_errors do
slow_requests do
dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
diff --git a/spec/features/uploads/user_uploads_file_to_note_spec.rb b/spec/features/uploads/user_uploads_file_to_note_spec.rb
index 30b5cf267ae..570ecad41fa 100644
--- a/spec/features/uploads/user_uploads_file_to_note_spec.rb
+++ b/spec/features/uploads/user_uploads_file_to_note_spec.rb
@@ -22,7 +22,7 @@ describe 'User uploads file to note' do
end
end
- context 'uploading is in progress' do
+ context 'uploading is in progress', :capybara_ignore_server_errors do
it 'cancels uploading on clicking to "Cancel" button', :js do
slow_requests do
dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
diff --git a/spec/frontend/diffs/components/commit_item_spec.js b/spec/frontend/diffs/components/commit_item_spec.js
index ecc28c78fb7..61bab77964e 100644
--- a/spec/frontend/diffs/components/commit_item_spec.js
+++ b/spec/frontend/diffs/components/commit_item_spec.js
@@ -59,7 +59,9 @@ describe('diffs/components/commit_item', () => {
expect(titleElement.text()).toBe(commit.title_html);
});
- it('renders commit description', () => {
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/209776
+ // eslint-disable-next-line jest/no-disabled-tests
+ it.skip('renders commit description', () => {
const descElement = getDescElement();
const descExpandElement = getDescExpandElement();
diff --git a/spec/frontend/error_tracking/components/error_details_spec.js b/spec/frontend/error_tracking/components/error_details_spec.js
index 2baec5f37fb..72b0466a1f0 100644
--- a/spec/frontend/error_tracking/components/error_details_spec.js
+++ b/spec/frontend/error_tracking/components/error_details_spec.js
@@ -1,6 +1,7 @@
import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import { __ } from '~/locale';
+import createFlash from '~/flash';
import {
GlButton,
GlLoadingIcon,
@@ -18,6 +19,8 @@ import {
errorStatus,
} from '~/error_tracking/components/constants';
+jest.mock('~/flash');
+
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -49,18 +52,6 @@ describe('ErrorDetails', () => {
csrfToken: 'fakeToken',
},
});
- wrapper.setData({
- error: {
- id: 'gid://gitlab/Gitlab::ErrorTracking::DetailedError/129381',
- sentryId: 129381,
- title: 'Issue title',
- externalUrl: 'http://sentry.gitlab.net/gitlab',
- firstSeen: '2017-05-26T13:32:48Z',
- lastSeen: '2018-05-26T13:32:48Z',
- count: 12,
- userCount: 2,
- },
- });
}
beforeEach(() => {
@@ -78,6 +69,7 @@ describe('ErrorDetails', () => {
const state = {
stacktraceData: {},
loadingStacktrace: true,
+ errorStatus: '',
};
store = new Vuex.Store({
@@ -99,6 +91,7 @@ describe('ErrorDetails', () => {
error: {
loading: true,
stopPolling: jest.fn(),
+ setOptions: jest.fn(),
},
},
},
@@ -123,10 +116,61 @@ describe('ErrorDetails', () => {
});
});
+ describe('sentry response timeout', () => {
+ const initTime = 300000;
+ const endTime = initTime + 10000;
+
+ beforeEach(() => {
+ mocks.$apollo.queries.error.loading = false;
+ jest.spyOn(Date, 'now').mockReturnValue(initTime);
+ mountComponent();
+ });
+
+ it('when before timeout, still shows loading', () => {
+ Date.now.mockReturnValue(endTime - 1);
+
+ wrapper.vm.onNoApolloResult();
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(createFlash).not.toHaveBeenCalled();
+ expect(mocks.$apollo.queries.error.stopPolling).not.toHaveBeenCalled();
+ });
+ });
+
+ it('when timeout is hit and no apollo result, stops loading and shows flash', () => {
+ Date.now.mockReturnValue(endTime + 1);
+
+ wrapper.vm.onNoApolloResult();
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.find(GlLink).exists()).toBe(false);
+ expect(createFlash).toHaveBeenCalledWith(
+ 'Could not connect to Sentry. Refresh the page to try again.',
+ 'warning',
+ );
+ expect(mocks.$apollo.queries.error.stopPolling).toHaveBeenCalled();
+ });
+ });
+ });
+
describe('Error details', () => {
beforeEach(() => {
mocks.$apollo.queries.error.loading = false;
mountComponent();
+ wrapper.setData({
+ error: {
+ id: 'gid://gitlab/Gitlab::ErrorTracking::DetailedError/129381',
+ sentryId: 129381,
+ title: 'Issue title',
+ externalUrl: 'http://sentry.gitlab.net/gitlab',
+ firstSeen: '2017-05-26T13:32:48Z',
+ lastSeen: '2018-05-26T13:32:48Z',
+ count: 12,
+ userCount: 2,
+ },
+ });
});
it('should show Sentry error details without stacktrace', () => {
@@ -232,10 +276,6 @@ describe('ErrorDetails', () => {
});
describe('When a user clicks the create issue button', () => {
- beforeEach(() => {
- mountComponent();
- });
-
it('should send sentry_issue_identifier', () => {
const sentryErrorIdInput = findInput(
'issue[sentry_issue_attributes][sentry_issue_identifier]',
@@ -275,7 +315,8 @@ describe('ErrorDetails', () => {
describe('when error is unresolved', () => {
beforeEach(() => {
store.state.details.errorStatus = errorStatus.UNRESOLVED;
- mountComponent();
+
+ return wrapper.vm.$nextTick();
});
it('displays Ignore and Resolve buttons', () => {
@@ -301,7 +342,8 @@ describe('ErrorDetails', () => {
describe('when error is ignored', () => {
beforeEach(() => {
store.state.details.errorStatus = errorStatus.IGNORED;
- mountComponent();
+
+ return wrapper.vm.$nextTick();
});
it('displays Undo Ignore and Resolve buttons', () => {
@@ -327,7 +369,8 @@ describe('ErrorDetails', () => {
describe('when error is resolved', () => {
beforeEach(() => {
store.state.details.errorStatus = errorStatus.RESOLVED;
- mountComponent();
+
+ return wrapper.vm.$nextTick();
});
it('displays Ignore and Unresolve buttons', () => {
diff --git a/spec/helpers/markup_helper_spec.rb b/spec/helpers/markup_helper_spec.rb
index 96c8b557625..33347f20de8 100644
--- a/spec/helpers/markup_helper_spec.rb
+++ b/spec/helpers/markup_helper_spec.rb
@@ -114,7 +114,7 @@ describe MarkupHelper do
let(:requested_path) { nil }
it 'returns the link to the image path as a relative path' do
- expanded_path = "/#{project.full_path}/master/./#{image_file}"
+ expanded_path = "/#{project.full_path}/-/blob/master/./#{image_file}"
expect(subject.css('a')[0].attr('href')).to eq(expanded_path)
end
diff --git a/spec/lib/banzai/filter/repository_link_filter_spec.rb b/spec/lib/banzai/filter/repository_link_filter_spec.rb
index f093a5b0a79..460c76acd78 100644
--- a/spec/lib/banzai/filter/repository_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/repository_link_filter_spec.rb
@@ -145,7 +145,7 @@ describe Banzai::Filter::RepositoryLinkFilter do
it 'ignores ref if commit is passed' do
doc = filter(link('non/existent.file'), commit: project.commit('empty-branch') )
expect(doc.at_css('a')['href'])
- .to eq "/#{project_path}/#{ref}/non/existent.file" # non-existent files have no leading blob/raw/tree
+ .to eq "/#{project_path}/-/blob/#{ref}/non/existent.file"
end
shared_examples :valid_repository do
@@ -201,6 +201,12 @@ describe Banzai::Filter::RepositoryLinkFilter do
.to eq "/#{project_path}/-/blob/#{ref}/doc/api/README.md"
end
+ it 'rebuilds relative URL for a missing file in the repo' do
+ doc = filter(link('missing-file'))
+ expect(doc.at_css('a')['href'])
+ .to eq "/#{project_path}/-/blob/#{ref}/missing-file"
+ end
+
it 'rebuilds relative URL for a file in the repo with leading ./' do
doc = filter(link('./doc/api/README.md'))
expect(doc.at_css('a')['href'])
diff --git a/spec/models/concerns/bulk_insertable_associations_spec.rb b/spec/models/concerns/bulk_insertable_associations_spec.rb
index 9e584417697..6359b2c57ef 100644
--- a/spec/models/concerns/bulk_insertable_associations_spec.rb
+++ b/spec/models/concerns/bulk_insertable_associations_spec.rb
@@ -57,16 +57,12 @@ describe BulkInsertableAssociations do
end
end
- before do
- ActiveRecord::Base.connection.execute('TRUNCATE bulk_foos RESTART IDENTITY')
- end
-
context 'saving bulk insertable associations' do
let(:parent) { BulkParent.new(name: 'parent') }
context 'when items already have IDs' do
it 'stores nothing and raises an error' do
- build_items(parent: parent) { |n, item| item.id = 100 + n }
+ build_items(parent: parent) { |n, item| item.id = n }
expect { save_with_bulk_inserts(parent) }.to raise_error(BulkInsertSafe::PrimaryKeySetError)
expect(BulkFoo.count).to eq(0)
@@ -79,7 +75,7 @@ describe BulkInsertableAssociations do
expect(BulkFoo).to receive(:bulk_insert!).once.and_call_original
expect { save_with_bulk_inserts(parent) }.to change { BulkFoo.count }.from(0).to(items.size)
- expect(parent.bulk_foos.pluck(:id)).to contain_exactly(*(1..10))
+ expect(parent.bulk_foos.pluck(:id)).to all(be_a Integer)
end
end
diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb
index af179e81b08..ca4a81773aa 100644
--- a/spec/support/capybara.rb
+++ b/spec/support/capybara.rb
@@ -23,6 +23,18 @@ JS_CONSOLE_FILTER = Regexp.union([
CAPYBARA_WINDOW_SIZE = [1366, 768].freeze
+# Run Workhorse on the given host and port, proxying to Puma on a UNIX socket,
+# for a closer-to-production experience
+Capybara.register_server :puma_via_workhorse do |app, port, host, **options|
+ file = Tempfile.new
+ socket_path = file.path
+ file.close! # We just want the filename
+
+ TestEnv.with_workhorse(TestEnv.workhorse_dir, host, port, socket_path) do
+ Capybara.servers[:puma].call(app, nil, socket_path, **options)
+ end
+end
+
Capybara.register_driver :chrome do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
# This enables access to logs with `page.driver.manage.get_log(:browser)`
@@ -60,7 +72,7 @@ Capybara.register_driver :chrome do |app|
)
end
-Capybara.server = :puma
+Capybara.server = :puma_via_workhorse
Capybara.javascript_driver = :chrome
Capybara.default_max_wait_time = timeout
Capybara.ignore_hidden_elements = true
@@ -101,6 +113,18 @@ RSpec.configure do |config|
end
end
+ # The :capybara_ignore_server_errors metadata means unhandled exceptions raised
+ # by the application under test will not necessarily fail the server. This is
+ # useful when testing conditions that are expected to raise a 500 error in
+ # production; it should not be used on the happy path.
+ config.around(:each, :capybara_ignore_server_errors) do |example|
+ Capybara.raise_server_errors = false
+
+ example.run
+ ensure
+ Capybara.raise_server_errors = true
+ end
+
config.after(:example, :js) do |example|
# when a test fails, display any messages in the browser's console
# but fail don't add the message if the failure is a pending test that got
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index bd945fe6409..0320f966c37 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -104,6 +104,9 @@ module TestEnv
setup_gitaly
+ # Feature specs are run through Workhorse
+ setup_workhorse
+
# Create repository for FactoryBot.create(:project)
setup_factory_repo
@@ -218,6 +221,52 @@ module TestEnv
ENV.fetch('GITALY_REPO_URL', nil)
end
+ def setup_workhorse
+ install_workhorse_args = [workhorse_dir, workhorse_url].compact.join(',')
+
+ component_timed_setup(
+ 'GitLab Workhorse',
+ install_dir: workhorse_dir,
+ version: Gitlab::Workhorse.version,
+ task: "gitlab:workhorse:install[#{install_workhorse_args}]"
+ )
+ end
+
+ def workhorse_dir
+ @workhorse_path ||= File.join('tmp', 'tests', 'gitlab-workhorse')
+ end
+
+ def with_workhorse(workhorse_dir, host, port, upstream, &blk)
+ host = "[#{host}]" if host.include?(':')
+ listen_addr = [host, port].join(':')
+
+ workhorse_pid = spawn(
+ File.join(workhorse_dir, 'gitlab-workhorse'),
+ '-authSocket', upstream,
+ '-documentRoot', Rails.root.join('public').to_s,
+ '-listenAddr', listen_addr,
+ '-secretPath', Gitlab::Workhorse.secret_path.to_s,
+ # TODO: Needed for workhorse + redis features.
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/209245
+ #
+ # '-config', '',
+ '-logFile', 'log/workhorse-test.log',
+ '-logFormat', 'structured',
+ '-developmentMode' # to serve assets and rich error messages
+ )
+
+ begin
+ yield
+ ensure
+ Process.kill('TERM', workhorse_pid)
+ Process.wait(workhorse_pid)
+ end
+ end
+
+ def workhorse_url
+ ENV.fetch('GITLAB_WORKHORSE_URL', nil)
+ end
+
def setup_factory_repo
setup_repo(factory_repo_path, factory_repo_path_bare, factory_repo_name,
BRANCH_SHA)
@@ -347,6 +396,8 @@ module TestEnv
gitlab-test_bare
gitlab-test-fork
gitlab-test-fork_bare
+ gitlab-workhorse
+ gitlab_workhorse_secret
]
end
diff --git a/spec/support/shared_examples/features/wiki_file_attachments_shared_examples.rb b/spec/support/shared_examples/features/wiki_file_attachments_shared_examples.rb
index 867290fb2d6..d30e8241da0 100644
--- a/spec/support/shared_examples/features/wiki_file_attachments_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki_file_attachments_shared_examples.rb
@@ -20,7 +20,7 @@ RSpec.shared_examples 'wiki file attachments' do
end
end
- context 'uploading is in progress' do
+ context 'uploading is in progress', :capybara_ignore_server_errors do
it 'cancels uploading on clicking to "Cancel" button' do
slow_requests do
attach_with_dropzone