Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
5ca56fbe46
commit
67e7b5a9ba
13 changed files with 120 additions and 144 deletions
|
@ -47,6 +47,8 @@ class Import::BulkImportsController < ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
return render json: { success: false }, status: :unprocessable_entity unless valid_create_params?
|
||||
|
||||
responses = create_params.map do |entry|
|
||||
if entry[:destination_name]
|
||||
entry[:destination_slug] ||= entry[:destination_name]
|
||||
|
@ -102,6 +104,10 @@ class Import::BulkImportsController < ApplicationController
|
|||
params.permit(bulk_import: bulk_import_params)[:bulk_import]
|
||||
end
|
||||
|
||||
def valid_create_params?
|
||||
create_params.all? { _1[:source_type] == 'group_entity' }
|
||||
end
|
||||
|
||||
def bulk_import_params
|
||||
%i[
|
||||
source_type
|
||||
|
|
|
@ -149,6 +149,13 @@ class BulkImports::Entity < ApplicationRecord
|
|||
end
|
||||
|
||||
def validate_imported_entity_type
|
||||
if project_entity? && !BulkImports::Features.project_migration_enabled?(destination_name)
|
||||
errors.add(
|
||||
:base,
|
||||
s_('BulkImport|invalid entity source type')
|
||||
)
|
||||
end
|
||||
|
||||
if group.present? && project_entity?
|
||||
errors.add(
|
||||
:group,
|
||||
|
|
|
@ -13,7 +13,6 @@ module ResourceAccessTokens
|
|||
return error("User does not have permission to create #{resource_type} access token") unless has_permission_to_create?
|
||||
|
||||
access_level = params[:access_level] || Gitlab::Access::MAINTAINER
|
||||
return error("Could not provision owner access to project access token") if do_not_allow_owner_access_level_for_project_bot?(access_level)
|
||||
|
||||
user = create_user
|
||||
|
||||
|
@ -108,7 +107,7 @@ module ResourceAccessTokens
|
|||
end
|
||||
|
||||
def create_membership(resource, user, access_level)
|
||||
resource.add_member(user, access_level, expires_at: params[:expires_at])
|
||||
resource.add_member(user, access_level, current_user: current_user, expires_at: params[:expires_at])
|
||||
end
|
||||
|
||||
def log_event(token)
|
||||
|
@ -122,12 +121,6 @@ module ResourceAccessTokens
|
|||
def success(access_token)
|
||||
ServiceResponse.success(payload: { access_token: access_token })
|
||||
end
|
||||
|
||||
def do_not_allow_owner_access_level_for_project_bot?(access_level)
|
||||
resource.is_a?(Project) &&
|
||||
access_level == Gitlab::Access::OWNER &&
|
||||
!current_user.can?(:manage_owners, resource)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -41,13 +41,13 @@ We were using Overcommit prior to Lefthook, so you may want to uninstall it firs
|
|||
bundle exec lefthook install
|
||||
```
|
||||
|
||||
1. Test Lefthook is working by running the Lefthook `prepare-commit-msg` Git hook:
|
||||
1. Test Lefthook is working by running the Lefthook `pre-push` Git hook:
|
||||
|
||||
```shell
|
||||
bundle exec lefthook run prepare-commit-msg
|
||||
bundle exec lefthook run pre-push
|
||||
```
|
||||
|
||||
This should return a fully qualified path command with no other output.
|
||||
This should return the lefthook version and the list of executable commands with output.
|
||||
|
||||
### Lefthook configuration
|
||||
|
||||
|
|
|
@ -5,5 +5,15 @@ module BulkImports
|
|||
def self.enabled?
|
||||
::Feature.enabled?(:bulk_import)
|
||||
end
|
||||
|
||||
def self.project_migration_enabled?(destination_namespace = nil)
|
||||
if destination_namespace.present?
|
||||
root_ancestor = Namespace.find_by_full_path(destination_namespace)&.root_ancestor
|
||||
|
||||
::Feature.enabled?(:bulk_import_projects, root_ancestor)
|
||||
else
|
||||
::Feature.enabled?(:bulk_import_projects)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -90,13 +90,7 @@ module BulkImports
|
|||
def feature_flag_enabled?
|
||||
destination_namespace = @bulk_import_entity.destination_namespace
|
||||
|
||||
if destination_namespace.present?
|
||||
root_ancestor = Namespace.find_by_full_path(destination_namespace)&.root_ancestor
|
||||
|
||||
::Feature.enabled?(:bulk_import_projects, root_ancestor)
|
||||
else
|
||||
::Feature.enabled?(:bulk_import_projects)
|
||||
end
|
||||
BulkImports::Features.project_migration_enabled?(destination_namespace)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7103,6 +7103,9 @@ msgstr ""
|
|||
msgid "BulkImport|expected an associated Project but has an associated Group"
|
||||
msgstr ""
|
||||
|
||||
msgid "BulkImport|invalid entity source type"
|
||||
msgstr ""
|
||||
|
||||
msgid "BulkImport|must be a group"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -247,10 +247,10 @@ RSpec.describe Import::BulkImportsController do
|
|||
"source_full_path" => "full_path",
|
||||
"destination_slug" => "destination_name",
|
||||
"destination_namespace" => "root" },
|
||||
{ "source_type" => "group_entity2",
|
||||
"source_full_path" => "full_path2",
|
||||
"destination_slug" => "destination_name2",
|
||||
"destination_namespace" => "root" }]
|
||||
{ "source_type" => "group_entity",
|
||||
"source_full_path" => "full_path",
|
||||
"destination_slug" => "destination_name",
|
||||
"destination_namespace" => "invalid-namespace" }]
|
||||
end
|
||||
|
||||
before do
|
||||
|
@ -308,6 +308,21 @@ RSpec.describe Import::BulkImportsController do
|
|||
expect(json_response).to match_array([{ "success" => true, "id" => bulk_import.id, "message" => nil }])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when source type is project' do
|
||||
let(:bulk_import_params) do
|
||||
[{ "source_type" => "project_entity",
|
||||
"source_full_path" => "full_path",
|
||||
"destination_slug" => "destination_name",
|
||||
"destination_namespace" => "root" }]
|
||||
end
|
||||
|
||||
it 'returns 422' do
|
||||
post :create, params: { bulk_import: bulk_import_params }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:unprocessable_entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'IDE user commits changes', :js do
|
||||
include WebIdeSpecHelpers
|
||||
|
||||
let(:project) { create(:project, :public, :repository) }
|
||||
let(:user) { project.first_owner }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vscode_web_ide: false)
|
||||
|
||||
sign_in(user)
|
||||
|
||||
ide_visit(project)
|
||||
end
|
||||
|
||||
it 'user updates nested files' do
|
||||
content = <<~HEREDOC
|
||||
Lorem ipsum
|
||||
Dolar sit
|
||||
Amit
|
||||
HEREDOC
|
||||
|
||||
ide_create_new_file('foo/bar/lorem_ipsum.md', content: content)
|
||||
ide_delete_file('foo/bar/.gitkeep')
|
||||
|
||||
ide_commit
|
||||
|
||||
expect(page).to have_content('All changes are committed')
|
||||
expect(project.repository.blob_at('master', 'foo/bar/.gitkeep')).to be_nil
|
||||
expect(project.repository.blob_at('master', 'foo/bar/lorem_ipsum.md').data).to eql(content)
|
||||
end
|
||||
end
|
|
@ -1,63 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'User creates new blob', :js do
|
||||
include WebIdeSpecHelpers
|
||||
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, :empty_repo) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(vscode_web_ide: false)
|
||||
end
|
||||
|
||||
shared_examples 'creating a file' do
|
||||
it 'allows the user to add a new file in Web IDE' do
|
||||
visit project_path(project)
|
||||
|
||||
click_link 'New file'
|
||||
|
||||
wait_for_requests
|
||||
|
||||
ide_create_new_file('dummy-file', content: "Hello world\n")
|
||||
|
||||
ide_commit
|
||||
|
||||
expect(page).to have_content('All changes are committed')
|
||||
expect(project.repository.blob_at('master', 'dummy-file').data).to eql("Hello world\n")
|
||||
end
|
||||
end
|
||||
|
||||
describe 'as a maintainer' do
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
it_behaves_like 'creating a file'
|
||||
end
|
||||
|
||||
describe 'as an admin' do
|
||||
let(:user) { create(:user, :admin) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
gitlab_enable_admin_mode_sign_in(user)
|
||||
end
|
||||
|
||||
it_behaves_like 'creating a file'
|
||||
end
|
||||
|
||||
describe 'as a developer' do
|
||||
before do
|
||||
project.add_developer(user)
|
||||
sign_in(user)
|
||||
visit project_path(project)
|
||||
end
|
||||
|
||||
it 'does not allow pushing to the default branch' do
|
||||
expect(page).not_to have_content('New file')
|
||||
end
|
||||
end
|
||||
end
|
43
spec/lib/bulk_imports/features_spec.rb
Normal file
43
spec/lib/bulk_imports/features_spec.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe BulkImports::Features do
|
||||
describe '.project_migration_enabled' do
|
||||
let_it_be(:top_level_namespace) { create(:group) }
|
||||
|
||||
context 'when bulk_import_projects feature flag is enabled' do
|
||||
it 'returns true' do
|
||||
stub_feature_flags(bulk_import_projects: true)
|
||||
|
||||
expect(described_class.project_migration_enabled?).to eq(true)
|
||||
end
|
||||
|
||||
context 'when feature flag is enabled on root ancestor level' do
|
||||
it 'returns true' do
|
||||
stub_feature_flags(bulk_import_projects: top_level_namespace)
|
||||
|
||||
expect(described_class.project_migration_enabled?(top_level_namespace.full_path)).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when feature flag is enabled on a different top level namespace' do
|
||||
it 'returns false' do
|
||||
stub_feature_flags(bulk_import_projects: top_level_namespace)
|
||||
|
||||
different_namepace = create(:group)
|
||||
|
||||
expect(described_class.project_migration_enabled?(different_namepace.full_path)).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when bulk_import_projects feature flag is disabled' do
|
||||
it 'returns false' do
|
||||
stub_feature_flags(bulk_import_projects: false)
|
||||
|
||||
expect(described_class.project_migration_enabled?(top_level_namespace.full_path)).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -46,6 +46,8 @@ RSpec.describe BulkImports::Entity, type: :model do
|
|||
end
|
||||
|
||||
it 'is invalid as a project_entity' do
|
||||
stub_feature_flags(bulk_import_projects: true)
|
||||
|
||||
entity = build(:bulk_import_entity, :project_entity, group: build(:group), project: nil)
|
||||
|
||||
expect(entity).not_to be_valid
|
||||
|
@ -55,6 +57,8 @@ RSpec.describe BulkImports::Entity, type: :model do
|
|||
|
||||
context 'when associated with a project and no group' do
|
||||
it 'is valid' do
|
||||
stub_feature_flags(bulk_import_projects: true)
|
||||
|
||||
entity = build(:bulk_import_entity, :project_entity, group: nil, project: build(:project))
|
||||
|
||||
expect(entity).to be_valid
|
||||
|
@ -84,6 +88,8 @@ RSpec.describe BulkImports::Entity, type: :model do
|
|||
|
||||
context 'when the parent is a project import' do
|
||||
it 'is invalid' do
|
||||
stub_feature_flags(bulk_import_projects: true)
|
||||
|
||||
entity = build(:bulk_import_entity, parent: build(:bulk_import_entity, :project_entity))
|
||||
|
||||
expect(entity).not_to be_valid
|
||||
|
@ -124,6 +130,27 @@ RSpec.describe BulkImports::Entity, type: :model do
|
|||
.to include('Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again.')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when bulk_import_projects feature flag is disabled and source_type is a project_entity' do
|
||||
it 'is invalid' do
|
||||
stub_feature_flags(bulk_import_projects: false)
|
||||
|
||||
entity = build(:bulk_import_entity, :project_entity)
|
||||
|
||||
expect(entity).not_to be_valid
|
||||
expect(entity.errors[:base]).to include('invalid entity source type')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when bulk_import_projects feature flag is enabled and source_type is a project_entity' do
|
||||
it 'is valid' do
|
||||
stub_feature_flags(bulk_import_projects: true)
|
||||
|
||||
entity = build(:bulk_import_entity, :project_entity)
|
||||
|
||||
expect(entity).to be_valid
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#encoded_source_full_path' do
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
# ...
|
||||
#
|
||||
# ide_visit(project)
|
||||
# ide_create_new_file('path/to/file.txt', content: 'Lorem ipsum')
|
||||
# ide_commit
|
||||
#
|
||||
module WebIdeSpecHelpers
|
||||
|
@ -40,29 +39,6 @@ module WebIdeSpecHelpers
|
|||
row.matches_css?('.folder.is-open')
|
||||
end
|
||||
|
||||
# Creates a file in the IDE by expanding directories
|
||||
# then using the dropdown next to the parent directory
|
||||
#
|
||||
# - Throws an error if the parent directory is not found
|
||||
def ide_create_new_file(path, content: '')
|
||||
parent_path = path.split('/')[0...-1].join('/')
|
||||
|
||||
container = ide_traverse_to_file(parent_path)
|
||||
|
||||
if container
|
||||
click_file_action(container, 'New file')
|
||||
else
|
||||
ide_tree_actions.click_button('New file')
|
||||
end
|
||||
|
||||
within '#ide-new-entry' do
|
||||
find('input').fill_in(with: path)
|
||||
click_button('Create file')
|
||||
end
|
||||
|
||||
ide_set_editor_value(content)
|
||||
end
|
||||
|
||||
# Deletes a file by traversing to `path`
|
||||
# then clicking the 'Delete' action.
|
||||
#
|
||||
|
|
Loading…
Reference in a new issue