13
runbot_state_lock = threading.Lock()
18
""" Serve HTTP requests via werkzeug development server.
20
If werkzeug can not be imported, we fall back to wsgiref's simple_server.
22
Calling this function is blocking, you might want to call it in its own
28
interface = '127.0.0.1'
30
import werkzeug.serving
31
httpd = werkzeug.serving.make_server(interface, port, application, threaded=True)
32
print 'HTTP service (werkzeug) running on %s:%s' % (interface, port)
33
except ImportError, e:
34
import wsgiref.simple_server
35
httpd = wsgiref.simple_server.make_server(interface, port, application)
36
print 'HTTP service (wsgiref) running on %s:%s' % (interface, port)
40
def start_server(port):
41
""" Call serve() in its own thread.
43
The WSGI server can be shutdown with stop_server() below.
45
threading.Thread(target=serve,args=(port,)).start()
15
def serve(port, folder):
16
app.run(port=port, extra_files=['../urls.conf'], )
17
print 'HTTP service (Flask) running on port %s' % port
20
def start_server(port, folder):
21
threading.Thread(target=serve,args=(port,folder,)).start()
48
""" Initiate the shutdown of the WSGI server.
50
The server is supposed to have been started by start_server() above.
56
with runbot_state_lock:
58
path = os.path.join('static', 'state.runbot')
59
if os.path.exists(path):
60
with open(path, 'r') as f:
61
state = simplejson.loads(f.read())
62
pxgorunbot.state = state
64
print "Exception in read_state(): ", e
69
path = os.path.join('static', 'state.runbot')
71
with runbot_state_lock:
72
if os.path.exists(path):
73
with open(path, 'r') as h:
74
state = simplejson.loads(h.read())
78
with open(path, 'w') as h:
79
data = simplejson.dumps(state, sort_keys=True, indent=4)
82
# Replace the whole dictionary at once.
83
pxgorunbot.state = state
85
def _stick(team, group):
86
print 'stick', team, group
88
# TODO check team and group are valid
89
state.setdefault(team, {})
90
state[team].setdefault(group, {})
91
state[team][group]['sticky'] = True
94
def _unstick(team, group):
95
print 'unstick', team, group
97
# TODO check team and group are valid
98
state.setdefault(team, {})
99
state[team].setdefault(group, {})
100
if 'sticky' in state[team][group]:
101
del state[team][group]['sticky']
102
if not state[team][group]:
103
del state[team][group]
108
def _build(team, group):
109
print 'build', team, group
110
pxgorunbot.queue.put(('build', (team, group)))
112
def _register_branch(team, project, group):
113
print 'register branch', team, project, group
115
# TODO check team and group are valid
116
state.setdefault('registered-branches', [])
117
state['registered-branches'].append("~%s/%s/%s" % (team, project, group))
120
def _register_project(project):
121
print 'register project'
123
# TODO check project is valid
124
state.setdefault('registered-projects', []) # TODO must be a {}
125
state['registered-projects'].append(project)
128
def _configure_group(project_name=None, name=None, version=None, server_branch=None,
129
client_web_branch=None, web_branch=None, addons_branch_0=None,
130
addons_branch_1=None, addons_branch_2=None, modules=None):
131
print 'configure group'
133
for i in (addons_branch_0, addons_branch_1, addons_branch_2):
135
addons_branches.append(i)
137
# TODO check project is valid
138
state.setdefault('configured-branches', {})
139
state['configured-branches'].setdefault(project_name, {})
140
state['configured-branches'][project_name].setdefault(name, {})
141
state['configured-branches'][project_name][name] = dict(
143
server_branch=server_branch,
144
client_web_branch=client_web_branch,
145
web_branch=web_branch,
146
addons_branches=addons_branches,
152
def application(environ, start_response):
153
def send_notice(message):
154
response = pxgorunbot.templates.render_template('notice.html.mako', message=message)
155
start_response('200 OK', [('Content-Type', 'text/html'), ('Content-Length', str(len(response)))])
158
if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'] == ('/a/branch'):
159
length = int(environ['CONTENT_LENGTH'])
160
data = urllib.unquote(environ['wsgi.input'].read(length))
161
data_ = urlparse.parse_qs(data).get('branch-input',[''])[0]
162
m = pxgorunbot.branch_input_re.match(data_)
164
project_name = m.group(1)
166
branch_name = m.group(3)
167
_register_branch(project_name, project, branch_name)
168
response = data_ + ' is registered. It will be picked by the Runbot at the next build iteration (about every two minutes).'
169
return send_notice(response)
171
if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'] == ('/a/project'):
172
length = int(environ['CONTENT_LENGTH'])
173
data = urllib.unquote(environ['wsgi.input'].read(length))
174
data_ = urlparse.parse_qs(data).get('project-input',[''])[0]
176
_register_project(data_)
177
response = data_ + ' is registered. It will be picked by the Runbot at the next build iteration (about every two minutes).'
178
return send_notice(response)
180
if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'] == ('/a/configure-build'):
181
length = int(environ['CONTENT_LENGTH'])
182
data = urllib.unquote(environ['wsgi.input'].read(length))
185
"project_name", "name", "version", "server_branch",
186
"client_web_branch", "web_branch",
187
"addons_branch_0", "addons_branch_1", "addons_branch_2", "modules"):
188
data_[n] = urlparse.parse_qs(data).get(n,[''])[0]
189
if (data_['version'] == 'trunk' or data_['version'] == '6.0') and \
190
data_['project_name'] and \
192
data_['server_branch'] and \
193
(data_['web_branch'] or data_['client_web_branch']) and \
194
data_['addons_branch_0']:
195
_configure_group(**data_)
196
response = data_['name'] + ' is registered. It will be picked by the Runbot at the next build iteration (about every two minutes).'
197
return send_notice(response)
199
# TODO must be a POST instead of a GET
200
if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'] == ('/a'):
201
query = urlparse.parse_qs(environ['QUERY_STRING'])
203
if query.get('project'):
204
project = query['project'][0]
206
if query.get('build'):
207
group = query['build'][0]
208
_build(project, group)
209
response = '`' + group + '` will be built.'
210
return send_notice(response)
212
message = 'Are you lost?\n\n\n(^____^)\n'
213
response = pxgorunbot.templates.render_template('notice.html.mako', message=message)
214
start_response('404 Not Found', [('Content-Type', 'text/html'), ('Content-Length', str(len(response)))])
217
if __name__ == '__main__':