Skip to content

Commit aa4d41b

Browse files
author
Andrew Tergis
committed
feat: add support for /import/github
Addresses #952 This adds a method to the `ProjectManager` called `import_github`, which maps to the `/import/github` API endpoint. Calling `import_github` will trigger an import operation from <repo_id> into <target_namespace>, using <personal_access_token> to authenticate against github. In practice a gitlab server may take many 10's of seconds to respond to this API call, so we also take the liberty of increasing the default timeout (only for this method invocation). Unfortunately since `import` is a protected keyword in python, I was unable to follow the endpoint structure with the manager namespace. I'm open to suggestions on a more sensible interface. I'm successfully using this addition to batch-import hundreds of github repositories into gitlab.
1 parent 61eaad2 commit aa4d41b

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

gitlab/tests/test_gitlab.py

+27
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,33 @@ def resp_update_submodule(url, request):
844844
self.assertEqual(ret["message"], "Message")
845845
self.assertEqual(ret["id"], "ed899a2f4b50b4370feeea94676502b42383c746")
846846

847+
def test_import_github(self):
848+
@urlmatch(
849+
scheme="http",
850+
netloc="localhost",
851+
path="/api/v4/import/github",
852+
method="post",
853+
)
854+
def resp_import_github(url, request):
855+
headers = {"content-type": "application/json"}
856+
content = """{
857+
"id": 27,
858+
"name": "my-repo",
859+
"full_path": "/root/my-repo",
860+
"full_name": "Administrator / my-repo"
861+
}"""
862+
content = content.encode("utf-8")
863+
return response(200, content, headers, None, 25, request)
864+
865+
with HTTMock(resp_import_github):
866+
base_path = "/root"
867+
name = "my-repo"
868+
ret = self.gl.projects.import_github("githubkey", 1234, base_path, name)
869+
self.assertIsInstance(ret, dict)
870+
self.assertEqual(ret["name"], name)
871+
self.assertEqual(ret["full_path"], "/".join((base_path, name)))
872+
self.assertTrue(ret["full_name"].endswith(name))
873+
847874
def _default_config(self):
848875
fd, temp_path = tempfile.mkstemp()
849876
os.write(fd, valid_config)

gitlab/v4/objects.py

+63
Original file line numberDiff line numberDiff line change
@@ -4744,6 +4744,69 @@ def import_project(
47444744
"/projects/import", post_data=data, files=files, **kwargs
47454745
)
47464746

4747+
def import_github(
4748+
self,
4749+
personal_access_token,
4750+
repo_id,
4751+
target_namespace,
4752+
new_name=None,
4753+
timeout_override=60.0,
4754+
**kwargs
4755+
):
4756+
"""Import a project from Github to Gitlab (schedule the import)
4757+
4758+
This method will return when an import operation has been safely queued,
4759+
or an error has occurred. After triggering an import, check the
4760+
`import_status` of the newly created project to detect when the import
4761+
operation has completed.
4762+
4763+
NOTE: this request may take longer than most other API requests.
4764+
So this method will override the session timeout with <timeout_override>,
4765+
which defaults to 60 seconds.
4766+
4767+
Args:
4768+
personal_access_token (str): GitHub personal access token
4769+
repo_id (int): Github repository ID
4770+
target_namespace (str): Namespace to import repo into
4771+
new_name (str): New repo name (Optional)
4772+
timeout_override (int or float): Timeout to use for this request
4773+
**kwargs: Extra options to send to the server (e.g. sudo)
4774+
4775+
Raises:
4776+
GitlabAuthenticationError: If authentication is not correct
4777+
GitlabListError: If the server failed to perform the request
4778+
4779+
Returns:
4780+
dict: A representation of the import status.
4781+
4782+
Example:
4783+
```
4784+
gl = gitlab.Gitlab_from_config()
4785+
print "Triggering import"
4786+
result = gl.projects.import_github(ACCESS_TOKEN,
4787+
123456,
4788+
"my-group/my-subgroup")
4789+
project = gl.projects.get(ret['id'])
4790+
print "Waiting for import to complete"
4791+
while project.import_status == u'started':
4792+
time.sleep(1.0)
4793+
project = gl.projects.get(project.id)
4794+
print "Github import complete"
4795+
```
4796+
"""
4797+
data = {
4798+
"personal_access_token": personal_access_token,
4799+
"repo_id": repo_id,
4800+
"target_namespace": target_namespace,
4801+
}
4802+
if new_name:
4803+
data["new_name"] = new_name
4804+
prev_timeout = self.gitlab.timeout
4805+
self.gitlab.timeout = timeout_override
4806+
result = self.gitlab.http_post("/import/github", post_data=data, **kwargs)
4807+
self.gitlab.timeout = prev_timeout
4808+
return result
4809+
47474810

47484811
class RunnerJob(RESTObject):
47494812
pass

0 commit comments

Comments
 (0)