Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
gitlab-ce
Commits
1e2bd853
Commit
1e2bd853
authored
Jan 17, 2019
by
Ben
Committed by
Dmitriy Zaporozhets
Jan 17, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
API for importing external repos
parent
f598daf2
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
230 additions
and
20 deletions
+230
-20
app/controllers/import/base_controller.rb
app/controllers/import/base_controller.rb
+2
-0
app/controllers/import/github_controller.rb
app/controllers/import/github_controller.rb
+9
-20
app/services/import/base_service.rb
app/services/import/base_service.rb
+35
-0
app/services/import/github_service.rb
app/services/import/github_service.rb
+48
-0
doc/api/import.md
doc/api/import.md
+33
-0
lib/api/api.rb
lib/api/api.rb
+1
-0
lib/api/import_github.rb
lib/api/import_github.rb
+46
-0
spec/requests/api/import_github_spec.rb
spec/requests/api/import_github_spec.rb
+56
-0
No files found.
app/controllers/import/base_controller.rb
View file @
1e2bd853
...
...
@@ -18,6 +18,7 @@ class Import::BaseController < ApplicationController
end
# rubocop: enable CodeReuse/ActiveRecord
# deprecated: being replaced by app/services/import/base_service.rb
def
find_or_create_namespace
(
names
,
owner
)
names
=
params
[
:target_namespace
].
presence
||
names
...
...
@@ -32,6 +33,7 @@ class Import::BaseController < ApplicationController
current_user
.
namespace
end
# deprecated: being replaced by app/services/import/base_service.rb
def
project_save_error
(
project
)
project
.
errors
.
full_messages
.
join
(
', '
)
end
...
...
app/controllers/import/github_controller.rb
View file @
1e2bd853
...
...
@@ -39,28 +39,21 @@ class Import::GithubController < Import::BaseController
end
def
create
repo
=
client
.
repo
(
params
[
:repo_id
].
to_i
)
project_name
=
params
[
:new_name
].
presence
||
repo
.
name
namespace_path
=
params
[
:target_namespace
].
presence
||
current_user
.
namespace_path
target_namespace
=
find_or_create_namespace
(
namespace_path
,
current_user
.
namespace_path
)
if
can?
(
current_user
,
:create_projects
,
target_namespace
)
project
=
Gitlab
::
LegacyGithubImport
::
ProjectCreator
.
new
(
repo
,
project_name
,
target_namespace
,
current_user
,
access_params
,
type:
provider
)
.
execute
(
extra_project_attrs
)
if
project
.
persisted?
render
json:
ProjectSerializer
.
new
.
represent
(
project
)
else
render
json:
{
errors:
project_save_error
(
project
)
},
status: :unprocessable_entity
end
result
=
Import
::
GithubService
.
new
(
client
,
current_user
,
import_params
).
execute
(
access_params
,
provider
)
if
result
[
:status
]
==
:success
render
json:
ProjectSerializer
.
new
.
represent
(
result
[
:project
])
else
render
json:
{
errors:
'This namespace has already been taken! Please choose another one.'
},
status: :unprocessable_entity
render
json:
{
errors:
result
[
:message
]
},
status:
result
[
:http_status
]
end
end
private
def
import_params
params
.
permit
(
:repo_id
,
:new_name
,
:target_namespace
)
end
def
client
@client
||=
Gitlab
::
LegacyGithubImport
::
Client
.
new
(
session
[
access_token_key
],
client_options
)
end
...
...
@@ -124,10 +117,6 @@ class Import::GithubController < Import::BaseController
{}
end
def
extra_project_attrs
{}
end
def
extra_import_params
{}
end
...
...
app/services/import/base_service.rb
0 → 100644
View file @
1e2bd853
# frozen_string_literal: true
module
Import
class
BaseService
<
::
BaseService
def
initialize
(
client
,
user
,
params
)
@client
=
client
@current_user
=
user
@params
=
params
end
private
def
find_or_create_namespace
(
namespace
,
owner
)
namespace
=
params
[
:target_namespace
].
presence
||
namespace
return
current_user
.
namespace
if
namespace
==
owner
group
=
Groups
::
NestedCreateService
.
new
(
current_user
,
group_path:
namespace
).
execute
group
.
errors
.
any?
?
current_user
.
namespace
:
group
rescue
=>
e
Gitlab
::
AppLogger
.
error
(
e
)
current_user
.
namespace
end
def
project_save_error
(
project
)
project
.
errors
.
full_messages
.
join
(
', '
)
end
def
success
(
project
)
super
().
merge
(
project:
project
,
status: :success
)
end
end
end
app/services/import/github_service.rb
0 → 100644
View file @
1e2bd853
# frozen_string_literal: true
module
Import
class
GithubService
<
Import
::
BaseService
attr_accessor
:client
attr_reader
:params
,
:current_user
def
execute
(
access_params
,
provider
)
unless
authorized?
return
error
(
'This namespace has already been taken! Please choose another one.'
,
:unprocessable_entity
)
end
project
=
Gitlab
::
LegacyGithubImport
::
ProjectCreator
.
new
(
repo
,
project_name
,
target_namespace
,
current_user
,
access_params
,
type:
provider
)
.
execute
(
extra_project_attrs
)
if
project
.
persisted?
success
(
project
)
else
error
(
project_save_error
(
project
),
:unprocessable_entity
)
end
end
def
repo
@repo
||=
client
.
repo
(
params
[
:repo_id
].
to_i
)
end
def
project_name
@project_name
||=
params
[
:new_name
].
presence
||
repo
.
name
end
def
namespace_path
@namespace_path
||=
params
[
:target_namespace
].
presence
||
current_user
.
namespace_path
end
def
target_namespace
@target_namespace
||=
find_or_create_namespace
(
namespace_path
,
current_user
.
namespace_path
)
end
def
extra_project_attrs
{}
end
def
authorized?
can?
(
current_user
,
:create_projects
,
target_namespace
)
end
end
end
doc/api/import.md
0 → 100644
View file @
1e2bd853
# Import API
## Import repository from GitHub
Import your projects from GitHub to GitLab via the API.
```
POST /import/github
```
| Attribute | Type | Required | Description |
|------------|---------|----------|---------------------|
|
`personal_access_token`
| string | yes | GitHub personal access token |
|
`repo_id`
| integer | yes | GitHub repository ID |
|
`new_name`
| string | no | New repo name |
|
`target_namespace`
| string | yes | Namespace to import repo into |
```
bash
curl
--request
POST
--header
"PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK"
--data
"personal_access_token=abc123&repo_id=12345&target_namespace=root"
https://gitlab.example.com/api/v4/import/github
```
Example response:
```
json
{
"id"
:
27
,
"name"
:
"my-repo"
,
"full_path"
:
"/root/my-repo"
,
"full_name"
:
"Administrator / my-repo"
}
```
lib/api/api.rb
View file @
1e2bd853
...
...
@@ -110,6 +110,7 @@ module API
mount
::
API
::
GroupMilestones
mount
::
API
::
Groups
mount
::
API
::
GroupVariables
mount
::
API
::
ImportGithub
mount
::
API
::
Internal
mount
::
API
::
Issues
mount
::
API
::
JobArtifacts
...
...
lib/api/import_github.rb
0 → 100644
View file @
1e2bd853
# frozen_string_literal: true
module
API
class
ImportGithub
<
Grape
::
API
rescue_from
Octokit
::
Unauthorized
,
with: :provider_unauthorized
helpers
do
def
client
@client
||=
Gitlab
::
LegacyGithubImport
::
Client
.
new
(
params
[
:personal_access_token
],
client_options
)
end
def
access_params
{
github_access_token:
params
[
:personal_access_token
]
}
end
def
client_options
{}
end
def
provider
:github
end
end
desc
'Import a GitHub project'
do
detail
'This feature was introduced in GitLab 11.3.4.'
success
Entities
::
ProjectEntity
end
params
do
requires
:personal_access_token
,
type:
String
,
desc:
'GitHub personal access token'
requires
:repo_id
,
type:
Integer
,
desc:
'GitHub repository ID'
optional
:new_name
,
type:
String
,
desc:
'New repo name'
requires
:target_namespace
,
type:
String
,
desc:
'Namespace to import repo into'
end
post
'import/github'
do
result
=
Import
::
GithubService
.
new
(
client
,
current_user
,
params
).
execute
(
access_params
,
provider
)
if
result
[
:status
]
==
:success
present
ProjectSerializer
.
new
.
represent
(
result
[
:project
])
else
status
result
[
:http_status
]
{
errors:
result
[
:message
]
}
end
end
end
end
spec/requests/api/import_github_spec.rb
0 → 100644
View file @
1e2bd853
require
'spec_helper'
describe
API
::
ImportGithub
do
include
ApiHelpers
let
(
:token
)
{
"asdasd12345"
}
let
(
:provider
)
{
:github
}
let
(
:access_params
)
{
{
github_access_token:
token
}
}
describe
"POST /import/github"
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:provider_username
)
{
user
.
username
}
let
(
:provider_user
)
{
OpenStruct
.
new
(
login:
provider_username
)
}
let
(
:provider_repo
)
do
OpenStruct
.
new
(
name:
'vim'
,
full_name:
"
#{
provider_username
}
/vim"
,
owner:
OpenStruct
.
new
(
login:
provider_username
)
)
end
before
do
Grape
::
Endpoint
.
before_each
do
|
endpoint
|
allow
(
endpoint
).
to
receive
(
:client
).
and_return
(
double
(
'client'
,
user:
provider_user
,
repo:
provider_repo
).
as_null_object
)
end
end
it
'returns 201 response when the project is imported successfully'
do
allow
(
Gitlab
::
LegacyGithubImport
::
ProjectCreator
)
.
to
receive
(
:new
).
with
(
provider_repo
,
provider_repo
.
name
,
user
.
namespace
,
user
,
access_params
,
type:
provider
)
.
and_return
(
double
(
execute:
project
))
post
api
(
"/import/github"
,
user
),
params:
{
target_namespace:
user
.
namespace_path
,
personal_access_token:
token
,
repo_id:
1234
}
expect
(
response
).
to
have_gitlab_http_status
(
201
)
expect
(
json_response
).
to
be_a
Hash
expect
(
json_response
[
'name'
]).
to
eq
(
project
.
name
)
end
it
'returns 422 response when user can not create projects in the chosen namespace'
do
other_namespace
=
create
(
:group
,
name:
'other_namespace'
)
post
api
(
"/import/github"
,
user
),
params:
{
target_namespace:
other_namespace
.
name
,
personal_access_token:
token
,
repo_id:
1234
}
expect
(
response
).
to
have_gitlab_http_status
(
422
)
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment