-
Notifications
You must be signed in to change notification settings - Fork 71
Expand file tree
/
Copy pathhandlers.py
More file actions
120 lines (97 loc) · 5.01 KB
/
handlers.py
File metadata and controls
120 lines (97 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
from notebook.utils import url_path_join as ujoin
from notebook.base.handlers import IPythonHandler
import os, json, git, urllib, requests
from git import Repo, GitCommandError
from subprocess import check_output
import subprocess
class GitCommitHandler(IPythonHandler):
def error_and_return(self, dirname, reason):
# send error
self.send_error(500, reason=reason)
# return to directory
os.chdir(dirname)
def put(self):
# git parameters from environment variables
# expand variables since Docker's will pass VAR=$VAL as $VAL without expansion
git_dir = "{}/{}".format(os.path.expandvars(os.environ.get('GIT_PARENT_DIR')), os.path.expandvars(os.environ.get('GIT_REPO_NAME')))
git_url = os.path.expandvars(os.environ.get('GIT_REMOTE_URL'))
git_user = os.path.expandvars(os.environ.get('GIT_USER'))
git_repo_upstream = os.path.expandvars(os.environ.get('GIT_REMOTE_UPSTREAM'))
git_branch = git_remote = os.path.expandvars(os.environ.get('GIT_BRANCH_NAME'))
git_access_token = os.path.expandvars(os.environ.get('GITHUB_ACCESS_TOKEN'))
# get the parent directory for git operations
git_dir_parent = os.path.dirname(git_dir)
# obtain filename and msg for commit
data = json.loads(self.request.body.decode('utf-8'))
filename = urllib.parse.unquote(data['filename'])
msg = data['msg']
commit_only_source = data['commit_only_source']
# get current directory (to return later)
cwd = os.getcwd()
# select branch within repo
try:
os.chdir(git_dir)
dir_repo = check_output(['git','rev-parse','--show-toplevel']).strip()
repo = Repo(dir_repo.decode('utf8'))
except GitCommandError as e:
self.error_and_return(cwd, "Could not checkout repo: {}".format(dir_repo))
return
# create new branch
try:
print(repo.git.checkout('HEAD', b=git_branch))
except GitCommandError:
print("Switching to {}".format(repo.heads[git_branch].checkout()))
# commit current notebook
# client will sent pathname containing git directory; append to git directory's parent
try:
if commit_only_source :
subprocess.run(['jupyter', 'nbconvert', '--to', 'script', str(os.environ.get('GIT_PARENT_DIR') + "/" + os.environ.get('GIT_REPO_NAME') + filename)])
filename = str(os.environ.get('GIT_PARENT_DIR') + "/" + os.environ.get('GIT_REPO_NAME') + filename.replace('ipynb', 'py'))
else:
filename = str(os.environ.get('GIT_PARENT_DIR') + "/" + os.environ.get('GIT_REPO_NAME') + filename)
print(repo.git.add(filename))
print(repo.git.commit( a=False, m="{}\n\nUpdated {}".format(msg, filename) ))
except GitCommandError as e:
print(e)
self.error_and_return(cwd, "Could not commit changes to notebook: {}".format(git_dir_parent + filename))
return
# create or switch to remote
try:
remote = repo.create_remote(git_remote, git_url)
except GitCommandError:
print("Remote {} already exists...".format(git_remote))
remote = repo.remote(git_remote)
# push changes
try:
pushed = remote.push(git_branch)
assert len(pushed)>0
assert pushed[0].flags in [git.remote.PushInfo.UP_TO_DATE, git.remote.PushInfo.FAST_FORWARD, git.remote.PushInfo.NEW_HEAD, git.remote.PushInfo.NEW_TAG]
except GitCommandError as e:
print(e)
self.error_and_return(cwd, "Could not push to remote {}".format(git_remote))
return
except AssertionError as e:
self.error_and_return(cwd, "Could not push to remote {}: {}".format(git_remote, pushed[0].summary))
return
# open pull request
try:
github_url = "https://api.github.com/repos/{}/pulls".format(git_repo_upstream)
github_pr = {
"title":"{} Notebooks".format(git_user),
"body":"IPython notebooks submitted by {}".format(git_user),
"head":"{}:{}".format(git_user, git_remote),
"base":"master"
}
github_headers = {"Authorization": "token {}".format(git_access_token)}
r = requests.post(github_url, data=json.dumps(github_pr), headers=github_headers)
if r.status_code != 201:
print("Error submitting Pull Request to {}".format(git_repo_upstream))
except:
print("Error submitting Pull Request to {}".format(git_repo_upstream))
# return to directory
os.chdir(cwd)
# close connection
self.write({'status': 200, 'statusText': 'Success! Changes to {} captured on branch {} at {}'.format(filename, git_branch, git_url)})
def setup_handlers(nbapp):
route_pattern = ujoin(nbapp.settings['base_url'], '/git/commit')
nbapp.add_handlers('.*', [(route_pattern, GitCommitHandler)])