Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Henrik Skov Midtiby
gitlab-assignment-handler
Commits
71d13a77
Commit
71d13a77
authored
Dec 19, 2019
by
Henrik Dyrberg Egemose
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
made it into a package
parent
7cf1f479
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
235 additions
and
17 deletions
+235
-17
gitlab_class_helper/__init__.py
gitlab_class_helper/__init__.py
+1
-0
gitlab_class_helper/gitlab_class_helper.py
gitlab_class_helper/gitlab_class_helper.py
+201
-0
misc/example_use_case.txt
misc/example_use_case.txt
+17
-17
requirements.txt
requirements.txt
+1
-0
setup.py
setup.py
+15
-0
No files found.
gitlab_class_helper/__init__.py
0 → 100644
View file @
71d13a77
from
gitlab_class_helper.gitlab_class_helper
import
GitlabClassHelper
gitlab_class_helper/gitlab_class_helper.py
0 → 100644
View file @
71d13a77
import
os
import
requests
import
git
import
simplejson
from
typing
import
List
class
GitlabClassHelper
:
def
__init__
(
self
,
url
:
str
,
access_token
:
str
):
self
.
path
=
url
self
.
headers
=
{
'Authorization'
:
'Bearer {}'
.
format
(
access_token
)}
self
.
check_connection
()
self
.
group_id
=
None
def
check_connection
(
self
):
url
=
self
.
path
+
'/projects'
resp
=
requests
.
get
(
url
,
self
.
headers
)
if
resp
.
status_code
==
401
:
raise
requests
.
HTTPError
(
'Personal access token is invalid. %s'
%
resp
.
text
)
elif
resp
.
ok
:
try
:
resp
.
json
()
print
(
'Initialized connection to gitlab instance.'
)
print
(
'Personal access token works.'
)
except
simplejson
.
errors
.
JSONDecodeError
:
raise
requests
.
HTTPError
(
'Bad request. Possible the url is wrong.'
)
else
:
raise
requests
.
HTTPError
(
'Bad request. %s'
%
resp
.
text
)
def
create_class
(
self
,
group_name
:
str
,
id_of_parent_group
:
int
)
->
int
:
"""
Create a new group with group_name as a subgroup of that parent with id id_of_parent_group
returns the new groups id
"""
group_path
=
''
.
join
(
e
if
e
.
isalnum
()
else
'-'
for
e
in
group_name
)
url
=
self
.
path
+
'/groups?name=%s&path=%s&parent_id=%d&visibility=private'
%
(
group_name
,
group_path
,
id_of_parent_group
)
resp
=
requests
.
post
(
url
,
headers
=
self
.
headers
)
if
resp
.
ok
:
idx
=
resp
.
json
()[
'id'
]
self
.
group_id
=
idx
web_url
=
resp
.
json
()[
'web_url'
]
print
(
'Created the "%s" group in gitlab.'
%
group_name
)
print
(
'web_url to the group: %s'
%
web_url
)
print
(
'Id of the group: %d'
%
idx
)
print
(
'Working in this group now.'
)
return
idx
else
:
raise
requests
.
HTTPError
(
'%s for url: %s'
%
(
resp
.
json
()[
'message'
],
url
))
def
create_assignment_repositories
(
self
,
repositories
:
List
[
str
],
group_id
:
int
=
None
):
"""
Create repositories in working group or in the group with group_id if supplied.
"""
use_group_id
,
group_name
=
self
.
check_group_id
(
group_id
)
for
repo
in
set
(
repositories
):
self
.
create_repo
(
repo
,
use_group_id
,
group_name
)
def
create_repo
(
self
,
repo_name
:
str
,
group_id
:
int
,
group_name
:
str
):
"""
Create a repository in the group with id
"""
url
=
'/projects?name=%s&namespace_id=%d'
%
(
repo_name
,
group_id
)
resp
=
requests
.
post
(
url
,
headers
=
self
.
headers
)
if
resp
.
ok
:
print
(
'Created project "%s" in "%s".'
%
(
repo_name
,
group_name
))
else
:
raise
requests
.
HTTPError
(
'%s for url: %s'
%
(
resp
.
json
()[
'message'
],
url
))
def
get_group_name
(
self
,
group_id
:
int
)
->
str
:
"""
Get the name of a group with id.
"""
url
=
self
.
path
+
'/groups/%d'
%
group_id
resp
=
requests
.
get
(
url
,
headers
=
self
.
headers
)
if
resp
.
ok
:
return
resp
.
json
()[
'name'
]
else
:
raise
requests
.
HTTPError
(
'%s for url: %s'
%
(
resp
.
json
()[
'message'
],
url
))
def
add_students_to_repositories
(
self
,
repositories
:
List
[
str
],
user_ids
:
List
[
int
],
group_id
:
int
=
None
):
"""
Give developer access rights to user in repository.
"""
use_group_id
,
_
=
self
.
check_group_id
(
group_id
)
for
repo
,
user_id
in
zip
(
repositories
,
user_ids
):
repo_id
=
self
.
get_repo_id
(
repo
,
use_group_id
)
self
.
add_user_to_repo
(
repo_id
,
user_id
,
repo
)
def
check_group_id
(
self
,
group_id
):
if
not
group_id
and
not
self
.
group_id
:
raise
AttributeError
(
'group_id must be supplied if not working in a group'
)
use_group_id
=
group_id
if
group_id
else
self
.
group_id
group_name
=
self
.
get_group_name
(
use_group_id
)
print
(
'Working in group: %d - %s'
%
(
use_group_id
,
group_name
))
return
use_group_id
,
group_name
def
get_repo_id
(
self
,
repo_name
:
str
,
group_id
:
int
)
->
int
:
"""
Get repository id from name
"""
url
=
self
.
path
+
'/groups/%d/projects?search=%s'
%
(
group_id
,
repo_name
)
resp
=
requests
.
get
(
url
,
headers
=
self
.
headers
)
if
resp
.
ok
:
if
len
(
resp
.
json
())
==
1
:
return
resp
.
json
()[
0
][
'id'
]
else
:
raise
NameError
(
'%d projects found in group: %d when searching on %s'
%
(
len
(
resp
.
json
()),
group_id
,
repo_name
))
else
:
raise
requests
.
HTTPError
(
'%s for url: %s'
%
(
resp
.
json
()[
'message'
],
url
))
def
add_user_to_repo
(
self
,
repo_id
:
int
,
user_id
:
int
,
repo_name
:
str
):
"""
Add user to given repository
"""
url
=
'/projects/%d/members?user_id=%d&access_level=30'
%
(
repo_id
,
user_id
)
resp
=
requests
.
post
(
url
,
headers
=
self
.
headers
)
if
resp
.
ok
:
print
(
'Added "%d" to the project "%s".'
%
(
user_id
,
repo_name
))
else
:
raise
requests
.
HTTPError
(
'%s for url: %s'
%
(
resp
.
json
()[
'message'
],
url
))
def
push_git_repo_to_repositories
(
self
,
local_path
:
str
,
repositories
:
List
[
str
],
group_id
:
int
=
None
):
"""
Push local repository to list of remote repositories
"""
use_group_id
,
_
=
self
.
check_group_id
(
group_id
)
for
repo
in
repositories
:
repo_id
=
self
.
get_repo_id
(
repo
,
use_group_id
)
self
.
push_git_repository_content_to_project
(
local_path
,
repo_id
)
print
(
'Pushed git repo "%s" to "%s"'
%
(
local_path
,
repo
))
def
push_git_repository_content_to_project
(
self
,
path_to_git_repository
:
str
,
project_id
:
int
):
"""
Push the local git repository located at "path_to_git_repository" to the project.
"""
repo
=
git
.
Repo
(
path_to_git_repository
)
ssh_url_to_git_repo
=
self
.
get_project_ssh_url
(
project_id
)
repo
.
git
.
push
(
ssh_url_to_git_repo
,
'master'
)
def
get_project_ssh_url
(
self
,
project_id
:
int
)
->
str
:
"""
Fetch project ssh url
"""
url
=
self
.
path
+
"/projects/%d"
%
project_id
resp
=
requests
.
get
(
url
,
headers
=
self
.
headers
)
if
resp
.
ok
:
return
resp
.
json
()[
'ssh_url_to_repo'
]
else
:
raise
requests
.
HTTPError
(
'%s for url: %s'
%
(
resp
.
json
()[
'message'
],
url
))
def
enter_class
(
self
,
group_name
:
str
,
id_of_parent_group
:
int
)
->
int
:
"""
Entering group_name as a subgroup of that parent as the new working group
returns the new groups id
"""
url
=
self
.
path
+
'/groups/%d/subgroups?search=%s'
%
(
id_of_parent_group
,
group_name
)
resp
=
requests
.
get
(
url
,
headers
=
self
.
headers
)
if
resp
.
ok
:
if
len
(
resp
.
json
())
==
1
:
idx
=
resp
.
json
()[
0
][
'id'
]
self
.
group_id
=
idx
web_url
=
resp
.
json
()[
'web_url'
]
print
(
'Entering the "%s" group in gitlab.'
%
group_name
)
print
(
'web_url to the group: %s'
%
web_url
)
print
(
'Id of the group: %d'
%
idx
)
print
(
'Working in this group now.'
)
return
idx
else
:
raise
NameError
(
'%d groups found in group: %d when searching on %s'
%
(
len
(
resp
.
json
()),
id_of_parent_group
,
group_name
))
else
:
raise
requests
.
HTTPError
(
'%s for url: %s'
%
(
resp
.
json
()[
'message'
],
url
))
def
clone_repositories
(
self
,
repositories
:
List
[
str
],
local_path_to_fetch_to
:
str
,
group_id
:
int
=
None
):
"""
Clone all repositories in "repositories" to the local path "local_path_to_fetch_to"
"""
use_group_id
,
_
=
self
.
check_group_id
(
group_id
)
for
repo
in
repositories
:
repo_id
=
self
.
get_repo_id
(
repo
,
use_group_id
)
self
.
clone_repo
(
local_path_to_fetch_to
,
repo_id
)
print
(
'Cloned the repository "%s" to "%s"'
%
(
repo
,
local_path_to_fetch_to
))
def
clone_repo
(
self
,
local_folder
:
str
,
project_id
:
int
):
"""
Clone the project into the local folder
"""
ssh_url_to_git_repo
=
self
.
get_project_ssh_url
(
project_id
)
git
.
Repo
.
clone_from
(
ssh_url_to_git_repo
,
local_folder
)
def
push_repositories
(
self
,
repositories
:
List
[
str
],
local_path
:
str
,
group_id
:
int
=
None
):
"""
Push repositories to remotes.
"""
use_group_id
,
_
=
self
.
check_group_id
(
group_id
)
for
repo
in
repositories
:
repo_id
=
self
.
get_repo_id
(
repo
,
use_group_id
)
path_to_repo
=
os
.
path
.
join
(
local_path
,
repo
)
self
.
push_git_repository_content_to_project
(
path_to_repo
,
repo_id
)
print
(
'Pushed the repository "%s" to "%s"'
%
(
path_to_repo
,
repo
))
misc/example_use_case.txt
View file @
71d13a77
...
...
@@ -12,31 +12,31 @@ $ python
Python 3.x.x ...
>>> import config
>>> import pandas as pd
>>> from gitlab_class_helper import
*
>>>
start_g
itlab
_c
lass
_h
elper("source.coderefinery.org", config.public_access_token)
>>> from gitlab_class_helper import
GitlabClassHelper
>>>
class_helper = G
itlab
C
lass
H
elper("source.coderefinery.org", config.public_access_token)
Initialized connection to gitlab instance.
Personal access token works.
>>> c
reate_gitlab
_class(
>>> c
lass_helper.create
_class(
group_name = "test-rmurv2",
id_of_parent_group = x)
Created the "test-rmurv2" group in gitlab.
Full path to the group: xxxxxxxxxx.
Id of the group: 123.
>>> list_of_repo_names = pd.read_csv("assignment1.csv")
>>> create_assignment_repositories(
>>>
class_helper.
create_assignment_repositories(
repositories = list_of_repo_names['repository'],
group_id = 123)
Working in group: 123 - "test-rmurv2".
Created project "hw1-adam" in "test-rmurv2".
Created project "hw1-birger" in "test-rmurv2".
>>> add_students_to_repositories(
>>>
class_helper.
add_students_to_repositories(
repositories = list_of_repo_names['repository'],
user_ids = list_of_repo_names['userid'],
group_id = 123)
Working in group: 123 - "test-rmurv2".
Added "adam_id" to the project "hw1-adam".
Added "birger_id" to the project "hw1-birger".
>>> push_git_repo_to_repositories(
>>>
class_helper.
push_git_repo_to_repositories(
local_path = "hw1",
repositories = list_of_repo_names['repository'],
group = 123)
...
...
@@ -51,25 +51,25 @@ $ python
Python 3.x.x ...
>>> import config
>>> import pandas as pd
>>> from gitlab_class_helper import
*
>>>
start_g
itlab
_c
lass
_h
elper("source.coderefinery.org", config.public_access_token)
>>> from gitlab_class_helper import
GitlabClassHelper
>>>
class_helper = G
itlab
C
lass
H
elper("source.coderefinery.org", config.public_access_token)
Initialized connection to gitlab instance.
Personal access token works.
>>> enter_gitlab_class(
>>>
class_helper.
enter_gitlab_class(
group_name = "test-rmurv2",
id_of_parent_group = x)
Entered the "test-rmurv2" group in gitlab.
Full path to the group: xxxxxxxxxx.
Id of the group: 123.
>>> list_of_repo_names = pd.read_csv("assignment1.csv")
>>> clone_repositories(
>>>
class_helper.
clone_repositories(
repositories = list_of_repo_names['repositories'],
local_path_to_fetch_to = "assignment1/studentresponses/")
Working in group: 123 - "test-rmurv2".
Cloned the repository "hw1-adam" to "assignment1/studentresponses/hw1-adam".
Cloned the repository "hw1-birger" to "assignment1/studentresponses/hw1-birger".
>>> # Grade assignments / provide feedback.
>>> push_repositories(
>>>
class_helper.
push_repositories(
repositories = list_of_repo_names['repositories'],
local_path_to_fetch_to = "assignment1/studentresponses/")
Working in group: 123 - "test-rmurv2".
...
...
@@ -89,30 +89,30 @@ $ python
Python 3.x.x ...
>>> import config
>>> import pandas as pd
>>> from gitlab_class_helper import
*
>>>
start_g
itlab
_c
lass
_h
elper("source.coderefinery.org", config.public_access_token)
>>> from gitlab_class_helper import
GitlabClassHelper
>>>
class_helper = G
itlab
C
lass
H
elper("source.coderefinery.org", config.public_access_token)
Initialized connection to gitlab instance.
Personal access token works.
>>> enter_gitlab_class(
>>>
class_helper.
enter_gitlab_class(
group_name = "test-rmurv2",
id_of_parent_group = x)
Entered the "test-rmurv2" group in gitlab.
Full path to the group: xxxxxxxxxx.
Id of the group: 123.
>>> list_of_repo_names = pd.read_csv("assignment2.csv")
>>> create_assignment_repositories(
>>>
class_helper.
create_assignment_repositories(
repositories = list_of_repo_names['repository'],
group_id = 123)
Working in group: 123 - "test-rmurv2".
Created project "hw2-group" in "test-rmurv2".
>>> add_students_to_repositories(
>>>
class_helper.
add_students_to_repositories(
repositories = list_of_repo_names['repository'],
user_ids = list_of_repo_names['userid'],
group_id = 123)
Working in group: 123 - "test-rmurv2".
Added "adam_id" to the project "hw2-group".
Added "birger_id" to the project "hw2-group".
>>> push_git_repo_to_repositories(
>>>
class_helper.
push_git_repo_to_repositories(
local_path = "hw2",
repositories = list_of_repo_names['repository'],
group = 123)
...
...
requirements.txt
View file @
71d13a77
requests
gitpython
simplejson
\ No newline at end of file
setup.py
0 → 100644
View file @
71d13a77
from
setuptools
import
setup
setup
(
name
=
'gitlab_class_helper'
,
version
=
'0.1'
,
description
=
'A package to create assignments for students on gitlab'
,
url
=
''
,
author
=
'Henrik Dyrberg Egemose'
,
author_email
=
'hes1990@gmail.com'
,
packages
=
[
'gitlab_class_helper'
],
install_requires
=
[
'requests'
,
'gitpython'
,
'simplejson'
,
],
zip_safe
=
False
)
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