summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-19 15:09:41 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-19 15:09:41 +0000
commit78d8830cec030ff12afed3c8ae1dddec454d0a24 (patch)
treeb5494f60c7d28be787eee7872fd3d99dcbf9f8c8
parent652bd073731b0028641672a75355c7918b5ac116 (diff)
downloadgitlab-ce-78d8830cec030ff12afed3c8ae1dddec454d0a24.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml23
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml6
-rw-r--r--GITLAB_WORKHORSE_VERSION2
-rw-r--r--app/assets/javascripts/registry/explorer/pages/details.vue1
-rw-r--r--app/controllers/import/gitlab_projects_controller.rb13
-rw-r--r--app/models/ci/build.rb18
-rw-r--r--app/views/layouts/_head.html.haml2
-rw-r--r--changelogs/unreleased/197926-add-branch-to-package-title.yml5
-rw-r--r--changelogs/unreleased/208674-use-wh-accel-only-for-ui-imports.yml5
-rw-r--r--changelogs/unreleased/refactor-admin-mode-single-session.yml5
-rw-r--r--changelogs/unreleased/remove-asset-host-prefetch-feature-flag.yml5
-rw-r--r--lib/gitlab/auth/current_user_mode.rb15
-rw-r--r--lib/tasks/gitlab/assets.rake75
-rw-r--r--package.json4
-rw-r--r--spec/controllers/import/gitlab_projects_controller_spec.rb100
-rw-r--r--spec/features/groups/navbar_spec.rb85
-rw-r--r--spec/features/projects/navbar_spec.rb135
-rw-r--r--spec/features/projects/snippets/user_comments_on_snippet_spec.rb6
-rw-r--r--spec/frontend/registry/explorer/pages/details_spec.js4
-rw-r--r--spec/lib/gitlab/auth/current_user_mode_spec.rb4
-rw-r--r--spec/models/project_services/bugzilla_service_spec.rb2
-rw-r--r--spec/requests/import/gitlab_projects_controller_spec.rb139
-rw-r--r--spec/support/helpers/navbar_structure_helper.rb21
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb163
-rw-r--r--spec/views/layouts/_head.html.haml_spec.rb25
-rw-r--r--yarn.lock18
26 files changed, 501 insertions, 380 deletions
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 8685ccc5432..630e9dfd06a 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -2,6 +2,8 @@
cache:
paths:
- vendor/ruby/
+ - public/assets/webpack/
+ - assets-hash.txt
- .yarn-cache/
- tmp/cache/assets/sprockets
- tmp/cache/babel-loader
@@ -28,18 +30,24 @@
DOCKER_DRIVER: overlay2
DOCKER_HOST: tcp://docker:2375
cache:
- key: "assets-compile:production:vendor_ruby:.yarn-cache:tmp_cache_assets_sprockets:tmp_cache_webpack:v9"
+ key: "assets-compile:production:v1"
artifacts:
name: webpack-report
expire_in: 31d
paths:
- webpack-report/
- - public/assets/
+ - assets-compile.log
+ - public/assets/application-*.css
+ - public/assets/application-*.css.gz
+ when: always
script:
- node --version
- retry yarn install --frozen-lockfile --production --cache-folder .yarn-cache --prefer-offline
- free -m
- - retry bundle exec rake gitlab:assets:compile
+ - time bin/rake gitlab:assets:compile > assets-compile.log 2>&1
+ # TODO: Change the image tag to be the MD5 of assets files and skip image building if the image exists
+ # We'll also need to pass GITLAB_ASSETS_TAG to the trigerred omnibus-gitlab pipeline similarly to how we do it for trigerred CNG pipelines
+ # https://gitlab.com/gitlab-org/gitlab/issues/208389
- time scripts/build_assets_image
- scripts/clean-old-cached-assets
- rm -f /etc/apt/sources.list.d/google*.list # We don't need to update Chrome here
@@ -71,7 +79,7 @@ gitlab:assets:compile pull-cache:
- node --version
- retry yarn install --frozen-lockfile --cache-folder .yarn-cache --prefer-offline
- free -m
- - retry bundle exec rake gitlab:assets:compile
+ - time bin/rake gitlab:assets:compile > assets-compile.log 2>&1
- scripts/clean-old-cached-assets
variables:
SETUP_DB: "false"
@@ -79,12 +87,13 @@ gitlab:assets:compile pull-cache:
NODE_OPTIONS: --max_old_space_size=3584
WEBPACK_VENDOR_DLL: "true"
cache:
- key: "assets-compile:v9"
+ key: "assets-compile:test:v1"
artifacts:
expire_in: 7d
paths:
- node_modules
- public/assets
+ - assets-compile.log
compile-assets pull-push-cache:
extends:
@@ -100,7 +109,7 @@ compile-assets pull-push-cache as-if-foss:
- .as-if-foss
cache:
policy: pull-push
- key: "assets-compile:v9:foss"
+ key: "assets-compile:test:as-if-foss:v1"
compile-assets pull-cache:
extends:
@@ -116,7 +125,7 @@ compile-assets pull-cache as-if-foss:
- .as-if-foss
cache:
policy: pull
- key: "assets-compile:v9:foss"
+ key: "assets-compile:test:as-if-foss:v1"
.frontend-fixtures-base:
extends:
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index b0713c0944a..8a8f66a4643 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -55,5 +55,9 @@ package-and-qa:
extends:
- .package-and-qa-base
- .qa:rules:package-and-qa
- needs: ["build-qa-image", "gitlab:assets:compile pull-cache"]
+ needs:
+ - job: build-qa-image
+ artifacts: false
+ - job: gitlab:assets:compile pull-cache
+ artifacts: false
allow_failure: true
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index f062572ef7b..c4ca5ee3475 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-8.25.0
+8.26.0
diff --git a/app/assets/javascripts/registry/explorer/pages/details.vue b/app/assets/javascripts/registry/explorer/pages/details.vue
index 88e437b16d9..be9a27e2c42 100644
--- a/app/assets/javascripts/registry/explorer/pages/details.vue
+++ b/app/assets/javascripts/registry/explorer/pages/details.vue
@@ -327,6 +327,7 @@ export default {
</gl-table>
<gl-pagination
+ v-if="!isLoading"
ref="pagination"
v-model="currentPage"
:per-page="tagsPagination.perPage"
diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb
index 6b8436d766c..6a3715a4675 100644
--- a/app/controllers/import/gitlab_projects_controller.rb
+++ b/app/controllers/import/gitlab_projects_controller.rb
@@ -48,14 +48,7 @@ class Import::GitlabProjectsController < Import::BaseController
private
def file_is_valid?
- # 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
+ return false unless project_params[:file].is_a?(::UploadedFile)
filename = project_params[:file].original_filename
@@ -75,8 +68,4 @@ 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/models/ci/build.rb b/app/models/ci/build.rb
index 517f2312a76..b555b78cda6 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -598,19 +598,15 @@ module Ci
end
def merge_request
- return @merge_request if defined?(@merge_request)
+ strong_memoize(:merge_request) do
+ merge_requests = MergeRequest.includes(:latest_merge_request_diff)
+ .where(source_branch: ref, source_project: pipeline.project)
+ .reorder(iid: :desc)
- @merge_request ||=
- begin
- merge_requests = MergeRequest.includes(:latest_merge_request_diff)
- .where(source_branch: ref,
- source_project: pipeline.project)
- .reorder(iid: :desc)
-
- merge_requests.find do |merge_request|
- merge_request.commit_shas.include?(pipeline.sha)
- end
+ merge_requests.find do |merge_request|
+ merge_request.commit_shas.include?(pipeline.sha)
end
+ end
end
def repo_url
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index 6b336f3eba2..8c272a73d40 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -16,7 +16,7 @@
%head{ prefix: "og: http://ogp.me/ns#" }
%meta{ charset: "utf-8" }
- - if Feature.enabled?('asset_host_prefetch') && ActionController::Base.asset_host
+ - if ActionController::Base.asset_host
%link{ rel: 'dns-prefetch', href: ActionController::Base.asset_host }
%link{ rel: 'preconnnect', href: ActionController::Base.asset_host, crossorigin: '' }
diff --git a/changelogs/unreleased/197926-add-branch-to-package-title.yml b/changelogs/unreleased/197926-add-branch-to-package-title.yml
new file mode 100644
index 00000000000..65d53e10c6f
--- /dev/null
+++ b/changelogs/unreleased/197926-add-branch-to-package-title.yml
@@ -0,0 +1,5 @@
+---
+title: Adds branch information to the package details title section
+merge_request: 27488
+author:
+type: added
diff --git a/changelogs/unreleased/208674-use-wh-accel-only-for-ui-imports.yml b/changelogs/unreleased/208674-use-wh-accel-only-for-ui-imports.yml
new file mode 100644
index 00000000000..3b74580bd3b
--- /dev/null
+++ b/changelogs/unreleased/208674-use-wh-accel-only-for-ui-imports.yml
@@ -0,0 +1,5 @@
+---
+title: Enable Workhorse upload acceleration for Project Import uploads via UI
+merge_request: 27332
+author:
+type: performance
diff --git a/changelogs/unreleased/refactor-admin-mode-single-session.yml b/changelogs/unreleased/refactor-admin-mode-single-session.yml
new file mode 100644
index 00000000000..4457394e5f7
--- /dev/null
+++ b/changelogs/unreleased/refactor-admin-mode-single-session.yml
@@ -0,0 +1,5 @@
+---
+title: Disable lookup of other ActiveSessions to determine admin mode status
+merge_request: 27318
+author: Diego Louzán
+type: changed
diff --git a/changelogs/unreleased/remove-asset-host-prefetch-feature-flag.yml b/changelogs/unreleased/remove-asset-host-prefetch-feature-flag.yml
new file mode 100644
index 00000000000..d08cdb27337
--- /dev/null
+++ b/changelogs/unreleased/remove-asset-host-prefetch-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Prefetch DNS for asset host
+merge_request: 26868
+author:
+type: performance
diff --git a/lib/gitlab/auth/current_user_mode.rb b/lib/gitlab/auth/current_user_mode.rb
index 06ae4d81870..0f327a39f61 100644
--- a/lib/gitlab/auth/current_user_mode.rb
+++ b/lib/gitlab/auth/current_user_mode.rb
@@ -77,7 +77,7 @@ module Gitlab
return false unless user
Gitlab::SafeRequestStore.fetch(admin_mode_rs_key) do
- user.admin? && any_session_with_admin_mode?
+ user.admin? && session_with_admin_mode?
end
end
@@ -136,19 +136,10 @@ module Gitlab
@current_session ||= Gitlab::NamespacedSessionStore.new(SESSION_STORE_KEY)
end
- def any_session_with_admin_mode?
+ def session_with_admin_mode?
return true if bypass_session?
- return true if current_session_data.initiated? && current_session_data[ADMIN_MODE_START_TIME_KEY].to_i > MAX_ADMIN_MODE_TIME.ago.to_i
- all_sessions.any? do |session|
- session[ADMIN_MODE_START_TIME_KEY].to_i > MAX_ADMIN_MODE_TIME.ago.to_i
- end
- end
-
- def all_sessions
- @all_sessions ||= ActiveSession.list_sessions(user).lazy.map do |session|
- Gitlab::NamespacedSessionStore.new(SESSION_STORE_KEY, session.with_indifferent_access )
- end
+ current_session_data.initiated? && current_session_data[ADMIN_MODE_START_TIME_KEY].to_i > MAX_ADMIN_MODE_TIME.ago.to_i
end
def admin_mode_requested_in_grace_period?
diff --git a/lib/tasks/gitlab/assets.rake b/lib/tasks/gitlab/assets.rake
index b398bbe403f..69a3526b872 100644
--- a/lib/tasks/gitlab/assets.rake
+++ b/lib/tasks/gitlab/assets.rake
@@ -1,3 +1,48 @@
+# frozen_string_literal: true
+
+require 'fileutils'
+
+module Tasks
+ module Gitlab
+ module Assets
+ FOSS_ASSET_FOLDERS = %w[app/assets app/views fixtures/emojis vendor/assets/javascripts].freeze
+ EE_ASSET_FOLDERS = %w[ee/app/assets ee/app/views].freeze
+ JS_ASSET_PATTERNS = %w[*.js config/**/*.js].freeze
+ JS_ASSET_FILES = %w[package.json yarn.lock].freeze
+ MASTER_MD5_HASH_FILE = 'master-assets-hash.txt'
+ HEAD_MD5_HASH_FILE = 'assets-hash.txt'
+ PUBLIC_ASSETS_WEBPACK_DIR = 'public/assets/webpack'
+
+ def self.md5_of_assets_impacting_webpack_compilation
+ start_time = Time.now
+ asset_files = assets_impacting_webpack_compilation
+ puts "Generating the MD5 hash for #{assets_impacting_webpack_compilation.size} Webpack-related assets..."
+
+ asset_file_md5s = asset_files.map do |asset_file|
+ Digest::MD5.file(asset_file).hexdigest
+ end
+
+ Digest::MD5.hexdigest(asset_file_md5s.join).tap { |md5| puts "=> MD5 generated in #{Time.now - start_time}: #{md5}" }
+ end
+
+ def self.assets_impacting_webpack_compilation
+ assets_folders = FOSS_ASSET_FOLDERS
+ assets_folders += EE_ASSET_FOLDERS if ::Gitlab.ee?
+
+ asset_files = Dir.glob(JS_ASSET_PATTERNS)
+ asset_files += JS_ASSET_FILES
+
+ assets_folders.each do |folder|
+ asset_files.concat(Dir.glob(["#{folder}/**/*.*"]))
+ end
+
+ asset_files
+ end
+ private_class_method :assets_impacting_webpack_compilation
+ end
+ end
+end
+
namespace :gitlab do
namespace :assets do
desc 'GitLab | Assets | Compile all frontend assets'
@@ -8,9 +53,35 @@ namespace :gitlab do
yarn:check
gettext:po_to_json
rake:assets:precompile
- webpack:compile
+ gitlab:assets:compile_webpack_if_needed
gitlab:assets:fix_urls
- ].each(&Gitlab::TaskHelpers.method(:invoke_and_time_task))
+ ].each(&::Gitlab::TaskHelpers.method(:invoke_and_time_task))
+ end
+
+ desc 'GitLab | Assets | Compile all Webpack assets'
+ task :compile_webpack_if_needed do
+ FileUtils.mv(Tasks::Gitlab::Assets::HEAD_MD5_HASH_FILE, Tasks::Gitlab::Assets::MASTER_MD5_HASH_FILE, force: true)
+
+ master_assets_md5 =
+ if File.exist?(Tasks::Gitlab::Assets::MASTER_MD5_HASH_FILE)
+ File.read(Tasks::Gitlab::Assets::MASTER_MD5_HASH_FILE)
+ else
+ 'missing!'
+ end
+
+ head_assets_md5 = Tasks::Gitlab::Assets.md5_of_assets_impacting_webpack_compilation.tap do |md5|
+ File.write(Tasks::Gitlab::Assets::HEAD_MD5_HASH_FILE, md5)
+ end
+
+ puts "Webpack assets MD5 for `master`: #{master_assets_md5}"
+ puts "Webpack assets MD5 for `HEAD`: #{head_assets_md5}"
+
+ public_assets_webpack_dir_exists = Dir.exist?(Tasks::Gitlab::Assets::PUBLIC_ASSETS_WEBPACK_DIR)
+
+ if head_assets_md5 != master_assets_md5 || !public_assets_webpack_dir_exists
+ FileUtils.rm_r(Tasks::Gitlab::Assets::PUBLIC_ASSETS_WEBPACK_DIR) if public_assets_webpack_dir_exists
+ Rake::Task['webpack:compile'].invoke
+ end
end
desc 'GitLab | Assets | Clean up old compiled frontend assets'
diff --git a/package.json b/package.json
index 11e5da73c23..f4f5d3a7070 100644
--- a/package.json
+++ b/package.json
@@ -39,8 +39,8 @@
"@babel/plugin-syntax-import-meta": "^7.8.3",
"@babel/preset-env": "^7.8.4",
"@gitlab/at.js": "^1.5.5",
- "@gitlab/svgs": "^1.113.0",
- "@gitlab/ui": "^9.29.0",
+ "@gitlab/svgs": "^1.114.0",
+ "@gitlab/ui": "^9.31.1",
"@gitlab/visual-review-tools": "1.5.1",
"@sentry/browser": "^5.10.2",
"@sourcegraph/code-host-integration": "0.0.31",
diff --git a/spec/controllers/import/gitlab_projects_controller_spec.rb b/spec/controllers/import/gitlab_projects_controller_spec.rb
deleted file mode 100644
index 0b74e2bbcbf..00000000000
--- a/spec/controllers/import/gitlab_projects_controller_spec.rb
+++ /dev/null
@@ -1,100 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe Import::GitlabProjectsController do
- let_it_be(:namespace) { create(:namespace) }
- let_it_be(:user) { namespace.owner }
- let(:file) { fixture_file_upload('spec/fixtures/project_export.tar.gz', 'text/plain') }
-
- before do
- sign_in(user)
- end
-
- describe 'POST create' do
- context 'with an invalid path' do
- it 'redirects with an error' do
- post :create, params: { namespace_id: namespace.id, path: '/test', file: file }
-
- expect(flash[:alert]).to start_with('Project could not be imported')
- expect(response).to have_gitlab_http_status(:found)
- end
-
- it 'redirects with an error when a relative path is used' do
- post :create, params: { namespace_id: namespace.id, path: '../test', file: file }
-
- expect(flash[:alert]).to start_with('Project could not be imported')
- expect(response).to have_gitlab_http_status(:found)
- end
- end
-
- context 'with a valid path' do
- it 'redirects to the new project path' do
- post :create, params: { namespace_id: namespace.id, path: 'test', file: file }
-
- expect(flash[:notice]).to include('is being imported')
- expect(response).to have_gitlab_http_status(:found)
- end
- end
-
- 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/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb
index 0c457c11fce..0cdc2aa88f4 100644
--- a/spec/features/groups/navbar_spec.rb
+++ b/spec/features/groups/navbar_spec.rb
@@ -3,90 +3,21 @@
require 'spec_helper'
describe 'Group navbar' do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
+ include NavbarStructureHelper
- let(:analytics_nav_item) do
- {
- nav_item: _('Analytics'),
- nav_sub_items: [
- _('Contribution')
- ]
- }
- end
+ include_context 'group navbar structure'
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
- let(:structure) do
- [
- {
- nav_item: _('Group overview'),
- nav_sub_items: [
- _('Details'),
- _('Activity')
- ]
- },
- {
- nav_item: _('Issues'),
- nav_sub_items: [
- _('List'),
- _('Board'),
- _('Labels'),
- _('Milestones')
- ]
- },
- {
- nav_item: _('Merge Requests'),
- nav_sub_items: []
- },
- {
- nav_item: _('Kubernetes'),
- nav_sub_items: []
- },
- (analytics_nav_item if Gitlab.ee?),
- {
- nav_item: _('Members'),
- nav_sub_items: []
- }
- ]
+ before do
+ group.add_maintainer(user)
+ sign_in(user)
end
it_behaves_like 'verified navigation bar' do
before do
- group.add_maintainer(user)
- sign_in(user)
-
visit group_path(group)
end
end
-
- if Gitlab.ee?
- context 'when productivity analytics is available' do
- before do
- stub_licensed_features(productivity_analytics: true)
-
- analytics_nav_item[:nav_sub_items] << _('Productivity')
-
- group.add_maintainer(user)
- sign_in(user)
-
- visit group_path(group)
- end
-
- it_behaves_like 'verified navigation bar'
- end
-
- context 'when value stream analytics is available' do
- before do
- stub_licensed_features(cycle_analytics_for_groups: true)
-
- analytics_nav_item[:nav_sub_items] << _('Value Stream')
-
- group.add_maintainer(user)
- sign_in(user)
-
- visit group_path(group)
- end
-
- it_behaves_like 'verified navigation bar'
- end
- end
end
diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb
index 2b8dfc4a5fa..6dbcace5401 100644
--- a/spec/features/projects/navbar_spec.rb
+++ b/spec/features/projects/navbar_spec.rb
@@ -3,112 +3,14 @@
require 'spec_helper'
describe 'Project navbar' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
+ include NavbarStructureHelper
- let(:analytics_nav_item) do
- {
- nav_item: _('Analytics'),
- nav_sub_items: [
- _('CI / CD'),
- (_('Code Review') if Gitlab.ee?),
- _('Repository'),
- _('Value Stream')
- ]
- }
- end
+ include_context 'project navbar structure'
- let(:requirements_nav_item) do
- {
- nav_item: _('Requirements'),
- nav_sub_items: [_('List')]
- }
- end
-
- let(:structure) do
- [
- {
- nav_item: _('Project overview'),
- nav_sub_items: [
- _('Details'),
- _('Activity'),
- _('Releases')
- ]
- },
- {
- nav_item: _('Repository'),
- nav_sub_items: [
- _('Files'),
- _('Commits'),
- _('Branches'),
- _('Tags'),
- _('Contributors'),
- _('Graph'),
- _('Compare'),
- (_('Locked Files') if Gitlab.ee?)
- ]
- },
- {
- nav_item: _('Issues'),
- nav_sub_items: [
- _('List'),
- _('Boards'),
- _('Labels'),
- _('Milestones')
- ]
- },
- {
- nav_item: _('Merge Requests'),
- nav_sub_items: []
- },
- (requirements_nav_item if Gitlab.ee?),
- {
- nav_item: _('CI / CD'),
- nav_sub_items: [
- _('Pipelines'),
- _('Jobs'),
- _('Artifacts'),
- _('Schedules')
- ]
- },
- {
- nav_item: _('Operations'),
- nav_sub_items: [
- _('Metrics'),
- _('Environments'),
- _('Error Tracking'),
- _('Serverless'),
- _('Logs'),
- _('Kubernetes')
- ]
- },
- analytics_nav_item,
- {
- nav_item: _('Wiki'),
- nav_sub_items: []
- },
- {
- nav_item: _('Snippets'),
- nav_sub_items: []
- },
- {
- nav_item: _('Settings'),
- nav_sub_items: [
- _('General'),
- _('Members'),
- _('Integrations'),
- _('Webhooks'),
- _('Repository'),
- _('CI / CD'),
- _('Operations'),
- (_('Audit Events') if Gitlab.ee?)
- ].compact
- }
- ]
- end
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
before do
- stub_licensed_features(requirements: false)
project.add_maintainer(user)
sign_in(user)
end
@@ -119,28 +21,19 @@ describe 'Project navbar' do
end
end
- if Gitlab.ee?
- context 'when issues analytics is available' do
- before do
- stub_licensed_features(issues_analytics: true)
-
- analytics_nav_item[:nav_sub_items] << _('Issues')
- analytics_nav_item[:nav_sub_items].sort!
+ context 'when pages are available' do
+ before do
+ allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
- visit project_path(project)
- end
+ insert_after_sub_nav_item(
+ _('Operations'),
+ within: _('Settings'),
+ new_sub_nav_item_name: _('Pages')
+ )
- it_behaves_like 'verified navigation bar'
+ visit project_path(project)
end
- context 'when requirements is available' do
- before do
- stub_licensed_features(requirements: true)
-
- visit project_path(project)
- end
-
- it_behaves_like 'verified navigation bar'
- end
+ it_behaves_like 'verified navigation bar'
end
end
diff --git a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
index 9d11b55228b..a7a220b926d 100644
--- a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
+++ b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
@@ -13,6 +13,9 @@ describe 'Projects > Snippets > User comments on a snippet', :js do
sign_in(user)
visit(project_snippet_path(project, snippet))
+
+ # Snippet's content is loaded async, we wait for it before we try to click anything
+ wait_for_requests
end
it 'leaves a comment on a snippet' do
@@ -34,7 +37,8 @@ describe 'Projects > Snippets > User comments on a snippet', :js do
end
it 'has zen mode' do
- find('.js-zen-enter').click
+ click_button 'Go full screen'
+
expect(page).to have_selector('.fullscreen')
end
end
diff --git a/spec/frontend/registry/explorer/pages/details_spec.js b/spec/frontend/registry/explorer/pages/details_spec.js
index 15c6b36af03..660004e5eea 100644
--- a/spec/frontend/registry/explorer/pages/details_spec.js
+++ b/spec/frontend/registry/explorer/pages/details_spec.js
@@ -66,6 +66,10 @@ describe('Details Page', () => {
it('does not have list items', () => {
expect(findFirstRowItem('rowCheckbox').exists()).toBe(false);
});
+
+ it('does not show pagination', () => {
+ expect(findPagination().exists()).toBe(false);
+ });
});
describe('table', () => {
diff --git a/spec/lib/gitlab/auth/current_user_mode_spec.rb b/spec/lib/gitlab/auth/current_user_mode_spec.rb
index 2b910fac155..8863f26fbf2 100644
--- a/spec/lib/gitlab/auth/current_user_mode_spec.rb
+++ b/spec/lib/gitlab/auth/current_user_mode_spec.rb
@@ -151,13 +151,13 @@ describe Gitlab::Auth::CurrentUserMode, :do_not_mock_admin_mode, :request_store
allow(ActiveSession).to receive(:list_sessions).with(user).and_return([session, another_session])
end
- it 'can be enabled in one and seen in the other' do
+ it 'cannot be enabled in one and seen in the other' do
Gitlab::Session.with_session(another_session) do
another_subject.request_admin_mode!
another_subject.enable_admin_mode!(password: user.password)
end
- expect(subject.admin_mode?).to be(true)
+ expect(subject.admin_mode?).to be(false)
end
end
end
diff --git a/spec/models/project_services/bugzilla_service_spec.rb b/spec/models/project_services/bugzilla_service_spec.rb
index d0ab5afc765..ab939e0d2f8 100644
--- a/spec/models/project_services/bugzilla_service_spec.rb
+++ b/spec/models/project_services/bugzilla_service_spec.rb
@@ -34,8 +34,6 @@ describe BugzillaService do
end
context 'overriding properties' do
- let(:default_title) { 'JIRA' }
- let(:default_description) { 'JiraService|Jira issue tracker' }
let(:url) { 'http://bugzilla.example.com' }
let(:access_params) do
{ project_url: url, issues_url: url, new_issue_url: url }
diff --git a/spec/requests/import/gitlab_projects_controller_spec.rb b/spec/requests/import/gitlab_projects_controller_spec.rb
new file mode 100644
index 00000000000..f16755e9766
--- /dev/null
+++ b/spec/requests/import/gitlab_projects_controller_spec.rb
@@ -0,0 +1,139 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Import::GitlabProjectsController do
+ include WorkhorseHelpers
+
+ let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
+ let(:workhorse_headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:user) { namespace.owner }
+
+ before do
+ login_as(user)
+ end
+
+ describe 'POST create' do
+ subject { upload_archive(file_upload, workhorse_headers, params) }
+
+ let(:file) { File.join('spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') }
+ let(:file_upload) { fixture_file_upload(file) }
+ let(:params) { { namespace_id: namespace.id, path: 'test' } }
+
+ before do
+ allow(ImportExportUploader).to receive(:workhorse_upload_path).and_return('/')
+ end
+
+ context 'with a valid path' do
+ it 'schedules an import and redirects to the new project path' do
+ stub_import(namespace)
+
+ subject
+
+ expect(flash[:notice]).to include('is being imported')
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+
+ context 'with an invalid path' do
+ ['/test', '../test'].each do |invalid_path|
+ it "redirects with an error when path is `#{invalid_path}`" do
+ params[:path] = invalid_path
+
+ subject
+
+ expect(flash[:alert]).to start_with('Project could not be imported')
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+ end
+
+ context 'when request exceeds the rate limit' do
+ before do
+ allow(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(true)
+ end
+
+ it 'prevents users from importing projects' do
+ subject
+
+ expect(flash[:alert]).to eq('This endpoint has been requested too many times. Try again later.')
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+
+ def upload_archive(file, headers = {}, params = {})
+ workhorse_finalize(
+ import_gitlab_project_path,
+ method: :post,
+ file_key: :file,
+ params: params.merge(file: file),
+ headers: headers,
+ send_rewritten_field: true
+ )
+ end
+
+ def stub_import(namespace)
+ expect_any_instance_of(ProjectImportState).to receive(:schedule)
+ expect(::Projects::CreateService)
+ .to receive(:new)
+ .with(user, instance_of(ActionController::Parameters))
+ .and_call_original
+ end
+ end
+
+ describe 'POST authorize' do
+ subject { post authorize_import_gitlab_project_path, headers: workhorse_headers }
+
+ it 'authorizes importing project with workhorse header' do
+ subject
+
+ 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)
+ end
+
+ it 'rejects requests that bypassed gitlab-workhorse' do
+ workhorse_headers.delete(Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER)
+
+ expect { subject }.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
+ subject
+
+ 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
+ subject
+
+ 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/support/helpers/navbar_structure_helper.rb b/spec/support/helpers/navbar_structure_helper.rb
new file mode 100644
index 00000000000..cfb1b185560
--- /dev/null
+++ b/spec/support/helpers/navbar_structure_helper.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module NavbarStructureHelper
+ def insert_after_nav_item(before_nav_item_name, new_nav_item:)
+ expect(structure).to include(a_hash_including(nav_item: before_nav_item_name))
+
+ index = structure.find_index { |h| h[:nav_item] == before_nav_item_name }
+ structure.insert(index + 1, new_nav_item)
+ end
+
+ def insert_after_sub_nav_item(before_sub_nav_item_name, within:, new_sub_nav_item_name:)
+ expect(structure).to include(a_hash_including(nav_item: within))
+ hash = structure.find { |h| h[:nav_item] == within }
+
+ expect(hash).to have_key(:nav_sub_items)
+ expect(hash[:nav_sub_items]).to include(before_sub_nav_item_name)
+
+ index = hash[:nav_sub_items].find_index(before_sub_nav_item_name)
+ hash[:nav_sub_items].insert(index + 1, new_sub_nav_item_name)
+ end
+end
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
new file mode 100644
index 00000000000..c7df54f9501
--- /dev/null
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -0,0 +1,163 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'project navbar structure' do
+ let(:requirements_nav_item) do
+ {
+ nav_item: _('Requirements'),
+ nav_sub_items: [_('List')]
+ }
+ end
+
+ let(:analytics_nav_item) do
+ {
+ nav_item: _('Analytics'),
+ nav_sub_items: [
+ _('CI / CD'),
+ (_('Code Review') if Gitlab.ee?),
+ _('Repository'),
+ _('Value Stream')
+ ]
+ }
+ end
+
+ let(:structure) do
+ [
+ {
+ nav_item: _('Project overview'),
+ nav_sub_items: [
+ _('Details'),
+ _('Activity'),
+ _('Releases')
+ ]
+ },
+ {
+ nav_item: _('Repository'),
+ nav_sub_items: [
+ _('Files'),
+ _('Commits'),
+ _('Branches'),
+ _('Tags'),
+ _('Contributors'),
+ _('Graph'),
+ _('Compare'),
+ (_('Locked Files') if Gitlab.ee?)
+ ]
+ },
+ {
+ nav_item: _('Issues'),
+ nav_sub_items: [
+ _('List'),
+ _('Boards'),
+ _('Labels'),
+ _('Milestones')
+ ]
+ },
+ {
+ nav_item: _('Merge Requests'),
+ nav_sub_items: []
+ },
+ (requirements_nav_item if Gitlab.ee?),
+ {
+ nav_item: _('CI / CD'),
+ nav_sub_items: [
+ _('Pipelines'),
+ _('Jobs'),
+ _('Artifacts'),
+ _('Schedules')
+ ]
+ },
+ {
+ nav_item: _('Operations'),
+ nav_sub_items: [
+ _('Metrics'),
+ _('Environments'),
+ _('Error Tracking'),
+ _('Serverless'),
+ _('Logs'),
+ _('Kubernetes')
+ ]
+ },
+ analytics_nav_item,
+ {
+ nav_item: _('Wiki'),
+ nav_sub_items: []
+ },
+ {
+ nav_item: _('Snippets'),
+ nav_sub_items: []
+ },
+ {
+ nav_item: _('Settings'),
+ nav_sub_items: [
+ _('General'),
+ _('Members'),
+ _('Integrations'),
+ _('Webhooks'),
+ _('Repository'),
+ _('CI / CD'),
+ _('Operations'),
+ (_('Audit Events') if Gitlab.ee?)
+ ].compact
+ }
+ ].compact
+ end
+end
+
+RSpec.shared_context 'group navbar structure' do
+ let(:analytics_nav_item) do
+ {
+ nav_item: _('Analytics'),
+ nav_sub_items: [
+ _('Contribution')
+ ]
+ }
+ end
+
+ let(:settings_nav_item) do
+ {
+ nav_item: _('Settings'),
+ nav_sub_items: [
+ _('General'),
+ _('Projects'),
+ _('CI / CD'),
+ _('Webhooks'),
+ _('Audit Events'),
+ _('Usage Quotas')
+ ]
+ }
+ end
+
+ let(:structure) do
+ [
+ {
+ nav_item: _('Group overview'),
+ nav_sub_items: [
+ _('Details'),
+ _('Activity')
+ ]
+ },
+ {
+ nav_item: _('Issues'),
+ nav_sub_items: [
+ _('List'),
+ _('Board'),
+ _('Labels'),
+ _('Milestones')
+ ]
+ },
+ {
+ nav_item: _('Merge Requests'),
+ nav_sub_items: []
+ },
+ {
+ nav_item: _('Kubernetes'),
+ nav_sub_items: []
+ },
+ (analytics_nav_item if Gitlab.ee?),
+ {
+ nav_item: _('Members'),
+ nav_sub_items: []
+ }
+ ]
+ end
+end
diff --git a/spec/views/layouts/_head.html.haml_spec.rb b/spec/views/layouts/_head.html.haml_spec.rb
index f181e18e53d..8d7dcfc2416 100644
--- a/spec/views/layouts/_head.html.haml_spec.rb
+++ b/spec/views/layouts/_head.html.haml_spec.rb
@@ -34,36 +34,23 @@ describe 'layouts/_head' do
expect(rendered).to match(%{content="foo&quot; http-equiv=&quot;refresh"})
end
- context 'when an asset_host is set and feature is activated in the config it will' do
+ context 'when an asset_host is set' do
let(:asset_host) { 'http://assets' }
before do
- stub_feature_flags(asset_host_prefetch: true)
allow(ActionController::Base).to receive(:asset_host).and_return(asset_host)
end
- it 'add a link dns-prefetch tag' do
+ it 'adds a link dns-prefetch tag' do
render
- expect(rendered).to match('<link href="http://assets" rel="dns-prefetch">')
- end
-
- it 'add a link preconnect tag' do
- render
- expect(rendered).to match('<link crossorigin="" href="http://assets" rel="preconnnect">')
- end
- end
- context 'when an asset_host is set and feature is not activated in the config it will' do
- let(:asset_host) { 'http://assets' }
-
- before do
- stub_feature_flags(asset_host_prefetch: false)
- allow(ActionController::Base).to receive(:asset_host).and_return(asset_host)
+ expect(rendered).to match(%Q(<link href="#{asset_host}" rel="dns-prefetch">))
end
- it 'not add a link dns-prefetch tag' do
+ it 'adds a link preconnect tag' do
render
- expect(rendered).not_to match('<link href="http://assets" rel="dns-prefetch">')
+
+ expect(rendered).to match(%Q(<link crossorigin="" href="#{asset_host}" rel="preconnnect">))
end
end
diff --git a/yarn.lock b/yarn.lock
index 7342879af10..00c6486764b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -781,15 +781,15 @@
eslint-plugin-vue "^6.2.1"
vue-eslint-parser "^7.0.0"
-"@gitlab/svgs@^1.113.0":
- version "1.113.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.113.0.tgz#0ea9cb3122a479f3ed4bb22943d68a9a38f69948"
- integrity sha512-upT+sKEnnwZDU7vzI5VSyg2l6IOd/0Icm/MLae6po/nOGbf2vftkUVfbalzISAmk9eYTuJQ1sGmRWdKXPGy1cw==
-
-"@gitlab/ui@^9.29.0":
- version "9.29.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-9.29.0.tgz#2308aec1d3d837392eaaf9d441aecec4b695ed73"
- integrity sha512-zIY/aChWaU4UBlAjZ95PpBxgUd9VrGiXs9ujVU6Gbi+ZsHbpDvPlBHsHEG9isnUVBE2AD4GPqMLO8K9i+B9O4A==
+"@gitlab/svgs@^1.114.0":
+ version "1.114.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.114.0.tgz#ffee243fa540016c8198596686a46e3c459adb32"
+ integrity sha512-r2tizWDx1fX2QbeXzU0Z5Fi9YS7TLIxt7K+vAnZxOeddgd5KdipCvhT/H7n9Oa9jLU4bMwGSrHZ1usCmCoWOnw==
+
+"@gitlab/ui@^9.31.1":
+ version "9.31.1"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-9.31.1.tgz#53206aac643d79f8eddbc5715131bad5ffc1e412"
+ integrity sha512-MHBVIpVzUYPkr70ti21dTZbzzZttOidWZdN3TeZOdqYbjYg2ONujFBxOGSCNYcaMYr+1/wFtuVRL/JmMVGjJrg==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"